第一章
Spring的MVC框架
6.1 Spring MVC概要
Spring的web框架是圍繞DispatcherServlet
來進行設計的。DispatcherServlet
的做用是將請求分發到不一樣的處理器。Spring的web框架包括可配置的處理器(handler)映射、視圖(view)解析、本地化(local)解析、主題(theme)解析以及對上傳文件解析。處理器是對Controller
接口的實現,該接口僅僅定義了ModelAndView handleRequest(request, response)
方法。你能夠經過實現這個接口來生成本身的控制器(也能夠稱之爲處理器),可是從Spring提供的一系列控制器繼承會更省事,好比AbstractController
、AbstractCommandController
和SimpleFormController
。注意,你須要選擇正確的基類:若是你沒有表單,你就不須要一個FormController。這是和Structs的一個主要區別。Spring的視圖解析至關靈活。一個控制器甚至能夠直接向response輸出一個視圖(此時控制器返回ModelAndView的值必須是null)。在通常的狀況下,一個ModelAndView實例包含一個視圖名字和一個類型爲Map的model,一個model是一些以bean的名字爲key,以bean對象(能夠是命令或form,也能夠是其餘的JavaBean)爲value的名值對。對視圖名稱的解析處理也是高度可配置的,能夠經過bean的名字、屬性文件或者自定義的ViewResolver實現來進行解析。實際上基於Map的model(也就是MVC中的M))是高度抽象的,適用於各類表現層技術。也就是說,任何表現層均可以直接和Spring集成,不管是JSP、Velocity仍是其它表現層技術。Map model能夠被轉換成合適的格式,好比JSP request attribute或者Velocity template model。
Spring Web MVC框架提供了大量獨特的功能,包括:
1) 清晰的角色劃分:控制器(controller)、驗證器(validator)、命令對象(command object)、表單對象(form object)、模型對象(model object)、Servlet分發器(DispatcherServlet)、處理器映射(handler mapping)、視圖解析器(view resolver)等等。 每個角色均可以由一個專門的對象來實現。
2)強大而直接的配置方式:將框架類和應用類都做爲JavaBean配置,支持在一個context中引用其餘context的中JavaBean,例如,在web控制器中對業務對象和驗證器(validator)的引用。
3) 可適配、非侵入的controller:你能夠根據不一樣的應用場景,選擇合適的控制器子類(simple型、command型、form型、wizard型、multi-action型或者自定義),而不是從單一控制器(好比Action/ActionForm)繼承。
4)可重用的業務代碼:你可使用現有的業務對象做爲命令或表單對象,而不須要在相似ActionForm的子類中重複它們的定義。
5)可定製的綁定(binding) 和驗證(validation):好比將類型不匹配做爲應用級的驗證錯誤,這能夠保存錯誤的值。再好比本地化的日期和數字綁定等等。在其餘某些框架中,你只能使用字符串表單對象,須要手動解析它並轉換到業務對象。
6) 可定製的handler mapping和view resolution:Spring提供從最簡單的的URL映射,到複雜的、專用的定製策略。與某些MVC框架強制開發人員使用單一特定技術相比,Spring顯得更加靈活。靈活。
7) 靈活的model轉換: 在Springweb框架中,使用基於Map的名/值對來達到輕易地與各類視圖技術的集成。
8) 可定製的本地化和主題(theme)解析:支持在JSP中可選擇地使用Spring標籤庫、支持JSTL、支持Velocity(不須要額外的中間層)等等。
9)Spring Bean的生命週期能夠被限制在當前的HTTP Request或者HTTP Session。準確的說,這並不是Spring MVC框架自己特性,而應歸屬於Sping MVC使用的WebApplicationContext容器。
6.2 將請求映射到控制器
和其它web框架同樣,Spring的web框架是一個請求驅動的web框架,其設計圍繞一箇中心的servlet進行,它能將請求分發給控制器,並提供其它功能幫助web應用開發。然而,Spring的DispatcherServlet
所作的不只僅是這些,它和Spring的IoC容器徹底集成在一塊兒,從而容許你使用Spring的其它功能。
代碼清單1
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-config-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
代碼清單1中咱們定義了DispatcherServlet取名dispatcher而且將全部以.do結尾的請求都交由dispatcher處理,而且爲他指定了名爲spring-config-mvc.xml 的Spring配置文件。若是咱們沒有指定配置文件的名稱Spring會在web應用的WEB-INF
文件夾下尋找名爲[servlet-name]-servlet.xml
的配置文件如dispatcher-servlet.xml
代碼清單2
<bean id="viewResolver" class="org.springframework.web.servlet.view.
InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="simpleUrlHandlerMapping" class="org.springframework.web.servlet.handler.
SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/helloworld.do"> helloworldController</prop>
</props>
</property>
</bean>
<bean id=" helloworldController "
class="
com.tony.web.controller
.
HelloworldController
"/>
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
import
org.springframework.web.servlet.ModelAndView;
import
org.springframework.web.servlet.mvc.Controller;
public
class
HelloworldController
implements
Controller {
@Override
public
ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response)
throws
Exception {
//
向
HttpServletRequest
中加入一個名爲
message
值爲
HelloWorld
的對象
request.setAttribute(
"message"
,
"HelloWorld"
);
//返回一個ModelAndView對象經過viewResolver的處理
//頁面跳轉至/WEB-INF/jsp/helloworld.jsp
return
new
ModelAndView(
"helloworld"
);
}
}
代碼清單
1
中配置 InternalResourceViewResolver,它是 jsp 渲染模板的處理器。若是你告訴 InternalResourceViewResolver 處理一個名爲
helloworld
的模板時,它會渲染 /WEB-INF/jsp/
helloworld
.jsp 文件。把 jsp 文件放到 /WEB-INF/jsp/ 目錄下是被鼓勵的,這樣能夠防止用戶不通過 Controller 直接訪問 jsp 文件從而出錯。配置
SimpleUrlHandlerMapping
,
在上面的配置文件中,
/
helloworld
.do
的請求將被
helloworldController處理。
"/
helloworld
.do"
和
"
helloworldController
"
是變量,你能夠更改。可是你注意到了嗎,
hello.do
以
.do
做爲後綴名。若是這裏
(
本文的條件下
)
你不使用
.do
做爲後綴名,
就沒有程序來處理這個請求了。
由於
DispatcherServlet
將收到的請求轉交給
SimpleUrlHandlerMapping
,
DispatcherServlet
收不到的請求,
SimpleUrlHandlerMapping
固然也收不到了。咱們還定義了一個名爲
HelloworldController
的控制器來處理/helloworld.do的請求。大多數Web應用都會遇到須要填寫表單的頁面,當表單提交成功後,表單的數據被傳送到Web服務器中處理,遇到這種狀況Spring爲咱們提供了一個簡單的類
SimpleFormController
。
代碼清單2
import
javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse;
import
org.springframework.web.servlet.mvc.SimpleFormController;
public
class
HelloworldController
extends
SimpleFormController{
public
HelloworldController(){
//
設置表單對象類型
this
.setCommandClass(User.
class
);
}
@Override
protected
void
doSubmitAction(Object command)
throws
Exception {
User user = (User)command;
//
將
User
對象存入數據庫
}
}
代碼清單
2
中咱們將
HelloworldController
類繼承
SimpleFormController
而且實現了
doSubmitAction
方法,在構造方法中咱們設置了表單對象的類型,當表單提交後
Spring
會自動調用
doSubmitAction
方法將表單對象裝配好做爲入參傳遞進來,咱們將其類型轉後就能夠對其操做了。