為什么需要前后分離
后端為主的 MVC 時代
為了降低開發(fā)的復(fù)雜度遍愿,以后端為出發(fā)點,比如:Struts嚎京、SpringMVC 等框架的使用诚隙,就是后端的 MVC 時代;可以參考 【什么是 MVC 模式】
以 SpringMVC
流程為例:
- 發(fā)起請求到前端控制器(
DispatcherServlet
) - 前端控制器請求
HandlerMapping
查找Handler
既穆,可以根據(jù)xml
配置、注解進(jìn)行查找 - 處理器映射器
HandlerMapping
向前端控制器返回Handler
- 前端控制器調(diào)用處理器適配器去執(zhí)行
Handler
- 處理器適配器去執(zhí)行
Handler
-
Handler
執(zhí)行完成給適配器返回ModelAndView
- 處理器適配器向前端控制器返回
ModelAndView
雀鹃,ModelAndView
是SpringMVC
框架的一個底層對象幻工,包括Model
和View
- 前端控制器請求視圖解析器去進(jìn)行視圖解析,根據(jù)邏輯視圖名解析成真正的視圖(
JSP
) - 視圖解析器向前端控制器返回
View
- 前端控制器進(jìn)行視圖渲染黎茎,視圖渲染將模型數(shù)據(jù)(在
ModelAndView
對象中)填充到request
域 - 前端控制器向用戶響應(yīng)結(jié)果
優(yōu)點
MVC 是一個非常好的協(xié)作模式囊颅,能夠有效降低代碼的耦合度,從架構(gòu)上能夠讓開發(fā)者明白代碼應(yīng)該寫在哪里傅瞻。為了讓 View 更純粹踢代,還可以使用 Thymeleaf、Freemarker 等模板引擎俭正,使模板里無法寫入 Java 代碼奸鬓,讓前后端分工更加清晰。
缺點
- 前端開發(fā)重度依賴開發(fā)環(huán)境掸读,開發(fā)效率低串远,這種架構(gòu)下,前后端協(xié)作有兩種模式:
- 第一種是前端寫 DEMO儿惫,寫好后澡罚,讓后端去套模板。好處是 DEMO 可以本地開發(fā)肾请,很高效留搔。不足是還需要后端套模板,有可能套錯铛铁,套完后還需要前端確定隔显,來回溝通調(diào)整的成本比較大;
- 另一種協(xié)作模式是前端負(fù)責(zé)瀏覽器端的所有開發(fā)和服務(wù)器端的 View 層模板開發(fā)饵逐。好處是 UI 相關(guān)的代碼都是前端去寫就好括眠,后端不用太關(guān)注,不足就是前端開發(fā)重度綁定后端環(huán)境倍权,環(huán)境成為影響前端開發(fā)效率的重要因素掷豺。
- 前后端職責(zé)糾纏不清:模板引擎功能強大,依舊可以通過拿到的上下文變量來實現(xiàn)各種業(yè)務(wù)邏輯薄声。這樣当船,只要前端弱勢一點,往往就會被后端要求在模板層寫出不少業(yè)務(wù)代碼默辨。還有一個很大的灰色地帶是
Controller
德频,頁面路由等功能本應(yīng)該是前端最關(guān)注的,但卻是由后端來實現(xiàn)缩幸。Controller
本身與Model
往往也會糾纏不清抱婉,看了讓人咬牙的業(yè)務(wù)代碼經(jīng)常會出現(xiàn)在Controller
層档叔。這些問題不能全歸結(jié)于程序員的素養(yǎng),否則 JSP 就夠了蒸绩。 - 對前端發(fā)揮的局限性:性能優(yōu)化如果只在前端做空間非常有限衙四,于是我們經(jīng)常需要后端合作,但由于后端框架限制患亿,我們很難使用 【Comet】传蹈、【BigPipe】 等技術(shù)方案來優(yōu)化性能。
注:在這期間(2005 年以前)步藕,包括早期的 JSP
惦界、PHP
可以稱之為 Web 1.0
時代。在這里想說一句咙冗,如果你是一名 Java 初學(xué)者沾歪,請你不要再把一些陳舊的技術(shù)當(dāng)回事了,比如 JSP
雾消,因為時代在變灾搏、技術(shù)在變、什么都在變(引用扎克伯格的一句話:唯一不變的是變化本身
)立润;當(dāng)我們 千鋒教育
機構(gòu)去給大學(xué)做實訓(xùn)時狂窑,有些同學(xué)會認(rèn)為我們沒有講什么 干貨
,其實不然桑腮,只能說是你認(rèn)知里的干貨對于市場來說早就過時了而已泉哈。
什么是前后分離
基于 AJAX 帶來的 SPA 時代
時間回到 2005 年 AJAX
(Asynchronous JavaScript And XML,異步 JavaScript 和 XML破讨,老技術(shù)新用法) 被正式提出并開始使用 CDN
作為靜態(tài)資源存儲丛晦,于是出現(xiàn)了 JavaScript 王者歸來(在這之前 JS 都是用來在網(wǎng)頁上貼狗皮膏藥廣告的)的 SPA(Single Page Application)單頁面應(yīng)用時代。
優(yōu)點
這種模式下提陶,前后端的分工非常清晰烫沙,前后端的關(guān)鍵協(xié)作點是 AJAX
接口「槠铮看起來是如此美妙,但回過頭來看看的話又固,這與 JSP 時代區(qū)別不大仲器。復(fù)雜度從服務(wù)端的 JSP 里移到了瀏覽器的 JavaScript,瀏覽器端變得很復(fù)雜仰冠。類似 Spring MVC乏冀,這個時代開始出現(xiàn)瀏覽器端的分層架構(gòu):
缺點
-
前后端接口的約定: 如果后端的接口一塌糊涂,如果后端的業(yè)務(wù)模型不夠穩(wěn)定洋只,那么前端開發(fā)會很痛苦辆沦;不少團(tuán)隊也有類似嘗試昼捍,通過接口規(guī)則、接口平臺等方式來做肢扯。有了和后端一起沉淀的
接口規(guī)則
妒茬,還可以用來模擬數(shù)據(jù),使得前后端可以在約定接口后實現(xiàn)高效并行開發(fā)蔚晨。 - 前端開發(fā)的復(fù)雜度控制: SPA 應(yīng)用大多以功能交互型為主乍钻,JavaScript 代碼過十萬行很正常。大量 JS 代碼的組織铭腕,與 View 層的綁定等银择,都不是容易的事情。
前端為主的 MV* 時代
此處的 MV* 模式如下:
- MVC(同步通信為主):Model累舷、View浩考、Controller
- MVP(異步通信為主):Model、View被盈、Presenter
- MVVM(異步通信為主):Model析孽、View、ViewModel
為了降低前端開發(fā)復(fù)雜度害捕,涌現(xiàn)了大量的前端框架绿淋,比如:AngularJS
、React
尝盼、Vue.js
吞滞、EmberJS
等,這些框架總的原則是先按類型分層盾沫,比如 Templates裁赠、Controllers、Models赴精,然后再在層內(nèi)做切分佩捞,如下圖:
優(yōu)點
- 前后端職責(zé)很清晰: 前端工作在瀏覽器端,后端工作在服務(wù)端蕾哟。清晰的分工一忱,可以讓開發(fā)并行,測試數(shù)據(jù)的模擬不難谭确,前端可以本地開發(fā)帘营。后端則可以專注于業(yè)務(wù)邏輯的處理,輸出 RESTful等接口逐哈。
- 前端開發(fā)的復(fù)雜度可控: 前端代碼很重芬迄,但合理的分層,讓前端代碼能各司其職昂秃。這一塊蠻有意思的禀梳,簡單如模板特性的選擇杜窄,就有很多很多講究。并非越強大越好算途,限制什么塞耕,留下哪些自由,代碼應(yīng)該如何組織郊艘,所有這一切設(shè)計荷科,得花一本書的厚度去說明。
- 部署相對獨立: 可以快速改進(jìn)產(chǎn)品體驗
缺點
- 代碼不能復(fù)用纱注。比如后端依舊需要對數(shù)據(jù)做各種校驗畏浆,校驗邏輯無法復(fù)用瀏覽器端的代碼。如果可以復(fù)用狞贱,那么后端的數(shù)據(jù)校驗可以相對簡單化刻获。
- 全異步,對 SEO 不利瞎嬉。往往還需要服務(wù)端做同步渲染的降級方案尉咕。
- 性能并非最佳串前,特別是移動互聯(lián)網(wǎng)環(huán)境下涨颜。
- SPA 不能滿足所有需求曙旭,依舊存在大量多頁面應(yīng)用。URL Design 需要后端配合便监,前端無法完全掌控扎谎。
NodeJS 帶來的全棧時代
前端為主的 MV* 模式解決了很多很多問題,但如上所述烧董,依舊存在不少不足之處毁靶。隨著 NodeJS 的興起,JavaScript 開始有能力運行在服務(wù)端逊移。這意味著可以有一種新的研發(fā)模式:
在這種研發(fā)模式下预吆,前后端的職責(zé)很清晰。對前端來說胳泉,兩個 UI 層各司其職:
- Front-end UI layer 處理瀏覽器層的展現(xiàn)邏輯拐叉。通過 CSS 渲染樣式,通過 JavaScript 添加交互功能扇商,HTML 的生成也可以放在這層凤瘦,具體看應(yīng)用場景。
- Back-end UI layer 處理路由钳吟、模板廷粒、數(shù)據(jù)獲取窘拯、Cookie 等红且。通過路由坝茎,前端終于可以自主把控 URL Design,這樣無論是單頁面應(yīng)用還是多頁面應(yīng)用暇番,前端都可以自由調(diào)控嗤放。后端也終于可以擺脫對展現(xiàn)的強關(guān)注,轉(zhuǎn)而可以專心于業(yè)務(wù)邏輯層的開發(fā)壁酬。
通過 Node次酌,Web Server 層也是 JavaScript 代碼,這意味著部分代碼可前后復(fù)用舆乔,需要 SEO 的場景可以在服務(wù)端同步渲染岳服,由于異步請求太多導(dǎo)致的性能問題也可以通過服務(wù)端來緩解。前一種模式的不足希俩,通過這種模式幾乎都能完美解決掉吊宋。
與 JSP 模式相比,全棧模式看起來是一種回歸颜武,也的確是一種向原始開發(fā)模式的回歸璃搜,不過是一種螺旋上升式的回歸。
基于 NodeJS 的全棧模式鳞上,依舊面臨很多挑戰(zhàn):
- 需要前端對服務(wù)端編程有更進(jìn)一步的認(rèn)識这吻。比如 TCP/IP 等網(wǎng)絡(luò)知識的掌握。
- NodeJS 層與 Java 層的高效通信篙议。NodeJS 模式下唾糯,都在服務(wù)器端,RESTful HTTP 通信未必高效涡上,通過 SOAP 等方式通信更高效趾断。一切需要在驗證中前行。
- 對部署吩愧、運維層面的熟練了解芋酌,需要更多知識點和實操經(jīng)驗。
- 大量歷史遺留問題如何過渡雁佳。這可能是最大最大的阻力脐帝。
注:看到這里,相信很多同學(xué)就可以理解糖权,為什么我總在課堂上說:“前端想學(xué)后臺很難堵腹,而我們后端程序員學(xué)任何東西都很簡單”;就是因為我們后端程序員具備相對完善的知識體系星澳。
總結(jié)
綜上所述疚顷,模式也好,技術(shù)也罷,沒有好壞優(yōu)劣之分腿堤,只有適合不適合阀坏;前后分離的開發(fā)思想主要是基于 SoC
(關(guān)注度分離原則),上面種種模式笆檀,都是讓前后端的職責(zé)更清晰忌堂,分工更合理高效。