# 第二章 Spring MVC入門 —— 跟開濤學SpringMVC
## 2.1、Spring Web MVC是什么
Spring Web MVC是一種基于Java的實現了Web MVC設計模式的請求驅動類型的輕量級Web框架,即使用了MVC架構模式的思想,將web層進行職責解耦,基于請求驅動指的就是使用請求-響應模型,框架的目的就是幫助我們簡化開發,Spring Web MVC也是要簡化我們日常Web開發的。
另外還有一種基于組件的、事件驅動的Web框架在此就不介紹了,如Tapestry、JSF等。
Spring Web MVC也是服務到工作者模式的實現,但進行可優化。前端控制器是`DispatcherServlet;`應用控制器其實拆為處理器映射器(Handler Mapping)進行處理器管理和視圖解析器(View Resolver)進行視圖管理;頁面控制器/動作/處理器為Controller接口(僅包含`ModelAndView handleRequest(request, response)`?方法)的實現(也可以是任何的POJO類);支持本地化(Locale)解析、主題(Theme)解析及文件上傳等;提供了非常靈活的數據驗證、格式化和數據綁定機制;提供了強大的約定大于配置(慣例優先原則)的契約式編程支持。
## 2.2、Spring Web MVC能幫我們做什么
√讓我們能非常簡單的設計出干凈的Web層和薄薄的Web層;
√進行更簡潔的Web層的開發;
√天生與Spring框架集成(如IoC容器、AOP等);
√提供強大的約定大于配置的契約式編程支持;
√能簡單的進行Web層的單元測試;
√支持靈活的URL到頁面控制器的映射;
√非常容易與其他視圖技術集成,如Velocity、FreeMarker等等,因為模型數據不放在特定的API里,而是放在一個Model里(`Map`數據結構實現,因此很容易被其他框架使用);
√非常靈活的數據驗證、格式化和數據綁定機制,能使用任何對象進行數據綁定,不必實現特定框架的API;
√提供一套強大的JSP標簽庫,簡化JSP開發;
√支持靈活的本地化、主題等解析;
√更加簡單的異常處理;
√對靜態資源的支持;
√支持Restful風格。
## 2.3、Spring Web MVC架構
Spring Web MVC框架也是一個基于請求驅動的Web框架,并且也使用了前端控制器模式來進行設計,再根據請求映射規則分發給相應的頁面控制器(動作/處理器)進行處理。首先讓我們整體看一下Spring Web MVC處理請求的流程:
### 2.3.1、Spring Web MVC處理請求的流程
如圖2-1

圖2-1
具體執行步驟如下:
1、? 首先用戶發送請求————>前端控制器,前端控制器根據請求信息(如URL)來決定選擇哪一個頁面控制器進行處理并把請求委托給它,即以前的控制器的控制邏輯部分;圖2-1中的1、2步驟;
2、? 頁面控制器接收到請求后,進行功能處理,首先需要收集和綁定請求參數到一個對象,這個對象在Spring Web MVC中叫命令對象,并進行驗證,然后將命令對象委托給業務對象進行處理;處理完畢后返回一個ModelAndView(模型數據和邏輯視圖名);圖2-1中的3、4、5步驟;
3、? 前端控制器收回控制權,然后根據返回的邏輯視圖名,選擇相應的視圖進行渲染,并把模型數據傳入以便視圖渲染;圖2-1中的步驟6、7;
4、? 前端控制器再次收回控制權,將響應返回給用戶,圖2-1中的步驟8;至此整個結束。
問題:
1、? 請求如何給前端控制器?
2、? 前端控制器如何根據請求信息選擇頁面控制器進行功能處理?
3、? 如何支持多種頁面控制器呢?
4、? 如何頁面控制器如何使用業務對象?
5、? 頁面控制器如何返回模型數據?
6、? 前端控制器如何根據頁面控制器返回的邏輯視圖名選擇具體的視圖進行渲染?
7、? 不同的視圖技術如何使用相應的模型數據?
首先我們知道有如上問題,那這些問題如何解決呢?請讓我們先繼續,在后邊依次回答。
### 2.3.2、Spring Web MVC架構
1、Spring Web MVC核心架構圖,如圖2-2

圖2-2
架構圖對應的DispatcherServlet核心代碼如下:
```
//前端控制器分派方法
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
int interceptorIndex = -1;
try {
ModelAndView mv;
boolean errorView = false;
try {
//檢查是否是請求是否是multipart(如文件上傳),如果是將通過MultipartResolver解析
processedRequest = checkMultipart(request);
//步驟2、請求到處理器(頁面控制器)的映射,通過HandlerMapping進行映射
mappedHandler = getHandler(processedRequest, false);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
noHandlerFound(processedRequest, response);
return;
}
//步驟3、處理器適配,即將我們的處理器包裝成相應的適配器(從而支持多種類型的處理器)
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 304 Not Modified緩存支持
//此處省略具體代碼
// 執行處理器相關的攔截器的預處理(HandlerInterceptor.preHandle)
//此處省略具體代碼
// 步驟4、由適配器執行處理器(調用處理器相應功能處理方法)
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
// Do we need view name translation?
if (mv != null && !mv.hasView()) {
mv.setViewName(getDefaultViewName(request));
}
// 執行處理器相關的攔截器的后處理(HandlerInterceptor.postHandle)
//此處省略具體代碼
}
catch (ModelAndViewDefiningException ex) {
logger.debug("ModelAndViewDefiningException encountered", ex);
mv = ex.getModelAndView();
}
catch (Exception ex) {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
mv = processHandlerException(processedRequest, response, handler, ex);
errorView = (mv != null);
}
//步驟5 步驟6、解析視圖并進行視圖的渲染
//步驟5 由ViewResolver解析View(viewResolver.resolveViewName(viewName, locale))
//步驟6 視圖在渲染時會把Model傳入(view.render(mv.getModelInternal(), request, response);)
if (mv != null && !mv.wasCleared()) {
render(mv, processedRequest, response);
if (errorView) {
WebUtils.clearErrorRequestAttributes(request);
}
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
"': assuming HandlerAdapter completed request handling");
}
}
// 執行處理器相關的攔截器的完成后處理(HandlerInterceptor.afterCompletion)
//此處省略具體代碼
catch (Exception ex) {
// Trigger after-completion for thrown exception.
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
throw ex;
}
catch (Error err) {
ServletException ex = new NestedServletException("Handler processing failed", err);
// Trigger after-completion for thrown exception.
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
throw ex;
}
finally {
// Clean up any resources used by a multipart request.
if (processedRequest != request) {
cleanupMultipart(processedRequest);
}
}
}
```
核心架構的具體流程步驟如下:
1、? 首先用戶發送請求——>DispatcherServlet,前端控制器收到請求后自己不進行處理,而是委托給其他的解析器進行處理,作為統一訪問點,進行全局的流程控制;
2、? DispatcherServlet——>HandlerMapping, HandlerMapping將會把請求映射為HandlerExecutionChain對象(包含一個Handler處理器(頁面控制器)對象、多個HandlerInterceptor攔截器)對象,通過這種策略模式,很容易添加新的映射策略;
3、? DispatcherServlet——>HandlerAdapter,HandlerAdapter將會把處理器包裝為適配器,從而支持多種類型的處理器,即適配器設計模式的應用,從而很容易支持很多類型的處理器;
4、? HandlerAdapter——>處理器功能處理方法的調用,HandlerAdapter將會根據適配的結果調用真正的處理器的功能處理方法,完成功能處理;并返回一個ModelAndView對象(包含模型數據、邏輯視圖名);
5、? ModelAndView的邏輯視圖名——> ViewResolver, ViewResolver將把邏輯視圖名解析為具體的View,通過這種策略模式,很容易更換其他視圖技術;
6、? View——>渲染,View會根據傳進來的Model模型數據進行渲染,此處的Model實際是一個Map數據結構,因此很容易支持其他視圖技術;
7、返回控制權給DispatcherServlet,由DispatcherServlet返回響應給用戶,到此一個流程結束。
此處我們只是講了核心流程,沒有考慮攔截器、本地解析、文件上傳解析等,后邊再細述。
到此,再來看我們前邊提出的問題:
1、? 請求如何給前端控制器?這個應該在web.xml中進行部署描述,在HelloWorld中詳細講解。
2、? 前端控制器如何根據請求信息選擇頁面控制器進行功能處理? 我們需要配置HandlerMapping進行映射
3、? 如何支持多種頁面控制器呢?配置HandlerAdapter從而支持多種類型的頁面控制器
4、? 如何頁面控制器如何使用業務對象?可以預料到,肯定利用Spring IoC容器的依賴注入功能
5、? 頁面控制器如何返回模型數據?使用ModelAndView返回
6、? 前端控制器如何根據頁面控制器返回的邏輯視圖名選擇具體的視圖進行渲染? 使用ViewResolver進行解析
7、? 不同的視圖技術如何使用相應的模型數據? 因為Model是一個Map數據結構,很容易支持其他視圖技術
在此我們可以看出具體的核心開發步驟:
1、? DispatcherServlet在web.xml中的部署描述,從而攔截請求到Spring Web MVC
2、? HandlerMapping的配置,從而將請求映射到處理器
3、? HandlerAdapter的配置,從而支持多種類型的處理器
4、? ViewResolver的配置,從而將邏輯視圖名解析為具體視圖技術
5、處理器(頁面控制器)的配置,從而進行功能處理
上邊的開發步驟我們會在Hello World中詳細驗證。
## 2.4、Spring Web MVC優勢
1、清晰的角色劃分:前端控制器(`DispatcherServlet`)、請求到處理器映射(HandlerMapping)、處理器適配器(HandlerAdapter)、視圖解析器(ViewResolver)、處理器或頁面控制器(Controller)、驗證器(?? Validator)、命令對象(Command? 請求參數綁定到的對象就叫命令對象)、表單對象(Form Object 提供給表單展示和提交到的對象就叫表單對象)。
2、分工明確,而且擴展點相當靈活,可以很容易擴展,雖然幾乎不需要;
3、由于命令對象就是一個POJO,無需繼承框架特定API,可以使用命令對象直接作為業務對象;
4、和Spring 其他框架無縫集成,是其它Web框架所不具備的;
5、可適配,通過HandlerAdapter可以支持任意的類作為處理器;
6、可定制性,HandlerMapping、ViewResolver等能夠非常簡單的定制;
7、功能強大的數據驗證、格式化、綁定機制;
8、利用Spring提供的Mock對象能夠非常簡單的進行Web層單元測試;
9、本地化、主題的解析的支持,使我們更容易進行國際化和主題的切換。
10、強大的JSP標簽庫,使JSP編寫更容易。
………………還有比如RESTful風格的支持、簡單的文件上傳、約定大于配置的契約式編程支持、基于注解的零配置支持等等。
到此我們已經簡單的了解了Spring Web MVC,接下來讓我們來個實例來具體使用下這個框架。
## 2.5、Hello World入門
### 2.5.1、準備開發環境和運行環境:
**☆開發工具:eclipse**
**☆運行環境:tomcat6.0.20**
**☆工程:動態web工程(springmvc-chapter2)**
**☆spring框架下載:**
spring-framework-3.1.1.RELEASE-with-docs.zip
**☆依賴jar包:**
1、? Spring框架jar包:
為了簡單,將spring-framework-3.1.1.RELEASE-with-docs.zip/dist/下的所有jar包拷貝到項目的WEB-INF/lib目錄下;
2、? Spring框架依賴的jar包:
需要添加Apache commons logging日志,此處使用的是commons.logging-1.1.1.jar;
需要添加jstl標簽庫支持,此處使用的是jstl-1.1.2.jar和standard-1.1.2.jar;
### 2.5.2、前端控制器的配置
在我們的web.xml中添加如下配置:
```
<servlet>
<servlet-name>chapter2</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>chapter2</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
```
**load-on-startup:**表示啟動容器時初始化該Servlet;
**url-pattern:**表示哪些請求交給Spring Web MVC處理, “/” 是用來定義默認servlet映射的。也可以如“*.html”表示攔截所有以html為擴展名的請求。
自此請求已交給Spring Web MVC框架處理,因此我們需要配置Spring的配置文件,默認DispatcherServlet會加載WEB-INF/[DispatcherServlet的Servlet名字]-servlet.xml配置文件。本示例為WEB-INF/ chapter2-servlet.xml。
### 2.5.3、在Spring配置文件中配置HandlerMapping、HandlerAdapter
具體配置在WEB-INF/ chapter2-servlet.xml文件中:
```
<!-- HandlerMapping -->
<bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<!-- HandlerAdapter -->
<bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
```
BeanNameUrlHandlerMapping:表示將請求的URL和Bean名字映射,如URL為 “上下文/hello”,則Spring配置文件必須有一個名字為“/hello”的Bean,上下文默認忽略。
SimpleControllerHandlerAdapter:表示所有實現了org.springframework.web.servlet.mvc.Controller接口的Bean可以作為Spring Web MVC中的處理器。如果需要其他類型的處理器可以通過實現HadlerAdapter來解決。
### 2.5.4、在Spring配置文件中配置ViewResolver
具體配置在WEB-INF/ chapter2-servlet.xml文件中:
```
<!-- ViewResolver -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
```
InternalResourceViewResolver:用于支持Servlet、JSP視圖解析;
viewClass:JstlView表示JSP模板頁面需要使用JSTL標簽庫,classpath中必須包含jstl的相關jar包;
prefix和suffix:查找視圖頁面的前綴和后綴(前綴[邏輯視圖名]后綴),比如傳進來的邏輯視圖名為hello,則該該jsp視圖頁面應該存放在“WEB-INF/jsp/hello.jsp”;
### 2.5.5、開發處理器/頁面控制器
```
package cn.javass.chapter2.web.controller;
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 req, HttpServletResponse resp) throws Exception {
//1、收集參數、驗證參數
//2、綁定參數到命令對象
//3、將命令對象傳入業務對象進行業務處理
//4、選擇下一個頁面
ModelAndView mv = new ModelAndView();
//添加模型數據 可以是任意的POJO對象
mv.addObject("message", "Hello World!");
//設置邏輯視圖名,視圖解析器會根據該名字解析到具體的視圖頁面
mv.setViewName("hello");
return mv;
}
}
```
org.springframework.web.servlet.mvc.Controller:頁面控制器/處理器必須實現Controller接口,注意別選錯了;后邊我們會學習其他的處理器實現方式;
public ModelAndView handleRequest(HttpServletRequest req, HttpServletResponse resp) :功能處理方法,實現相應的功能處理,比如收集參數、驗證參數、綁定參數到命令對象、將命令對象傳入業務對象進行業務處理、最后返回ModelAndView對象;
ModelAndView:包含了視圖要實現的模型數據和邏輯視圖名;“mv.addObject("message", "Hello World!");
”表示添加模型數據,此處可以是任意POJO對象;“mv.setViewName("hello");”表示設置邏輯視圖名為“hello”,視圖解析器會將其解析為具體的視圖,如前邊的視圖解析器InternalResourceVi。wResolver會將其解析為“WEB-INF/jsp/hello.jsp”。
我們需要將其添加到Spring配置文件(WEB-INF/chapter2-servlet.xml),讓其接受Spring IoC容器管理:
```
<!-- 處理器 -->
<bean name="/hello" class="cn.javass.chapter2.web.controller.HelloWorldController"/>
```
name="/hello":前邊配置的BeanNameUrlHandlerMapping,表示如過請求的URL為 “上下文/hello”,則將會交給該Bean進行處理。?
### 2.5.6、開發視圖頁面
創建 /WEB-INF/jsp/hello.jsp視圖頁面:
```
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Hello World</title>
</head>
<body>
${message}
</body>
</html>
```
${message}:表示顯示由HelloWorldController處理器傳過來的模型數據。
### 2.5.6、啟動服務器運行測試
通過請求:[http://localhost:9080/springmvc-chapter2/hello](http://localhost:9080/springmvc-chapter2/hello),如果頁面輸出“Hello World! ”就表明我們成功了!
### 2.5.7、運行流程分析
如圖2-3

圖2-3
運行步驟:
1、? 首先用戶發送請求[http://localhost:9080/springmvc-chapter2/hello——>web](http://localhost:9080/springmvc-chapter2/hello%E2%80%94%E2%80%94%3eweb)容器,web容器根據“/hello”路徑映射到DispatcherServlet(url-pattern為/)進行處理;
2、? DispatcherServlet——>BeanNameUrlHandlerMapping進行請求到處理的映射,BeanNameUrlHandlerMapping將“/hello”路徑直接映射到名字為“/hello”的Bean進行處理,即HelloWorldController,BeanNameUrlHandlerMapping將其包裝為HandlerExecutionChain(只包括HelloWorldController處理器,沒有攔截器);
3、? DispatcherServlet——> SimpleControllerHandlerAdapter,SimpleControllerHandlerAdapter將HandlerExecutionChain中的處理器(HelloWorldController)適配為SimpleControllerHandlerAdapter;
4、? SimpleControllerHandlerAdapter——> HelloWorldController處理器功能處理方法的調用,SimpleControllerHandlerAdapter將會調用處理器的handleRequest方法進行功能處理,該處理方法返回一個ModelAndView給DispatcherServlet;
5、? hello(ModelAndView的邏輯視圖名)——>InternalResourceViewResolver, InternalResourceViewResolver使用JstlView,具體視圖頁面在/WEB-INF/jsp/hello.jsp;
6、? JstlView(/WEB-INF/jsp/hello.jsp)——>渲染,將在處理器傳入的模型數據(message=HelloWorld!)在視圖中展示出來;
7、? 返回控制權給DispatcherServlet,由DispatcherServlet返回響應給用戶,到此一個流程結束。
到此HelloWorld就完成了,步驟是不是有點多?而且回憶下我們主要進行了如下配置:
1、? 前端控制器DispatcherServlet;
2、? HandlerMapping
3、? HandlerAdapter
4、? ViewResolver
5、? 處理器/頁面控制器
6、? 視圖
因此,接下來幾章讓我們詳細看看這些配置,先從DispatcherServlet開始吧。
## 2.6、POST中文亂碼解決方案
spring Web MVC框架提供了org.springframework.web.filter.CharacterEncodingFilter用于解決POST方式造成的中文亂碼問題,具體配置如下:
```
<filter>
<filter-name>CharacterEncodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CharacterEncodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
```
以后我們項目及所有頁面的編碼均為UTF-8。
## 2.7、Spring3.1新特性
`**一、Spring2.5之前,我們都是通過實現Controller接口或其實現來定義我們的處理器類。**`
`**二、Spring2.5引入注解式處理器支持,通過@Controller 和 @RequestMapping注解定義我們的處理器類。并且提供了一組強大的注解:**`
`需要通過處理器映射DefaultAnnotationHandlerMapping和處理器適配器AnnotationMethodHandlerAdapter來開啟支持@Controller 和 @RequestMapping注解的處理器。`
`@Controller:``用于標識是處理器類;`
`@RequestMapping:``請求到處理器功能方法的映射規則;`
`@RequestParam:``請求參數到處理器功能處理方法的方法參數上的綁定;`
`@ModelAttribute:``請求參數到命令對象的綁定;`
`@SessionAttributes:``用于聲明session級別存儲的屬性,放置在處理器類上,通常列出模型屬性(如@ModelAttribute)對應的名稱,則這些屬性會透明的保存到session中;`
`@InitBinder:``自定義數據綁定注冊支持,用于將請求參數轉換到命令對象屬性的對應類型;`
`**三、Spring3.0引入RESTful架構風格支持(通過@PathVariable注解和一些其他特性支持),且又引入了更多的注解支持:**`
`@CookieValue:``cookie數據到處理器功能處理方法的方法參數上的綁定;`
`@RequestHeader:``請求頭(header)數據到處理器功能處理方法的方法參數上的綁定;`
`@RequestBody:``請求的body體的綁定(通過HttpMessageConverter進行類型轉換);`
`@ResponseBody:``處理器功能處理方法的返回值作為響應體(通過HttpMessageConverter進行類型轉換);`
`@ResponseStatus:``定義處理器功能處理方法/異常處理器返回的狀態碼和原因;`
`@ExceptionHandler:``注解式聲明異常處理器;`
`@PathVariable:``請求URI中的模板變量部分到處理器功能處理方法的方法參數上的綁定,從而支持RESTful架構風格的URI;`
`**四、還有比如:**`
`JSR-303驗證框架的無縫支持(通過@Valid注解定義驗證元數據);`
`使用Spring 3開始的ConversionService進行類型轉換(`PropertyEditor依然有效`),支持`使用@NumberFormat 和 @DateTimeFormat來進行數字和日期的格式化;
`HttpMessageConverter``(Http輸入/輸出轉換器,比如JSON、XML等的數據輸出轉換器);`
`ContentNegotiatingViewResolver``,內容協商視圖解析器,它還是視圖解析器,只是它支持根據請求信息將同一模型數據以不同的視圖方式展示(如json、xml、html等),RESTful架構風格中很重要的概念(同一資源,多種表現形式);`
`Spring 3 引入 一個 ?mvc XML的命名空間用于支持mvc配置,包括如:`
`??? <mvc:annotation-driven>:`
`????? 自動注冊基于注解風格的處理器需要的DefaultAnnotationHandlerMapping、AnnotationMethodHandlerAdapter`
`????? 支持Spring3的ConversionService自動注冊`
`????? 支持JSR-303驗證框架的自動探測并注冊(只需把JSR-303實現放置到classpath)`
`????? 自動注冊相應的HttpMessageConverter(用于支持@RequestBody ?和 @ResponseBody)(如XML輸入輸出轉換器(只需將JAXP實現放置到classpath)、JSON輸入輸出轉換器(只需將Jackson實現放置到classpath))等。`
`??? <mvc:interceptors>:注冊自定義的處理器攔截器;`
`??? <mvc:view-controller>:和ParameterizableViewController類似,收到相應請求后直接選擇相應的視圖;`
<mvc:resources>:邏輯靜態資源路徑到物理靜態資源路徑的支持;
<mvc:default-servlet-handler>:當在web.xml?中DispatcherServlet使用<url-pattern>/</url-pattern>?映射時,能映射靜態資源(當Spring Web MVC框架沒有處理請求對應的控制器時(如一些靜態資源),轉交給默認的Servlet來響應靜態文件,否則報404找不到資源錯誤,)。
`……等等。`
`**五、Spring3.1新特性:**`
`對Servlet 3.0的全面支持。`
`@EnableWebMvc:``用于在基于Java類定義Bean配置中開啟MVC支持,和XML中的<mvc:annotation-driven>功能一樣;`
`新的@Contoller和@RequestMapping注解支持類:處理器映射RequestMappingHandlerMapping 和 處理器適配器RequestMappingHandlerAdapter組合來代替Spring2.5開始的處理器映射DefaultAnnotationHandlerMapping和處理器適配器AnnotationMethodHandlerAdapter,提供更多的擴展點,它們之間的區別我們在處理器映射一章介紹。`
`新的@ExceptionHandler 注解支持類:ExceptionHandlerExceptionResolver來代替Spring3.0的AnnotationMethodHandlerExceptionResolver,在異常處理器一章我們再詳細講解它們的區別。`
`@RequestMapping的"consumes" 和 "produces" 條件支持:``用于支持@RequestBody 和 @ResponseBody,`
`1``consumes``指定請求的內容是什么類型的內容,即本處理方法消費什么類型的數據,如consumes="application/json"表示JSON類型的內容,Spring會根據相應的HttpMessageConverter進行請求內容區數據到@RequestBody注解的命令對象的轉換;`
`2``produces``指定生產什么類型的內容,如produces="application/json"表示JSON類型的內容,Spring的根據相應的HttpMessageConverter進行請求內容區數據到@RequestBody注解的命令對象的轉換,Spring會根據相應的HttpMessageConverter進行模型數據(返回值)到JSON響應內容的轉換`
`3``以上內容,本章第×××節詳述。`
`URI模板變量增強:``URI模板變量可以直接綁定到@ModelAttribute指定的命令對象、@PathVariable方法參數在視圖渲染之前被合并到模型數據中(除JSON序列化、XML混搭場景下)。`
`@Validated:``JSR-303的javax.validation.Valid一種變體(非JSR-303規范定義的,而是Spring自定義的),用于提供對Spring的驗證器(org.springframework.validation.Validator)支持,需要Hibernate Validator 4.2及更高版本支持;`
`@RequestPart:``提供對“multipart/form-data”請求的全面支持,支持Servlet 3.0文件上傳(javax.servlet.http.Part)、支持內容的HttpMessageConverter(即根據請求頭的Content-Type,來判斷內容區數據是什么類型,如JSON、XML,能自動轉換為命令對象),比@RequestParam更強大(只能對請求參數數據綁定,key-alue格式),而@RequestPart支持如JSON、XML內容區數據的綁定;詳見本章的第×××節;`
`Flash 屬性 和 RedirectAttribute:``通過FlashMap存儲一個請求的輸出,當進入另一個請求時作為該請求的輸入,典型場景如重定向(POST-REDIRECT-GET模式,1、POST時將下一次需要的數據放在FlashMap;2、重定向;3、通過GET訪問重定向的地址,此時FlashMap會把1放到FlashMap的數據取出放到請求中,并從FlashMap中刪除;從而支持在兩次請求之間保存數據并防止了重復表單提交)。`
`Spring Web MVC提供FlashMapManager用于管理FlashMap,默認使用`SessionFlashMapManager,即數據默認存儲在session中`。`
[
私塾在線學習網](http://sishuok.com/)原創內容([http://sishuok.com](http://sishuok.com/))
原創內容,轉載請注明私塾在線【[http://sishuok.com/forum/blogPost/list/5160.html](http://sishuok.com/forum/blogPost/list/5050.html#15499)】
- 跟我學 Spring3
- 【第二章】 IoC 之 2.1 IoC基礎 ——跟我學Spring3
- 【第二章】 IoC 之 2.2 IoC 容器基本原理 ——跟我學Spring3
- 【第二章】 IoC 之 2.3 IoC的配置使用——跟我學Spring3
- 【第三章】 DI 之 3.1 DI的配置使用 ——跟我學spring3
- 【第三章】 DI 之 3.2 循環依賴 ——跟我學spring3
- 【第三章】 DI 之 3.3 更多DI的知識 ——跟我學spring3
- 【第三章】 DI 之 3.4 Bean的作用域 ——跟我學spring3
- 【第四章】 資源 之 4.1 基礎知識 ——跟我學spring3
- 【第四章】 資源 之 4.2 內置Resource實現 ——跟我學spring3
- 【第四章】 資源 之 4.3 訪問Resource ——跟我學spring3
- 【第四章】 資源 之 4.4 Resource通配符路徑 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.1 概述 5.2 SpEL基礎 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.3 SpEL語法 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.4在Bean定義中使用EL—跟我學spring3
- 【第六章】 AOP 之 6.1 AOP基礎 ——跟我學spring3
- 【第六章】 AOP 之 6.2 AOP的HelloWorld ——跟我學spring3
- 【第六章】 AOP 之 6.3 基于Schema的AOP ——跟我學spring3
- 【第六章】 AOP 之 6.4 基于@AspectJ的AOP ——跟我學spring3
- 【第六章】 AOP 之 6.5 AspectJ切入點語法詳解 ——跟我學spring3
- 【第六章】 AOP 之 6.6 通知參數 ——跟我學spring3
- 【第六章】 AOP 之 6.7 通知順序 ——跟我學spring3
- 【第六章】 AOP 之 6.8 切面實例化模型 ——跟我學spring3
- 【第六章】 AOP 之 6.9 代理機制 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.1 概述 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.2 JDBC模板類 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.3 關系數據庫操作對象化 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.4 Spring提供的其它幫助 ——跟我學spring3【私塾在線原創】
- 【第七章】 對JDBC的支持 之 7.5 集成Spring JDBC及最佳實踐 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.1 概述 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.2 集成Hibernate3 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.3 集成iBATIS ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.4 集成JPA ——跟我學spring3
- 【第九章】 Spring的事務 之 9.1 數據庫事務概述 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.2 事務管理器 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.3 編程式事務 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.4 聲明式事務 ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.1 概述 ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.2 集成Struts1.x ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.3 集成Struts2.x ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.4 集成JSF ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.1 概述 ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.2 實現通用層 ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.3 實現積分商城層 ——跟我學spring3
- 【第十二章】零配置 之 12.1 概述 ——跟我學spring3
- 【第十二章】零配置 之 12.2 注解實現Bean依賴注入 ——跟我學spring3
- 【第十二章】零配置 之 12.3 注解實現Bean定義 ——跟我學spring3
- 【第十二章】零配置 之 12.4 基于Java類定義Bean配置元數據 ——跟我學spring3
- 【第十二章】零配置 之 12.5 綜合示例-積分商城 ——跟我學spring3
- 【第十三章】 測試 之 13.1 概述 13.2 單元測試 ——跟我學spring3
- 【第十三章】 測試 之 13.3 集成測試 ——跟我學spring3
- 跟我學 Spring MVC
- SpringMVC + spring3.1.1 + hibernate4.1.0 集成及常見問題總結
- Spring Web MVC中的頁面緩存支持 ——跟我學SpringMVC系列
- Spring3 Web MVC下的數據類型轉換(第一篇)——《跟我學Spring3 Web MVC》搶先看
- Spring3 Web MVC下的數據格式化(第二篇)——《跟我學Spring3 Web MVC》搶先看
- 第一章 Web MVC簡介 —— 跟開濤學SpringMVC
- 第二章 Spring MVC入門 —— 跟開濤學SpringMVC
- 第三章 DispatcherServlet詳解 ——跟開濤學SpringMVC
- 第四章 Controller接口控制器詳解(1)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(2)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(3)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解 (4)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(5)——跟著開濤學SpringMVC
- 跟著開濤學SpringMVC 第一章源代碼下載
- 第二章 Spring MVC入門 源代碼下載
- 第四章 Controller接口控制器詳解 源代碼下載
- 第四章 Controller接口控制器詳解(6)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(7 完)——跟著開濤學SpringMVC
- 第五章 處理器攔截器詳解——跟著開濤學SpringMVC
- 源代碼下載 第五章 處理器攔截器詳解——跟著開濤學SpringMVC
- 注解式控制器運行流程及處理器定義 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- 源代碼下載 第六章 注解式控制器詳解
- SpringMVC3強大的請求映射規則詳解 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- Spring MVC 3.1新特性 生產者、消費者請求限定 —— 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC強大的數據綁定(1)——第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC強大的數據綁定(2)——第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC數據類型轉換——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC
- SpringMVC數據格式化——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC
- SpringMVC數據驗證——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC