好書一起讀(117):重學(xué)Spring之表現(xiàn)層方法

關(guān)于Spring MVC的使用,事實上已足夠簡單,《Spring 3.x企業(yè)應(yīng)用開發(fā)實戰(zhàn)》和《Spring實戰(zhàn)》也說得足夠好,尤其是前者。不多說。聊聊表現(xiàn)層的話題吧,如對本篇內(nèi)容感興趣,請讀《Struts2技術(shù)內(nèi)幕》,是的,你沒看錯,一個我自己都不再推薦使用的框架,我也當(dāng)然不會為它寫一篇,但這書,值得讀,當(dāng)年曾震得我驚如天人。

說到表現(xiàn)層,繞不過MVC。

落花散人《老子集注》:

在無數(shù)凡夫俗子的喋喋不休之下,大圣人原本清晰的概念變得模糊不清!

這是一切流行詞語的宿命:它太流行了,就無論什么人都來說一番,說來說去概念就不清了。

所以討論之前做出以下設(shè)定:

1.本文中說的模型,指的是一種有狀態(tài)無行為的對象,是用于承載業(yè)務(wù)邏輯結(jié)果數(shù)據(jù),準(zhǔn)備被渲染成頁面的東西,其后綴,可能是entity/bean/dto/vo等。

2.本文中說的頁面,指的是模型被灌到模板中后渲染出的結(jié)果,一般情況下是個html片段(也包括ajax或rest api的json響應(yīng),但不是本文重點)。

3.本文中說的控制器,指的是請求進(jìn)、響應(yīng)出的黑箱中,最上層的那個東西,負(fù)責(zé)接收請求和給出響應(yīng),但具體業(yè)務(wù)邏輯它交給業(yè)務(wù)層去處理。

4.本文中說的模板,指的是定義了頁面格式的那個東西,可能是標(biāo)簽化的jsp或freemarker文件等。

5.本文中說的請求,指的是HttpServletRequest表示的網(wǎng)絡(luò)請求,主要關(guān)注點包括路徑和參數(shù)。

6.本文中說的響應(yīng),指的是HttpServletResponse表示的網(wǎng)絡(luò)響應(yīng),性質(zhì)為把頁面給還到瀏覽器(也包括給還到其他http請求發(fā)起者,如移動端的rest請求,但不是本文重點)。

概念都很容易理解,那就從控制器具體說說。

這是上面少有的沒有舉例的東西,因為它的工作職責(zé)最多。

還是把它拆開看吧,既然「請求進(jìn)響應(yīng)出」,而「請求的主要關(guān)注點是路徑和參數(shù)」,那控制器就該承擔(dān)兩個職責(zé):

1)處理路徑

2)處理參數(shù)

處理路徑在實踐中常常就是:

1)把這個路徑的請求,映射給哪個方法?

——在servlet里是servlet-mapping,在種種框架中就是xml或annotation或約定優(yōu)于配置的設(shè)定。

2)把該方法的結(jié)果,灌裝到哪個模板,來生成結(jié)果頁面?

——在servlet里是forward,在種種框架里還是xml或annotation或約定優(yōu)于配置的設(shè)定。

處理參數(shù)在實踐中常常就是:

1)怎樣想辦法盡量簡單地把參數(shù)給到那個方法的手里?

——在servlet里是getParameter,在Struts1中是ActionForm,在Struts2中是Action屬性,在SpringMVC中是方法參數(shù)。

所以,本文中控制器的概念的組成包括請求分發(fā)器、響應(yīng)渲染器、表現(xiàn)層方法三部分。

請求分發(fā)器和響應(yīng)渲染器的代碼由框架提供,配置由程序員進(jìn)行,它們聯(lián)手為表現(xiàn)層方法掃清外圍的嘈雜,使表現(xiàn)層方法得以相對簡單地干正事。

而我們知道,干正事其實是業(yè)務(wù)層的職責(zé)……

所以表現(xiàn)層方法就很清閑,方法體大約是調(diào)用一下業(yè)務(wù)層,俗稱「表現(xiàn)層是個薄層」。

但表現(xiàn)層方法原本不薄。它原本應(yīng)當(dāng)做4件事:

1)獲得參數(shù),即request.getParameter()

2)執(zhí)行邏輯,即service.xx()

3)設(shè)置模型,即request.setAttribute()

4)渲染頁面,即request..forward()

但框架既然職責(zé)在于「讓程序員專注于業(yè)務(wù)」,就當(dāng)然該降低1) 3) 4)的復(fù)雜度。

對1)獲得參數(shù),框架的想法就是把參數(shù)綁定到一些容易被表現(xiàn)層方法處理的什么東西上,較先進(jìn)的是方法參數(shù)。

對3)設(shè)置模型,框架的想法就是讓程序員可以輕松地把數(shù)據(jù)放到什么地方,放到這個地方就相當(dāng)于放進(jìn)了模型里,較先進(jìn)的是方法返回值。

對4)渲染頁面,框架的想法就是讓響應(yīng)渲染器做這事,程序員盡量輕松地給響應(yīng)渲染器提供必要信息即可,較先進(jìn)的是基于約定,根據(jù)表現(xiàn)層類和方法名尋找相應(yīng)路徑的模板(類和方法名的約定同時也是指定請求分發(fā)的路由)。

于是,表現(xiàn)層方法的方法名、參數(shù)、返回值都分擔(dān)掉了責(zé)任,方法體就可以只調(diào)一句service.xx()就行了……

所以我覺得,SpringMVC那個Controller,配不上「控制器」這么八荒六合唯我獨尊的霸氣名字。

你一個只有方法沒有屬性的單例對象,每個方法體又只包括一行語句,如果不是托了Java是個面向?qū)ο笳Z言的福,這些方法完全可以散落出去,各自承擔(dān)責(zé)任,還要你包袱皮何用?

別說,之前還真散落過……Servlet就是每個控制器處理一個請求,Struts2的初衷也是。

但Java這熊孩子,在lambda橫空出世之前,每個方法都必須身處類之中(導(dǎo)致了各種各樣的設(shè)計模式的出現(xiàn),最典型的就是策略模式,實踐中常表現(xiàn)為令人聞風(fēng)喪膽的匿名內(nèi)部類),結(jié)果用Servlet時web.xml膨脹不堪。

Struts2實踐中更是完全違反了「命令模式」「面向?qū)ο蟆沟某踔?,一個類里負(fù)責(zé)各個業(yè)務(wù)的屬性都有,別提多亂了……

想想也是,你一個方法就一條語句,還要獨占一個類,委實不能再過分。

大家叫苦不迭,直到有了SpringMVC這個尤物,大家把各個模塊的表現(xiàn)層方法歸攏歸攏,放到一個類里,減輕配置和約定的負(fù)擔(dān)。

這樣一來,也可以用類名稱和方法名稱,分別匹配模板所存在的文件夾名稱和模板文件名稱,以方便響應(yīng)渲染時模板的指定。

類名稱匹配文件夾名稱……

我們可憐的Controller,終于其性質(zhì)不幸從一個類,墮落成了一個package……

其實,其他語言的主流MVC框架,也都是這么回事。

處理請求的根本載體是方法,映射請求的根本性質(zhì)是框架把請求映射到方法。

類夾在框架和方法之間,上不上下不下,高不成低不就,當(dāng)然只能淪落成package,美其名曰「表現(xiàn)層組件」。

Struts2還曾想扶它一把,給它點屬性爽爽,大家表示,實在扶不上墻,你還是當(dāng)無狀態(tài)單例吧。

為什么會這樣捏?

因為,處理請求給出響應(yīng)這件事,根本就是,面向過程的。

所以,表現(xiàn)層方法,理所當(dāng)然,應(yīng)當(dāng)是一等公民。

而Java,沒給它這個機會。

它只好,把類架空。

偉大的Spring MVC,終于讓我們看清了這一點。

請求進(jìn)、響應(yīng)出的責(zé)任,經(jīng)過層層包裹,終于成了參數(shù)進(jìn),返回值出。

這是如此理所當(dāng)然和天經(jīng)地義。

脫離了對象的方法是什么——是函數(shù)。

函數(shù)是什么——對一組給定的自變量,給出一個確切的因變量——也就是映射。

我們?yōu)g覽網(wǎng)頁的時候在做的是什么——給出一個操作,希求得到一個確切的合邏輯的結(jié)果。

我們想要結(jié)果。

我們做出動作。

有一個函數(shù),幫我們把動作映射成結(jié)果。

——所以還要你這個類何用?

當(dāng)然,雖然你在語義上已經(jīng)沒有價值,但在編程元素上你還是不可缺少,物盡其用,你就當(dāng)package吧!

《魏書.孝靜紀(jì)第十二》:

帝不悅,曰:「自古無不亡之國,朕亦何用此活!」

文襄怒曰:「朕!朕!狗腳朕!」

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,590評論 19 139
  • 從三月份找實習(xí)到現(xiàn)在,面了一些公司,掛了不少,但最終還是拿到小米、百度、阿里、京東、新浪、CVTE、樂視家的研發(fā)崗...
    時芥藍(lán)閱讀 42,814評論 11 349
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 47,275評論 6 342
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法,內(nèi)部類的語法,繼承相關(guān)的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,734評論 18 399
  • 走在十字路口 漫隨人流涌向馬路的另一頭 腦子仿佛被思念絆了一下 于是,步代亂了綠燈的節(jié)奏 獨自困于馬路中央 車流在...
    詩姬閱讀 294評論 0 2

友情鏈接更多精彩內(nèi)容