跟開濤學Spring MVC:第一章 Web MVC簡介

發表於2012-10-24

注:本文來自文章作者張開濤(@開濤)的投稿(原文)。伯樂線上也歡迎其他朋友投稿,如果您有新浪微博,請投稿時記得留下哦~

// 提示:如果下文圖片看不清,可單擊檢視原圖。

Web MVC簡介

1.1、Web開發中的請求-響應模型:

在Web世界裡,具體步驟如下:

1、  Web瀏覽器(如IE)發起請求,如訪問 http://sishuok.com

2、  Web伺服器(如Tomcat)接收請求,處理請求(比如使用者新增,則將把使用者儲存一下),最後產生響應(一般為html)。

3、web伺服器處理完成後,返回內容給web客戶端(一般就是我們的瀏覽器),客戶端對接收的內容進行處理(如web瀏覽器將會對接收到的html內容進行渲染以展示給客戶)。

 

因此,在Web世界裡:

都是Web客戶端發起請求,Web伺服器接收、處理併產生響應。

 

一般Web伺服器是不能主動通知Web客戶端更新內容。雖然現在有些技術如伺服器推(如Comet)、還有現在的HTML5 websocket可以實現Web伺服器主動通知Web客戶端。

 

到此我們瞭解了在web開發時的請求/響應模型,接下來我們看一下標準的MVC模型是什麼。

 

1.2、標準MVC模型概述

MVC模型:是一種架構型的模式,本身不引入新功能,只是幫助我們將開發的結構組織的更加合理,使展示與模型分離、流程控制邏輯、業務邏輯呼叫與展示邏輯分離。如圖1-2

圖1-2

首先讓我們瞭解下MVC(Model-View-Controller)三元組的概念:

Model(模型):資料模型,提供要展示的資料,因此包含資料和行為,可以認為是領域模型或JavaBean元件(包含資料和行為),不過現在一般都分離開來:Value Object(資料) 和 服務層(行為)。也就是模型提供了模型資料查詢和模型資料的狀態更新等功能,包括資料和業務。

 

View(檢視):負責進行模型的展示,一般就是我們見到的使用者介面,客戶想看到的東西。

 

Controller(控制器):接收使用者請求,委託給模型進行處理(狀態改變),處理完畢後把返回的模型資料返回給檢視,由檢視負責展示。 也就是說控制器做了個排程員的工作,。

 

從圖1-1我們還看到,在標準的MVC中模型能主動推資料給檢視進行更新(觀察者設計模式,在模型上註冊檢視,當模型更新時自動更新檢視),但在Web開發中模型是無法主動推給檢視(無法主動更新使用者介面),因為在Web開發是請求-響應模型。

 

那接下來我們看一下在Web裡MVC是什麼樣子,我們稱其為 Web MVC 來區別標準的MVC。

 

1.3、Web MVC概述

模型-檢視-控制器概念和標準MVC概念一樣,請參考1.2,我們再看一下Web MVC標準架構,如圖1-3:

如圖1-3

 

在Web MVC模式下,模型無法主動推資料給檢視,如果使用者想要檢視更新,需要再傳送一次請求(即請求-響應模型)。

 

概念差不多了,我們接下來了解下Web端開發的發展歷程,和使用程式碼來演示一下Web MVC是如何實現的,還有為什麼要使用MVC這個模式呢?

 

1.4、Web端開發發展歷程

此處我們只是簡單的敘述比較核心的歷程,如圖1-4

圖1-4

1.4.1、CGI:(Common Gateway Interface)公共閘道器介面,一種在web服務端使用的指令碼技術,使用C或Perl語言編寫,用於接收web使用者請求並處理,最後動態產生響應給使用者,但每次請求將產生一個程式,重量級。

 

1.4.2、Servlet:一種JavaEE web元件技術,是一種在伺服器端執行的web元件,用於接收web使用者請求並處理,最後動態產生響應給使用者。但每次請求只產生一個執行緒(而且有執行緒池),輕量級。而且能利用許多JavaEE技術(如JDBC等)。本質就是在java程式碼裡面 輸出 html流。但表現邏輯、控制邏輯、業務邏輯呼叫混雜。如圖1-5

圖1-5

如圖1-5,這種做法是絕對不可取的,控制邏輯、表現程式碼、業務邏輯物件呼叫混雜在一起,最大的問題是直接在Java程式碼裡面輸出Html,這樣前端開發人員無法進行頁面風格等的設計與修改,即使修改也是很麻煩,因此實際專案這種做法不可取。

 

1.4.3、JSP(Java Server Page):一種在伺服器端執行的web元件,是一種執行在標準的HTML頁面中嵌入指令碼語言(現在只支援Java)的模板頁面技術。本質就是在html程式碼中嵌入java程式碼。JSP最終還是會被編譯為Servlet,只不過比純Servlet開發頁面更簡單、方便。但表現邏輯、控制邏輯、業務邏輯呼叫還是混雜。如圖1-6

 

圖1-6

 

如圖1-6,這種做法也是絕對不可取的,控制邏輯、表現程式碼、業務邏輯物件呼叫混雜在一起,但比直接在servlet裡輸出html要好一點,前端開發人員可以進行簡單的頁面風格等的設計與修改(但如果嵌入的java指令碼太多也是很難修改的),因此實際專案這種做法不可取。

JSP本質還是Servlet,最終在執行時會生成一個Servlet(如tomcat,將在tomcat\work\Catalina\web應用名\org\apache\jsp下生成),但這種使得寫html簡單點,但仍是控制邏輯、表現程式碼、業務邏輯物件呼叫混雜在一起。

 

1.4.4、Model1可以認為是JSP的增強版,可以認為是jsp+javabean如圖1-7

特點:使用<jsp:useBean>標準動作,自動將請求引數封裝為JavaBean元件;還必須使用java指令碼執行控制邏輯。

 

圖1-7

此處我們可以看出,使用<jsp:useBean>標準動作可以簡化javabean的獲取/建立,及將請求引數封裝到javabean,再看一下Model1架構,如圖1-8。

圖1-8 Model1架構

Model1架構中,JSP負責控制邏輯、表現邏輯、業務物件(javabean)的呼叫,只是比純JSP簡化了獲取請求引數和封裝請求引數。同樣是不好的,在專案中應該嚴禁使用(或最多再demo裡使用)。

 

1.4.5、Model2在JavaEE世界裡,它可以認為就是Web MVC模型

Model2架構其實可以認為就是我們所說的Web MVC模型,只是控制器採用Servlet、模型採用JavaBean、檢視採用JSP,如圖1-9

圖1-9 Model2架構

 

具體程式碼事例如下:

從Model2架構可以看出,檢視和模型分離了,控制邏輯和展示邏輯分離了。

但我們也看到嚴重的缺點:

1.  1、控制器:

1.1.1、控制邏輯可能比較複雜,其實我們可以按照規約,如請求引數submitFlag=toAdd,我們其實可以直接呼叫toAdd方法,來簡化控制邏輯;而且每個模組基本需要一個控制器,造成控制邏輯可能很複雜;

1.1.2、請求引數到模型的封裝比較麻煩,如果能交給框架來做這件事情,我們可以從中得到解放;

1.1.3、選擇下一個檢視,嚴重依賴Servlet API,這樣很難或基本不可能更換檢視;

1.1.4、給檢視傳輸要展示的模型資料,使用Servlet API,更換檢視技術也要一起更換,很麻煩。

 

1.2、模型:

1.2.1、此處模型使用JavaBean,可能造成JavaBean元件類很龐大,一般現在專案都是採用三層架構,而不採用JavaBean。

 

1.3、檢視

1.3.1、現在被繫結在JSP,很難更換檢視,比如Velocity、FreeMarker;比如我要支援Excel、PDF檢視等等。

 

1.4.5、服務到工作者:Front Controller + Application Controller + Page Controller + Context

即,前端控制器+應用控制器+頁面控制器(也有稱其為動作)+上下文,也是Web MVC,只是責任更加明確,詳情請參考《核心J2EE設計模式》和《企業應用架構模式》如圖1-10:

圖1-10

執行流程如下:

職責:

Front Controller前端控制器,負責為表現層提供統一訪問點,從而避免Model2中出現的重複的控制邏輯(由前端控制器統一回撥相應的功能方法,如前邊的根據submitFlag=login轉調login方法);並且可以為多個請求提供共用的邏輯(如準備上下文等等),將選擇具體檢視和具體的功能處理(如login裡邊封裝請求引數到模型,並呼叫業務邏輯物件)分離。

 

Application Controller應用控制器,前端控制器分離選擇具體檢視和具體的功能處理之後,需要有人來管理,應用控制器就是用來選擇具體檢視技術(檢視的管理)和具體的功能處理(頁面控制器/命令物件/動作管理),一種策略設計模式的應用,可以很容易的切換檢視/頁面控制器,相互不產生影響。

 

Page Controller(Command)頁面控制器/動作/處理器:功能處理程式碼,收集引數、封裝引數到模型,轉調業務物件處理模型,返回邏輯檢視名交給前端控制器(和具體的檢視技術解耦),由前端控制器委託給應用控制器選擇具體的檢視來展示,可以是命令設計模式的實現。頁面控制器也被稱為處理器或動作。

 

Context上下文,還記得Model2中為檢視準備要展示的模型資料嗎,我們直接放在request中(Servlet API相關),有了上下文之後,我們就可以將相關資料放置在上下文,從而與協議無關(如Servlet API)的訪問/設定模型資料,一般通過ThreadLocal模式實現。

 

 

到此,我們回顧了整個web開發架構的發展歷程,可能不同的web層框架在細節處理方面不同,但的目的是一樣的:

乾淨的web表現層:

·模型和檢視的分離;

·控制器中的控制邏輯與功能處理分離(收集並封裝引數到模型物件、業務物件呼叫);

·控制器中的檢視選擇與具體檢視技術分離。

輕薄的web表現層:

·做的事情越少越好,薄薄的,不應該包含無關程式碼;

·只負責收集並組織引數到模型物件,啟動業務物件的呼叫;

·控制器只返回邏輯檢視名並由相應的應用控制器來選擇具體使用的檢視策略;

·儘量少使用框架特定API,保證容易測試。

 

到此我們瞭解Web MVC的發展歷程,接下來讓我們瞭解下Spring MVC到底是什麼、架構及來個HelloWorld瞭解下具體怎麼使用吧。

 

本章具體程式碼請參考 springmvc-chapter1工程。

 

 

相關文章