
21. Web MVC框架
21.1 Spring Web MVC框架簡介
Spring Web模型 - 視圖 - 控制器(MVC)框架是圍繞一個(gè) DispatcherServlet
派發(fā)請(qǐng)求處理程序,具有可配置的處理程序映射,視圖分辨率,區(qū)域設(shè)置,時(shí)區(qū)和主題解析以及支持上載文件的。默認(rèn)處理程序是基于@Controller
和@RequestMapping
注釋,提供了廣泛的靈活的處理方法。隨著Spring 3.0的推出,該@Controller
機(jī)制還允許您通過@PathVariable
注釋和其他功能創(chuàng)建RESTful Web站點(diǎn)和應(yīng)用程序。
“Open for extension ...”Spring Web MVC和Spring中的一個(gè)關(guān)鍵設(shè)計(jì)原則是“ Open for extension,closed for modification ”原則。
Spring Web MVC的核心類中的一些方法被標(biāo)記final
。作為一名開發(fā)人員,您無法重寫這些方法來提供您自己的行為。這不是任意的,而是專門針對(duì)這一原則。
有關(guān)這個(gè)原理的解釋,請(qǐng)參閱Seth Ladd等人的Expert Spring Web MVC和Web Flow ; 具體請(qǐng)參閱第一版117頁的“設(shè)計(jì)看看”一節(jié)?;蛘撸?/p>
當(dāng)您使用Spring MVC時(shí),不能將建議添加到最終方法中。例如,您不能向該AbstractController.setSynchronizeOnSession()
方法添加建議。請(qǐng)參閱 第10.6.1節(jié)“了解AOP代理”以獲取有關(guān)AOP代理的更多信息,以及為什么不能將建議添加到最終方法。
在Spring Web MVC中,可以使用任何對(duì)象作為命令或形式支持對(duì)象; 您不需要實(shí)現(xiàn)特定于框架的接口或基類。Spring的數(shù)據(jù)綁定非常靈活:例如,它將類型不匹配視為可由應(yīng)用程序評(píng)估的驗(yàn)證錯(cuò)誤,而不是系統(tǒng)錯(cuò)誤。因此,您不需要將您的業(yè)務(wù)對(duì)象的屬性復(fù)制為表單對(duì)象中簡單的非類型化字符串,只是為了處理無效的提交,或者正確地轉(zhuǎn)換字符串。相反,通常最好直接綁定到您的業(yè)務(wù)對(duì)象。
Spring的視圖分辨率非常靈活。A Controller
通常負(fù)責(zé)Map
使用數(shù)據(jù)準(zhǔn)備模型并選擇視圖名稱,但也可以直接寫入響應(yīng)流并完成請(qǐng)求。通過文件擴(kuò)展名或者Accept頭內(nèi)容類型協(xié)商,通過bean名稱,屬性文件甚至自定義ViewResolver
實(shí)現(xiàn),視圖名稱解析是高度可配置的。模型(MVC中的M)是一個(gè)Map
接口,它允許視圖技術(shù)的完整抽象。您可以直接與基于模板的渲染技術(shù)(如JSP,Velocity和Freemarker)進(jìn)行集成,也可以直接生成XML,JSON,Atom和許多其他類型的內(nèi)容。該模型Map
簡單地轉(zhuǎn)換成適當(dāng)?shù)母袷?,例如JSP請(qǐng)求屬性,Velocity模板模型。
21.1.1 Spring Web MVC的特性
Spring Web Flow
Spring Web Flow(SWF)旨在成為Web應(yīng)用程序頁面流程管理的最佳解決方案。
SWF與Spring MVC和JSF等現(xiàn)有框架集成在Servlet和Portlet環(huán)境中。如果您有一個(gè)業(yè)務(wù)流程(或多個(gè)流程)可以從對(duì)話模型中獲益,而不是純粹的請(qǐng)求模型,那么SWF可能就是解決方案。
SWF允許您將邏輯頁面流作為獨(dú)立模塊進(jìn)行捕獲,這些模塊可在不同情況下重復(fù)使用,因此非常適合構(gòu)建通過受控導(dǎo)航來引導(dǎo)業(yè)務(wù)流程來指導(dǎo)用戶的Web應(yīng)用程序模塊。
有關(guān)SWF的更多信息,請(qǐng)參閱 Spring Web Flow網(wǎng)站。
Spring的Web模塊包含許多獨(dú)特的Web支持功能:
明確區(qū)分角色。每個(gè)角色 - 控制器,驗(yàn)證器,命令對(duì)象,表單對(duì)象,模型對(duì)象DispatcherServlet
,處理程序映射,視圖解析器等 - 都可以由專門的對(duì)象來實(shí)現(xiàn)。
強(qiáng)大而直接的框架和應(yīng)用程序類的配置,如JavaBeans。此配置功能包括跨上下文的簡單引用,例如從Web控制器到業(yè)務(wù)對(duì)象和驗(yàn)證程序。
適應(yīng)性,非侵入性和靈活性。定義您需要的任何控制器方法簽名,可能使用某個(gè)參數(shù)注釋(例如@RequestParam,@RequestHeader,@PathVariable等)來執(zhí)行給定的方案。
可重復(fù)使用的業(yè)務(wù)代碼,不需要重復(fù)。使用現(xiàn)有的業(yè)務(wù)對(duì)象作為命令或表單對(duì)象,而不是鏡像它們來擴(kuò)展特定的框架基類。
可定制的綁定和驗(yàn)證。將不匹配項(xiàng)視為應(yīng)用程序級(jí)驗(yàn)證錯(cuò)誤,從而保留違規(guī)值,本地化日期和數(shù)字綁定等,而不是手動(dòng)分析和轉(zhuǎn)換為業(yè)務(wù)對(duì)象的僅字符串表單對(duì)象。
可定制的處理程序映射和視圖解析。處理程序映射和視圖分辨率策略的范圍從簡單的基于URL的配置到復(fù)雜的專用解析策略。Spring比web MVC框架更靈活,它要求一個(gè)特定的技術(shù)。
靈活的模型轉(zhuǎn)移。具有名稱/值的模型傳輸Map
支持與任何視圖技術(shù)輕松集成。
可定制的語言環(huán)境,時(shí)區(qū)和主題解析,支持帶有或不帶有Spring標(biāo)簽庫的JSP,支持JSTL,支持Velocity而不需要額外的橋接,等等。
一個(gè)簡單而強(qiáng)大的JSP標(biāo)簽庫,被稱為Spring標(biāo)簽庫,提供對(duì)數(shù)據(jù)綁定和主題等功能的支持。自定義標(biāo)簽允許在標(biāo)記代碼方面有最大的靈活性。有關(guān)標(biāo)記庫描述符的信息,請(qǐng)參閱附錄,標(biāo)題為 Chapter 42,Spring JSP Tag Library
在Spring 2.0中引入了一個(gè)JSP表單標(biāo)簽庫,它使JSP頁面中的表單變得更容易。有關(guān)標(biāo)記庫描述符的信息,請(qǐng)參閱附錄標(biāo)題為“ Spring-form JSP標(biāo)記庫 ”的第43章
Bean的生命周期范圍為當(dāng)前的HTTP請(qǐng)求或HTTP Session
。 這不是Spring MVC本身的特定功能,而是WebApplicationContext
Spring MVC使用的 容器。這些bean作用域在第6.5.4節(jié)“請(qǐng)求,會(huì)話和全局會(huì)話作用域”
21.1.2其他MVC實(shí)現(xiàn)的可插入性
對(duì)于某些項(xiàng)目來說,非Spring MVC實(shí)現(xiàn)更可取。許多團(tuán)隊(duì)希望利用他們現(xiàn)有的技能和工具投資,例如JSF。
如果您不想使用Spring的Web MVC,但是打算利用Spring提供的其他解決方案,則可以輕松地將您所選擇的Web MVC框架與Spring集成。簡單地通過它啟動(dòng)一個(gè)Spring根應(yīng)用程序上下文 ContextLoaderListener
,并通過其ServletContext
屬性(或Spring的相應(yīng)的輔助方法)從任何操作對(duì)象中訪問它。不涉及“插件”,所以不需要專門的集成。從Web層的角度來看,只需使用Spring作為庫,并以根應(yīng)用程序上下文實(shí)例作為入口點(diǎn)。
即使沒有Spring的Web MVC,你注冊(cè)的bean和Spring的服務(wù)也可以在你的指尖。在這種情況下,Spring不會(huì)與其他Web框架競(jìng)爭(zhēng)。它只是簡單地解決了純Web的MVC框架所沒有的許多領(lǐng)域,從bean配置到數(shù)據(jù)訪問和事務(wù)處理。因此,即使您只是想使用JDBC或Hibernate的事務(wù)抽象,也可以使用Spring中間層和/或數(shù)據(jù)訪問層來豐富您的應(yīng)用程序。
21.2 DispatcherServlet
Spring的web MVC框架和許多其他的web MVC框架一樣,是以請(qǐng)求為驅(qū)動(dòng)的,圍繞一個(gè)中央Servlet進(jìn)行設(shè)計(jì),這個(gè)中央Servlet將請(qǐng)求分發(fā)給控制器,并提供其他功能來促進(jìn)Web應(yīng)用程序的開發(fā)。DispatcherServlet
然而,春天 不止于此。它與Spring IoC容器完全集成,因此可以使用Spring提供的其他所有功能。
Spring Web MVC的請(qǐng)求處理工作流程DispatcherServlet
如下圖所示。精通模式的讀者會(huì)認(rèn)識(shí)到,這 DispatcherServlet
是“Front Controller”設(shè)計(jì)模式(這是Spring Web MVC與許多其他領(lǐng)先的Web框架共享的模式)的表達(dá)。
圖21.1。Spring Web MVC中的請(qǐng)求處理工作流(高級(jí))
這DispatcherServlet
是一個(gè)實(shí)際的Servlet
(它從HttpServlet
基類繼承),并且這是在web.xml
你的Web應(yīng)用程序中聲明的。您需要映射要DispatcherServlet
處理的請(qǐng)求,方法是使用同一個(gè)web.xml
文件中的URL映射。這是標(biāo)準(zhǔn)的Java EE Servlet配置; 下面的例子顯示了這樣一個(gè)DispatcherServlet
聲明和映射:
exampleorg.springframework.web.servlet.DispatcherServlet1example/example/*
在前面的示例中,所有以開頭的請(qǐng)求/example
將由DispatcherServlet
名為的實(shí)例處理 example
。在Servlet 3.0+環(huán)境中,您也可以選擇以編程方式配置Servlet容器。以下是基于代碼的上面web.xml
例子的等價(jià)物:
public class MyWebApplicationInitializer implements WebApplicationInitializer { @Overridepublic void onStartup(ServletContext container) {ServletRegistration.Dynamic registration = container.addServlet('dispatcher', new DispatcherServlet());registration.setLoadOnStartup(1);registration.addMapping('/example/*');}}