學習完整課程請移步 互聯(lián)網(wǎng) Java 全棧工程師
本節(jié)視頻
為什么需要前后分離
后端為主的 MVC 時代
為了降低開發(fā)的復雜度,以后端為出發(fā)點,比如:Struts、SpringMVC 等框架的使用,就是后端的 MVC 時代;可以參考 【什么是 MVC 模式】
以 SpringMVC 流程為例:

- 發(fā)起請求到前端控制器(
DispatcherServlet) - 前端控制器請求
HandlerMapping查找Handler,可以根據(jù)xml配置、注解進行查找 - 處理器映射器
HandlerMapping向前端控制器返回Handler - 前端控制器調(diào)用處理器適配器去執(zhí)行
Handler - 處理器適配器去執(zhí)行
Handler -
Handler執(zhí)行完成給適配器返回ModelAndView - 處理器適配器向前端控制器返回
ModelAndView,ModelAndView是SpringMVC框架的一個底層對象,包括Model和View - 前端控制器請求視圖解析器去進行視圖解析,根據(jù)邏輯視圖名解析成真正的視圖(
JSP) - 視圖解析器向前端控制器返回
View - 前端控制器進行視圖渲染,視圖渲染將模型數(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ā)和服務(wù)器端的 View 層模板開發(fā)。好處是 UI 相關(guān)的代碼都是前端去寫就好,后端不用太關(guān)注,不足就是前端開發(fā)重度綁定后端環(huán)境,環(huán)境成為影響前端開發(fā)效率的重要因素。
- 前后端職責糾纏不清:模板引擎功能強大,依舊可以通過拿到的上下文變量來實現(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 初學者,請你不要再把一些陳舊的技術(shù)當回事了,比如 JSP,因為時代在變、技術(shù)在變、什么都在變(引用扎克伯格的一句話:唯一不變的是變化本身);當我們 千鋒教育 機構(gòu)去給大學做實訓時,有些同學會認為我們沒有講什么 干貨 ,其實不然,只能說是你認知里的干貨對于市場來說早就過時了而已。
什么是前后分離
基于 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ū)別不大。復雜度從服務(wù)端的 JSP 里移到了瀏覽器的 JavaScript,瀏覽器端變得很復雜。類似 Spring MVC,這個時代開始出現(xiàn)瀏覽器端的分層架構(gòu):

缺點
-
前后端接口的約定: 如果后端的接口一塌糊涂,如果后端的業(yè)務(wù)模型不夠穩(wěn)定,那么前端開發(fā)會很痛苦;不少團隊也有類似嘗試,通過接口規(guī)則、接口平臺等方式來做。有了和后端一起沉淀的
接口規(guī)則,還可以用來模擬數(shù)據(jù),使得前后端可以在約定接口后實現(xiàn)高效并行開發(fā)。 - 前端開發(fā)的復雜度控制: SPA 應(yīng)用大多以功能交互型為主,JavaScript 代碼過十萬行很正常。大量 JS 代碼的組織,與 View 層的綁定等,都不是容易的事情。
前端為主的 MV* 時代
此處的 MV* 模式如下:
- MVC(同步通信為主):Model、View、Controller
- MVP(異步通信為主):Model、View、Presenter
- MVVM(異步通信為主):Model、View、ViewModel
為了降低前端開發(fā)復雜度,涌現(xiàn)了大量的前端框架,比如:AngularJS、React、Vue.js、EmberJS 等,這些框架總的原則是先按類型分層,比如 Templates、Controllers、Models,然后再在層內(nèi)做切分,如下圖:

優(yōu)點
- 前后端職責很清晰: 前端工作在瀏覽器端,后端工作在服務(wù)端。清晰的分工,可以讓開發(fā)并行,測試數(shù)據(jù)的模擬不難,前端可以本地開發(fā)。后端則可以專注于業(yè)務(wù)邏輯的處理,輸出 RESTful(可以參考 【如何設(shè)計一個良好的 API】)等接口。
- 前端開發(fā)的復雜度可控: 前端代碼很重,但合理的分層,讓前端代碼能各司其職。這一塊蠻有意思的,簡單如模板特性的選擇,就有很多很多講究。并非越強大越好,限制什么,留下哪些自由,代碼應(yīng)該如何組織,所有這一切設(shè)計,得花一本書的厚度去說明。
- 部署相對獨立: 可以快速改進產(chǎn)品體驗
缺點
- 代碼不能復用。比如后端依舊需要對數(shù)據(jù)做各種校驗,校驗邏輯無法復用瀏覽器端的代碼。如果可以復用,那么后端的數(shù)據(jù)校驗可以相對簡單化。
- 全異步,對 SEO 不利。往往還需要服務(wù)端做同步渲染的降級方案。
- 性能并非最佳,特別是移動互聯(lián)網(wǎng)環(huán)境下。
- SPA 不能滿足所有需求,依舊存在大量多頁面應(yīng)用。URL Design 需要后端配合,前端無法完全掌控。
NodeJS 帶來的全棧時代
前端為主的 MV* 模式解決了很多很多問題,但如上所述,依舊存在不少不足之處。隨著 NodeJS 的興起,JavaScript 開始有能力運行在服務(wù)端。這意味著可以有一種新的研發(fā)模式:

在這種研發(fā)模式下,前后端的職責很清晰。對前端來說,兩個 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 代碼,這意味著部分代碼可前后復用,需要 SEO 的場景可以在服務(wù)端同步渲染,由于異步請求太多導致的性能問題也可以通過服務(wù)端來緩解。前一種模式的不足,通過這種模式幾乎都能完美解決掉。
與 JSP 模式相比,全棧模式看起來是一種回歸,也的確是一種向原始開發(fā)模式的回歸,不過是一種螺旋上升式的回歸。
基于 NodeJS 的全棧模式,依舊面臨很多挑戰(zhàn):
- 需要前端對服務(wù)端編程有更進一步的認識。比如 TCP/IP 等網(wǎng)絡(luò)知識的掌握。
- NodeJS 層與 Java 層的高效通信。NodeJS 模式下,都在服務(wù)器端,RESTful HTTP 通信未必高效,通過 SOAP 等方式通信更高效。一切需要在驗證中前行。
- 對部署、運維層面的熟練了解,需要更多知識點和實操經(jīng)驗。
- 大量歷史遺留問題如何過渡。這可能是最大最大的阻力。
注:看到這里,相信很多同學就可以理解,為什么我總在課堂上說:“前端想學后臺很難,而我們后端程序員學任何東西都很簡單”;就是因為我們后端程序員具備相對完善的知識體系。
全棧!So Easy!╮( ̄▽ ̄)╭!
總結(jié)
綜上所述,模式也好,技術(shù)也罷,沒有好壞優(yōu)劣之分,只有適合不適合;前后分離的開發(fā)思想主要是基于 SoC(關(guān)注度分離原則),上面種種模式,都是讓前后端的職責更清晰,分工更合理高效。