文章目錄
- 1. SpringMVC 概述
- 2. 使用 @RequestMapping 映射請求
- 3. @PathVariable 映射 URL 綁定的佔位符
- 4. REST
- 5. 請求處理方法簽名
- 6. 使用 @RequestParam 綁定請求參數值
- 7. 使用 @RequestHeader 綁定請求報頭的屬性值
- 8. 使用 @CookieValue 綁定請求中的 Cookie 值
- 9. 使用 POJO 對象綁定請求參數值
- 10. MVC 的 Handler 方法可以接受
- 11. 處理模型數據
- 11.1 ModelAndView
- 11.2 Map 及 Model
- 11.3 @SessionAttributes
- 11.4 @ModelAttribute
- 11.5 SpringMVC確定目標方法POJO類型入參的過程
- 12. Spring MVC如何解析視圖
- 13. 關於重定向
- 14. Spring 的表單標籤
- 15. 處理靜態資源
- 16. 數據綁定流程
- 17. Springmvc自帶轉換器類型(部分)
- 18. 自定義類型轉換器
- 19. 關於 mvc:annotation-driven
- 20. @InitBinder
- 21. 數據格式化
- 22. 校驗
- 23. 提示消息的國際化
- 24. 處理 JSON
- 25. HttpMessageConverter\
1. SpringMVC 概述
-
Spring 爲展現層提供的基於 MVC設計理念的優秀的Web 框架,是目前最主流的MVC 框架之一
-
Spring3.0 後全面超越 Struts2,成爲最優秀的 MVC框架
-
Spring MVC 通過一套 MVC 註解,讓 POJO 成爲處理請求的控制器,而無須實現任何接口。
-
支持 REST 風格的 URL請求
-
採用了鬆散耦合可插拔組件結構,比其他 MVC 框架更具擴展性和靈活性
2. 使用 @RequestMapping 映射請求
-
Spring MVC 使用 @RequestMapping 註解爲控制器指定可以處理哪些 URL 請求 ()
-
在控制器的類定義及方法定義處都可標註
- @RequestMapping
- 類定義處:提供初步的請求映射信息。相對於 WEB 應用的根目錄
- 方法處:提供進一步的細分映射信息。相對於類定義處的 URL。若類定義處未標註 @RequestMapping,則方法處標記的 URL 相對於WEB 應用的根目錄**
-
DispatcherServlet 截獲請求後,就通過控制器上@RequestMapping 提供的映射信息確定請求所對應的處理方法。
示例:
@Controller
public class Helloworld {
@RequestMapping("/helloworld")
public String hello() {
System.out.println("hello");
return "success";
}
}
2.1 映射請求參數、請求方法或請求頭
-
@RequestMapping 除了可以使用請求 URL 映射請求外,還可以使用請求方法、請求參數及請求頭映射請求
-
@RequestMapping 的 value、method、params 及 heads 分別表示請求 URL、請求方法、請求參數及請求頭的映射條件,他們之間是與的關係,聯合使用多個條件可讓請求映射更加精確化。
-
params 和 headers支持簡單的表達式:
- param1: 表示請求必須包含名爲 param1 的請求參數
- !param1: 表示請求不能包含名爲 param1 的請求參數
- param1 != value1: 表示請求包含名爲 param1 的請求參數,但其值不能爲 value1
- {“param1=value1”, “param2”}: 請求必須包含名爲 param1 和param2 的兩個請求參數,且 param1 參數的值必須爲 value1
示例:
2.2 Maping支持通配符
-
Ant 風格資源地址支持 3 種匹配符:
- ?:匹配文件名中的一個字符
- *:匹配文件名中的任意字符
- **:** 匹配多層路徑
-
@RequestMapping 還支持 Ant 風格的 URL:
-
/user/*/createUser: 匹配
/user/aaa/createUser、/user/bbb/createUser 等 URL
-
/user//createUser: 匹配
/user/createUser、/user/aaa/bbb/createUser 等 URL
-
/user/createUser??: 匹配
/user/createUseraa、/user/createUserbb 等 URL
-
3. @PathVariable 映射 URL 綁定的佔位符
-
帶佔位符的 URL 是 Spring3.0 新增的功能,該功能在SpringMVC 向 REST 目標挺進發展過程中具有里程碑的意義
-
通過 @PathVariable 可以將 URL 中佔位符參數綁定到控制器處理方法的入參中:URL 中的 {xxx} 佔位符可以通過 @PathVariable(“xxx”) 綁定到操作方法的入參中。
4. REST
-
REST: 即 Representational State Transfer。(資源)表現層狀態轉化。是目前最流行的一種互聯網軟件架構。它結構清晰、符合標準、易於理解、擴展方便,所以正得到越來越多網站的採用
-
資源(Resources): 網絡上的一個實體,或者說是網絡上的一個具體信息。它可以是一段文本、一張圖片、一首歌曲、一種服務,總之就是一個具體的存在。可以用一個URI(統一資源定位符)指向它,每種資源對應一個特定的 URI 。要 獲取這個資源,訪問它的URI就可以,因此 URI 即爲每一個資源的獨一無二的識 別符。
-
表現層(Representation): 把資源具體呈現出來的形式,叫做它的表現層(Representation)。比如,文本可以用 txt 格式表現,也可以用 HTML 格 式、XML 格式、JSON 格式表現,甚至可以採用二進制格式。
-
狀態轉化(State Transfer):每發出一個請求,就代表了客戶端和服務器的一次交互過程。HTTP協議,是一個無狀態協議,即所有的狀態都保存在服務器端。因此,如果客戶端想要操作服務器,必須通過某種手段,讓服務器端發生“ 狀態轉化”(State Transfer)。而這種轉化是建立在表現層之上的,所以就是 “ 表現層狀態轉化”。具體說,就是 HTTP 協議裏面,四個表示操作方式的動 詞:GET、POST、PUT、DELETE。它們分別對應四種基本操作:GET 用來獲取資源,POST 用來新建資源,PUT 用來更新資源,DELETE 用來刪除資源。
示例:
- /order/1 HTTP GET :得到 id = 1 的 order
- /order/1 HTTP DELETE:刪除 id = 1的 order
- /order/1 HTTP PUT:更新id = 1的 order
- /order HTTP POST:新增 order
HiddenHttpMethodFilter:瀏覽器 form 表單只支持 GET 與 POST 請求,而DELETE、PUT 等 method 並不支 持,Spring3.0 添加了一個過濾器,可以將這些請求轉換爲標準的 http 方法,使得支持 GET、POST、PUT 與DELETE 請求。
5. 請求處理方法簽名
- Spring MVC 通過分析處理方法的簽名,將 HTTP 請求信息綁定到處理方法的相應人蔘中。
- Spring MVC 對控制器處理方法簽名的限制是很寬鬆的,幾乎可以按喜歡的任何方式對方法進行簽名。
- 必要時可以對方法及方法入參標註相應的註解( @PathVariable、@RequestParam、@RequestHeader 等)、Spring MVC 框架會將 HTTP 請求的信息綁定到相應的方法入參中,並根據方法的返回值類型做出相應的後續處理。
6. 使用 @RequestParam 綁定請求參數值
- 在處理方法入參處使用 @RequestParam 可以把請求參數傳遞給請求方法
- value:參數名
- required:是否必須。默認爲 true, 表示請求參數中必須包含對應的參數,若不存在,將拋出異常
- defaultValue請求參數的默認值
7. 使用 @RequestHeader 綁定請求報頭的屬性值
請求頭包含了若干個屬性,服務器可據此獲知客戶端的信息,通過 @RequestHeader 即可將請求頭中的屬性值綁定到處理方法的入參中
8. 使用 @CookieValue 綁定請求中的 Cookie 值
@CookieValue 可讓處理方法入參綁定某個 Cookie 值
9. 使用 POJO 對象綁定請求參數值
Spring MVC 會按請求參數名和 POJO 屬性名進行自動匹配,自動爲該對象填充屬性值。支持級聯屬性。
級聯屬性:對象中的成員屬性對象
10. MVC 的 Handler 方法可以接受
哪些 ServletAPI 類型的參數
- HttpServletRequest
- HttpServletResponse
- HttpSession
- java.security.Principal
- Locale
- InputStream
- OutputStream
- Reader
- Writer
直接寫在hander方法的參數部分即可
11. 處理模型數據
Spring MVC 提供了以下幾種途徑輸出模型數據:
-
ModelAndView: 處理方法返回值類型爲ModelAndView時, 方法體即可通過該對象添加模型數據
-
Map 及 Model: 入參爲org.springframework.ui.Model、org.springframework.ui.ModelMap 或 java.uti.Map 時,處理方法返回時,Map 中的數據會自動添加到模型中。
-
@SessionAttributes: 將模型中的某個屬性暫存到HttpSession 中,以便多個請求之間可以共享這個屬性
-
@ModelAttribute: 方法入參標註該註解後, 入參的對象
就會放到數據模型中
11.1 ModelAndView
-
控制器處理方法的返回值如果爲 ModelAndView, 則其既包含視圖信息,也包含模型數據信息。
-
添加模型數據:
- MoelAndView addObject(String attributeName, Object attributeValue) (SpringMVC會把ModelAndView的model中數據放入到 request域對象中、可以使用requestScope取出)
- ModelAndView addAllObject(Map<String, ?> modelMap)
-
設置視圖:
- void setView(View view)
- void setViewName(String viewName)
Springmvc無論hander返回的是什麼類型,都會封裝成ModelAndView
11.2 Map 及 Model
-
Spring MVC 在內部使用了一個org.springframework.ui.Model 接口存儲模型數據
-
具體步驟
-
Spring MVC 在調用方法前會創建一個隱含的模型對象作爲模型數據的存儲容器。
-
目標方法可以添加Map類型(實際上也可以是Model類型或ModelMap類型)的參數。
-
如果方法的入參爲 Map 或 Model 類 型,Spring MVC 會將隱含模型的引用傳遞給這些入參。在方法體內,開發者可以通過這個入參對象訪問到模型中的所有數據,也可以向模型中添加新的屬性數據
-
屬性默認傳遞到request域裏
-
11.3 @SessionAttributes
-
還是使用Map傳遞屬性
-
若希望在多個請求之間共用某個模型屬性數據,則可以在控制器類上標註一個 @SessionAttributes, Spring MVC 將在模型中對應的屬性暫存到 HttpSession 中。(當然request域中的屬性還在)
-
@SessionAttributes 除了可以通過屬性名指定需要放到會話中的屬性外(實際上使用的是value 屬性值),還可以通過模型屬性的對象類型指定哪些模型屬性需要放到會話中 (實際上使用的是types 屬性值)
-
@SessionAttributes(types=User.class) 會將隱含模型中所有類型 爲 User.class 的屬性添加到會話中。
- @SessionAttributes(value={“user1”, “user2”})
- @SessionAttributes(types={User.class, Dept.class})
- @SessionAttributes(value={“user1”, “user2”}, types={Dept.class})
-
注意:該註解只能放在類的上面。 而不能修飾方法.
11.4 @ModelAttribute
- 在方法定義上使用 @ModelAttribute 註解:Spring MVC在調用目標處理方法前,會先逐個調用在方法級上標註了
@ModelAttribute 的方法。
- 注意:在@ModelAttribute修飾的方法中,放入到Map時的鍵需要和目標方法入參類型的第一個字母小寫的字符串一致!
- @ModelAttribute註解也可以來修飾目標方法POJO類型的入參,其value屬性值有如下的作用:
SpringMVC會使用value屬性值在implicitModel中查找對應的對象,若存在則會直接傳入到目標方法的入參中。
11.5 SpringMVC確定目標方法POJO類型入參的過程
- 確定一個key:若目標方法的P0JO類型的參數沒有使用@ModelAttribute作爲修飾,則key爲POJO類名第一個字母的小寫,若使用了@ModelAttribute 來修飾,則key爲@ModelAttribute註解的value屬性值
- 在implicitModel中查找key對應的對象,若存在,則作爲入參傳入
- 若implicitModel中不存在key對應的對象,則檢查當前的Handler是否使用@SessionAttributes註解修飾,
若使用了該註解,且@SessionAttributes註解的value屬性值中包含了key,則會從HttpSession中來獲取key所對應的value值,若存在則直接傳入到目標方法的入參中。若不存在則將拋出異常. - 若Handler沒有標識@SessionAttributes註解或@Sess ionAttributes註解的value值中不包含key,則
會通過反射來創建P0JO類型的參數,傳入爲目標方法的參數 - SpringMVC 會把key和value保存到implicitModel中,進而會保存到request中.
12. Spring MVC如何解析視圖
-
請求處理方法執行完成後,最終返回一個 ModelAndView對象。對於那些返回 String,View 或 ModeMap 等類型的處理方法,Spring MVC 也會在內部將它們裝配成一個ModelAndView 對象,它包含了邏輯名和模型對象的視圖
-
Spring MVC 藉助視圖解析器**(**ViewResolver)得到最終 的視圖對象(View),最終的視圖可以是 JSP ,也可能是Excel、JFreeChart 等各種表現形式的視圖
-
對於最終究竟採取何種視圖對象對模型數據進行渲染,s處理器並不關心,處理器工作重點聚焦在生產模型數據的工作上,從而實現 MVC 的充分解耦
13. 關於重定向
-
一般情況下,控制器方法返回字符串類型的值會被當成邏輯視圖名處理
-
如果返回的字符串中帶 forward: 或 redirect: 前綴 時,SpringMVC 會對他們進行特殊處理:將 forward: 和redirect: 當成指示符,其後的字符串作爲 URL 來處理
-
redirect:success.jsp:會完成一個到 success.jsp 的重定向的操作
-
forward:success.jsp:會完成一個到 success.jsp 的轉發操作
14. Spring 的表單標籤
通過 SpringMVC 的表單標籤可以實現將模型數據中的屬性和 HTML 表單元素相綁定,以實現表單數據更便捷編輯和表單值的回顯
14.1 form 標籤
- 一般情況下,通過 GET 請求獲取表單頁面,而通過POST 請求提交表單頁面,因此獲取表單頁面和提交表單
頁面的 URL 是相同的。只要滿足該最佳條件的契約,<form:form> 標籤就無需通過 action 屬性指定表單提交的 URL
- 可以通過 modelAttribute 屬性指定綁定的模型屬性,若沒有指定該屬性,則默認從 request 域對象中讀取command 的表單 bean,如果該屬性值也不存在,則會 發生錯誤。
14.2 表單標籤
SpringMVC 提供了多個表單組件標籤,如
-
<form:input/>、<form:select/> 等,用以綁定表單字段的屬性值,它們的共有屬性如下:
- path:表單字段,對應 html 元素的 name 屬性,支持級聯屬性
- htmlEscape:是否對錶單值的 HTML 特殊字符進行轉換,默認值爲 true
- cssClass:表單組件對應的 CSS 樣式類名
- cssErrorClass:表單組件的數據存在錯誤時,採取的 CSS 樣式
-
form:input、form:password、form:hidden、form:textarea, 對應 HTML 表單的 text、password、hidden、textarea 標籤
-
form:radiobutton:單選框組件標籤,當表單 bean 對應的屬性值和 value 值相等時,單選框被選中
-
form:radiobuttons:單選框組標籤,用於構造多個單選框
- items:可以是一個 List、String[] 或 Map
- itemValue:指定 radio 的 value 值。可以是集合中 bean 的一個屬性值
- itemLabel:指定 radio 的 label 值
- delimiter:多個單選框可以通過 delimiter 指定分隔符
-
form:checkbox:複選框組件。用於構造單個複選框
-
form:checkboxs:用於構造多個複選框。使用方式同form:radiobuttons 標籤
-
form:select:用於構造下拉框組件。使用方式同form:radiobuttons 標籤
-
form:option:下拉框選項組件標籤。使用方式同form:radiobuttons 標籤
-
form:errors:顯示錶單組件或數據校驗所對應的錯誤
- <form:errors path= “ ” /> :顯示錶單所有的錯誤
- <form:errors path= “ user” /> :顯示所有以 user 爲前綴的屬性對應的錯誤
- <form:errors path= “ username” /> :顯示特定表單對象屬性的錯誤
15. 處理靜態資源
優雅的 REST 風格的資源URL 不希望帶 .html 或 .do 等後綴
-
若將 DispatcherServlet 請求映射配置爲 /,則 Spring MVC 將捕獲WEB 容器的所有請求,包括靜態資源的請求, SpringMVC 會將他們當成一個普通請求處理,因找不到對應處理器將導致錯誤。
-
可以在 SpringMVC 的配置文件中配置 <mvc:default-servlet-handler/> 的方式解決靜態資源的問題:
-
<mvc:default-servlet-handler/> 將在 SpringMVC 上下文中定義一個DefaultServletHttpRequestHandler,它會對進入 DispatcherServlet 的 請求進行篩查,如果發現是沒有經過映射的請求,就將該請求交由 WEB 應用服務器默認的 Servlet 處理,如果不是靜態資源的請求,才由DispatcherServlet 繼續處理
-
一般 WEB 應用服務器默認的 Servlet 的名稱都是 default。若所使用的WEB 服務器的默認 Servlet 名稱不是 default,則需要通過 default-servlet-name 屬性顯式指定
16. 數據綁定流程
-
Spring MVC 主框架將 ServletRequest 對象及目標方法的入參實例傳遞給 WebDataBinderFactory 實例,以創建 DataBinder 實例對象
-
DataBinder 調用裝配在 Spring MVC 上下文中的ConversionService 組件進行數據類型轉換、數據格式化工作。將 Servlet 中的請求信息填充到入參對象中
-
調用 Validator 組件對已經綁定了請求消息的入參對象 進行數據合法性校驗,並最終生成數據綁定結果BindingData 對象
-
Spring MVC 抽取 BindingResult 中的入參對象和校驗錯誤對象,將它們賦給處理方法的響應入參
17. Springmvc自帶轉換器類型(部分)
-
java.lang.Boolean -> java.lang.String
-
java.lang.Character -> java.lang.Number
-
java.lang.Character -> java.lang.String
-
java.lang.Enum -> java.lang.String
-
java.lang.Number -> java.lang.Character
-
java.lang.Number -> java.lang.Number
-
java.lang.Number -> java.lang.String
-
java.lang.String -> java.lang.Boolean
-
java.lang.String -> java.lang.Character
-
java.lang.String -> java.lang.Enum
-
java.lang.String -> java.lang.Number
-
java.lang.String -> java.util.Locale
-
java.lang.String -> java.util.Properties
-
java.lang.String -> java.util.UUID
-
java.util.Locale -> java.lang.String
-
java.util.Properties -> java.lang.String
-
java.util.UUID -> java.lang.String
18. 自定義類型轉換器
-
ConversionService 是 Spring 類型轉換體系的核心接口。
-
可以利用 ConversionServiceFactoryBean 在 Spring 的 IOC 容器中定義一個 ConversionService. Spring 將自動識別出IOC 容器中的 ConversionService,並在 Bean 屬性配置及Spring MVC 處理方法入參綁定等場合使用它進行數據的轉換
-
可通過 ConversionServiceFactoryBean 的 converters 屬性註冊自定義的類型轉換器
Spring 定義了 3 種類型的轉換器接口,實現任意一個轉換器接口都可以作爲自定義轉換器註冊到ConversionServiceFactroyBean 中:
-
Converter<S,T>(一般用這種):將 S 類型對象轉爲 T 類型對象
-
ConverterFactory:將相同系列多個 “同質” Converter 封裝在一起。如果希望將一種類型的對象轉換爲另一種類型及其子類的對象(例如將 String 轉換爲 Number 及 Number 子類 (Integer、Long、Double 等)對象)可使用該轉換器工廠類
-
GenericConverter:會根據源類對象及目標類對象所在的宿主類 中的上下文信息進行類型轉換
- <mvc:annotation-driven conversion-service=“conversionService”/> 會將自定義的 ConversionService 註冊到Spring MVC 的上下文中
19. 關於 mvc:annotation-driven
- <mvc:annotation-driven /> 會自動注 冊RequestMappingHandlerMapping、RequestMappingHandlerAdapter 與
ExceptionHandlerExceptionResolver 三個bean。
- 還將提供以下支持:
- 支持使用 ConversionService 實例對錶單參數進行類型轉換
- 支持使用 @NumberFormat annotation、@DateTimeFormat註解完成數據類型的格式化
- 支持使用 @Valid 註解對 JavaBean 實例進行 JSR 303 驗證
- 支持使用 @RequestBody 和 @ResponseBody 註解
20. @InitBinder
-
由 @InitBinder 標識的方法,可以對 WebDataBinder 對象進行初始化。WebDataBinder 是 DataBinder 的子類,用於完成由表單字段到 JavaBean 屬性的綁定
-
@InitBinder方法不能有返回值,它必須聲明爲void。
-
@InitBinder方法的參數通常是是 WebDataBinder
21. 數據格式化
-
對屬性對象的輸入/輸出進行格式化,從其本質上講依然屬於 “類型轉換” 的範疇。
-
Spring 在格式化模塊中定義了一個實現ConversionService 接口的FormattingConversionService 實現類,該實現類擴展 了 GenericConversionService,因此它既具有類型轉換的功能,又具有格式化的功能
-
FormattingConversionService 擁有一個FormattingConversionServiceFactroyBean 工廠類,後者用於在 Spring 上下文中構造前者
-
FormattingConversionServiceFactroyBean 內部已經註冊了 :
-
NumberFormatAnnotationFormatterFactroy:支持對數字類型的屬性使用 @NumberFormat 註解
-
JodaDateTimeFormatAnnotationFormatterFactroy:支持對日期類型的屬性使用 @DateTimeFormat 註解
-
裝配了 FormattingConversionServiceFactroyBean 後,就可以在 Spring MVC 入參綁定及模型數據輸出時使用註解驅動了。<mvc:annotation-driven/> 默認創建的ConversionService 實例即爲FormattingConversionServiceFactroyBean
21.1 日期格式化
- @DateTimeFormat 註解可對java.util.Date、java.util.Calendar、java.long.Long 時間類型進行標註:
- pattern 屬性:類型爲字符串。指定解析/格式化字段數據的模式,如:”yyyy-MM-dd hh:mm:ss”
- iso 屬性:類型爲 DateTimeFormat.ISO。指定解析/格式化字段數據的ISO模式,包括四種:ISO.NONE(不使用) – 默 認、ISO.DATE(yyyy-MM-dd) 、ISO.TIME(hh:mm:ss.SSSZ)、ISO.DATE_TIME(yyyy-MM-dd hh:mm:ss.SSSZ)
- style 屬性:字符串類型。通過樣式指定日期時間的格式,由兩位字符組成,第一位表示日期的格式,第二位表示時間的格式:S:短日期/時間格式、M:中日期/時間格式、L:長日期/時間格式、F:完整日期/時間格式、-:忽略日期或時間格式
21.2 數值格式化
- @NumberFormat 可對類似數字類型的屬性進行標註,它擁有兩個互斥的屬性:
- style:類型爲 NumberFormat.Style。用於指定樣式類型,包括三種:Style.NUMBER(正常數字類型)、Style.CURRENCY(貨幣類型)、 Style.PERCENT(百分數類型)
- pattern:類型爲 String,自定義樣式,如patter="#,###";
22. 校驗
22.1 JSR 303
-
JSR 303 是 Java 爲 Bean 數據合法性校驗提供的標準框架,它已經包含在 JavaEE 6.0 中 .
-
JSR 303 通過在 Bean 屬性上標註類似於 @NotNull、@Max 等標準的註解指定校驗規則,並通過標準的驗證接口對 Bean 進行驗證
22.2 Hibernate Validator 擴展註解
- Hibernate Validator 是 JSR 303 的一個參考實現,除支持所有標準的校驗註解外,它還支持以下的擴展註解
22.3 Spring MVC 數據校驗
-
Spring 4.0 擁有自己獨立的數據校驗框架,同時支持 JSR 303 標準的校驗框架。
-
Spring 在進行數據綁定時,可同時調用校驗框架完成數據校驗工作。在 Spring MVC 中,可直接通過註解驅動的方式進行數據校驗
-
Spring 的 LocalValidatorFactroyBean 既實現了 Spring 的Validator 接口,也實現了 JSR 303 的 Validator 接口。只要在 Spring 容器中定義了一個LocalValidatorFactoryBean,即可將其注入到需要數據校驗的 Bean 中。
-
Spring 本身並沒有提供 JSR303 的實現,所以必須將JSR303 的實現者的 jar 包放到類路徑下。
-
<mvc:annotation-driven/> 會默認裝配好一個LocalValidatorFactoryBean,通過在處理方法的入參上標 注 @valid 註解即可讓 Spring MVC 在完成數據綁定後執行數據校驗的工作
-
在已經標註了 JSR303 註解的表單/命令對象前標註一個@Valid,Spring MVC 框架在將請求參數綁定到該入參對象後,就會調用校驗框架根據註解聲明的校驗規則實施校驗
-
Spring MVC 是通過對處理方法簽名的規約來保存校驗結果的:前一個表單/命令對象的校驗結果保存到隨後的入參中,這個保存校驗結果的入參必須是 BindingResult 或Errors 類型,這兩個類都位於org.springframework.validation 包中
22.4 在目標方法中獲取校驗結果
-
在表單/命令對象類的屬性中標註校驗註解,在處理方法對 應的入參前添加 @Valid,Spring MVC 就會實施校驗並將校驗結果保存在被校驗入參對象之後的 BindingResult 或Errors 入參中。
-
常用方法:
- FieldError getFieldError(String field)
- List<FieldError> getFieldErrors()
- Object getFieldValue(String field)
- Int getErrorCount()
23. 提示消息的國際化
-
每個屬性在數據綁定和數據校驗發生錯誤時,都會生成一個對應的 FieldError 對象。
-
當一個屬性校驗失敗後,校驗框架會爲該屬性生成 4 個消息代碼,這些代碼以校驗註解類名爲前綴,結合modleAttribute、屬性名及屬性類型名生成多個對應的消息代碼:例如 User 類中的 password 屬性標準了一個 @Pattern 註解,當該屬性值不滿足 @Pattern 所定義的規則時, 就會產生以下 4 個錯誤代碼:
- Pattern.user.password
- Pattern.password
- Pattern.java.lang.String
- Pattern
-
當使用 Spring MVC 標籤顯示錯誤消息時, Spring MVC 會查看WEB 上下文是否裝配了對應的國際化消息,如果沒有,則顯示默認的錯誤消息,否則使用國際化消息。
-
若數據類型轉換或數據格式轉換時發生錯誤,或該有的參數不存在,或調用處理方法時發生錯誤,都會在隱含模型中創建錯誤消息。其錯誤代碼前綴說明如下:
- required:必要的參數不存在。如 @RequiredParam(“param1”) 標註了一個入參,但是該參數不存在
- typeMismatch:在數據綁定時,發生數據類型不匹配的問題
- methodInvocation:Spring MVC 在調用處理方法時發生了錯誤
-
註冊國際化資源文件
24. 處理 JSON
- 加入 jar 包
-
編寫目標方法,使其返回 JSON 對應的對象或集合
-
在方法上添加 @ResponseBody 註解
25. HttpMessageConverter<T>
-
HttpMessageConverter 是 Spring3.0 新添加的一個接口,負責將請求信息轉換爲一個對象(類型爲 T),將對象(類型爲 T)輸出爲響應信息
-
HttpMessageConverter接口定義的方法:
- Boolean canRead(Class<?> clazz,MediaType mediaType): 指定轉換器可以讀取的對象類型,即轉換器是否可將請求信息轉換爲 clazz 類型的對象,同時指定支持 MIME 類型(text/html,applaiction/json等)
- Boolean canWrite(Class<?> clazz,MediaType mediaType):指定轉換器是否可將 clazz 類型的對象寫到響應流中,響應流支持的媒體類型 在MediaType 中定義。
- LIst<MediaType> getSupportMediaTypes():該轉換器支持的媒體類型。
- T read(Class<? extends T> clazz,HttpInputMessage inputMessage): 將請求信息流轉換爲 T 類型的對象。
- void write(T t,MediaType contnetType,HttpOutputMessgaeoutputMessage):將T類型的對象寫到響應流中,同時指定相應的媒體類 型爲 contentType。
25.1 使用 HttpMessageConverter<T>
-
使用 HttpMessageConverter<T> 將請求信息轉化並綁定到處理方法的入參中或將響應結果轉爲對應類型的響應信息,Spring 提供了兩種途徑:
- 使用 @RequestBody / @ResponseBody 對處理方法進行標註
- 使用 HttpEntity<T> / ResponseEntity<T> 作爲處理方法的入參或返回值
-
當控制器處理方法使用到 @RequestBody/@ResponseBody 或HttpEntity/ResponseEntity 時, Spring 首先根據請求頭或響應頭的Accept 屬性選擇匹配的 HttpMessageConverter, 進而根據參數類型或泛型類型的過濾得到匹配的 HttpMessageConverter, 若找不到可用的HttpMessageConverter 將報錯
-
@RequestBody 和 @ResponseBody 不需要成對出現
25.2 @RequestBody、@ResponseBody 示例
26. 國際化概述
-
默認情況下,SpringMVC 根據 Accept-Language 參數判斷客戶端的本地化類型。
-
當接受到請求時,SpringMVC 會在上下文中查找一個本地化解析器(LocalResolver),找到後使用它獲取請求 所對應的本地化類型信息。
-
SpringMVC 還允許裝配一個動態更改本地化類型的攔截器,這樣通過指定一個請求參數就可以控制單個請求的本地化類型。
26.1 本地化解析器和本地化攔截器
-
AcceptHeaderLocaleResolver:根據 HTTP 請求頭的Accept-Language 參數確定本地化類型,如果沒有顯式定義本地化解析器, SpringMVC 使用該解析器。
-
CookieLocaleResolver:根據指定的 Cookie 值確定本地化類型
-
SessionLocaleResolver:根據 Session 中特定的屬性確定本地化類型
-
LocaleChangeInterceptor:從請求參數中獲取本次請求對應的本地化類型。
27. 文件上傳
-
Spring MVC 爲文件上傳提供了直接的支持,這種支持是通過即插即用的 MultipartResolver 實現的。Spring 用Jakarta Commons FileUpload 技術實現了一個MultipartResolver 實現類:CommonsMultipartResovler
-
Spring MVC 上下文中默認沒有裝配 MultipartResovler,因此默認情況下不能處理文件的上傳工作,如果想使用 Spring 的文件上傳功能,需現在上下文中配置 MultipartResolver
27.1 配置 MultipartResolver
-
defaultEncoding: 必須和用戶 JSP 的 pageEncoding 屬性一致,以便正確解析表單的內容
-
爲了讓 CommonsMultipartResovler 正確工作,必須先 將 Jakarta Commons FileUpload 及 Jakarta Commons io的類包添加到類路徑下。
27.2 文件上傳示例
28. 自定義攔截器
- Spring MVC也可以使用攔截器對請求進行攔截處理,用戶可以自定義攔截器來實現特定的功能,自定義的攔截器必須實現HandlerInterceptor接口
- preHandle():這個方法在業務處理器處理請求之前被調用,在該方法中對用戶請求 request 進行處理。如果程序員決定該攔截器對 請求進行攔截處理後還要調用其他的攔截器,或者是業務處理器去進行處理,則返回true;如果程序員決定不需要再調用其他的組件 去處理請求,則返回false。
- postHandle():這個方法在業務處理器處理完請求後,但是DispatcherServlet 向客戶端返回響應前被調用,在該方法中對 用戶請求request進行處理。
- afterCompletion():這個方法在 DispatcherServlet 完全處理完請求後被調用,可以在該方法中進行一些資源清理的操作。
28.1 攔截器方法執行順序
如果有一個攔截器的preHandle返回的是true,則一定會執行這個攔截器的afterCompletion釋放資源
28.2 配置自定義攔截器
28.3 對指定請求啓用攔截器
29. 異常處理
-
Spring MVC 通過 HandlerExceptionResolver 處理程序的異常,包括 Handler 映射、數據綁定以及目標方法執行時發生的異常。
-
SpringMVC 提供的 HandlerExceptionResolver 的實現類
29.1 ExceptionHandlerExceptionResolver
-
主要處理 Handler 中用 @ExceptionHandler 註解定義的方法。
-
@ExceptionHandler 註解定義的方法優先級問題:例如發生的是NullPointerException,但是聲明的異常有RuntimeException 和 Exception,此候會根據異常的最近繼承關係找到繼承深度最淺的那個 @ExceptionHandler註解方法,即標記了 RuntimeException 的方法
-
ExceptionHandlerMethodResolver 內部若找不到@ExceptionHandler 註解的話,會找 @ControllerAdvice 中的 @ExceptionHandler 註解方法
-
在@ExceptionHandler方法的入參中可以加入Exception類型的參數,該參數即對應發生的異常對象
-
@ExceptionHandler方法的入參中不能傳入Map.若希望把異常信息傳導頁面上,需要使用ModelAndView作爲返回值
-
@ExceptionHandler方法標記的異常有優先級的問題.(越具體越優先)
-
@ControllerAdvice: 如果在當前Handler中找不到@ExceptionHandler方法來出來當前方法出現的異常,則將去@ControllerAdvice標記的類中查找@ExceptionHandler標記的方法來處理異常.
29.2 ResponseStatusExceptionResolver
-
在異常及異常父類中找到 @ResponseStatus 註解,然後使用這個註解的屬性進行處理。
-
定義一個 @ResponseStatus 註解修飾的異常類
- 若在處理器方法中拋出了上述異常: 若ExceptionHandlerExceptionResolver 不解析述異常。由於觸發的異常 UnauthorizedException 帶有@ResponseStatus註解。因此會被ResponseStatusExceptionResolver 解析到。最後響應HttpStatus.UNAUTHORIZED 代碼給客戶端。HttpStatus.UNAUTHORIZED 代表響應碼401,無權限。關於其他的響應碼請參考 HttpStatus 枚舉類型源碼。
29.3 DefaultHandlerExceptionResolver
- 對一些特殊的異常進行處理,比如NoSuchRequestHandlingMethodException、HttpRequestMethodNotSupportedException、HttpMediaTypeNotSupportedException、HttpMediaTypeNotAcceptableException等。
29.4 SimpleMappingExceptionResolver
- 如果希望對所有異常進行統一處理,可以使用SimpleMappingExceptionResolver,它將異常類名映射爲視圖名,即發生異常時使用對應的視圖報告異常,SpringMVC會自動將exception傳入到頁面中