前言:本篇主要介紹SpringMVC的資料綁定流程中資料校驗的相關概念與用法。
本篇文章重點關注以下問題:
- JSR303校驗架構
- Spring内置的驗證限制注解
1. JSR303校驗架構
JSR 303 是 Java 為 Bean 資料合法性校驗提供的标準架構,它已經包含在 JavaEE 6.0 中。JSR 303 通過在 Bean 屬性上标注類似于 @NotNull、@Max等标準的注解指定校驗規則,并通過标準的驗證接口對 Bean 進行驗證。
JSR303 校驗架構注解類:
- @NotNull 注解元素必須是非空
- @Null 注解元素必須是空
- @Digits 驗證數字構成是否合法
- @Future 驗證是否在目前系統時間之後
- @Past 驗證是否在目前系統時間之前
- @Max 驗證值是否小于等于最大指定整數值
- @Min 驗證值是否大于等于最小指定整數值
- @Pattern 驗證字元串是否比對指定的正規表達式
- @Size 驗證元素大小是否在指定範圍内
- @DecimalMax 驗證值是否小于等于最大指定小數值
- @DecimalMin 驗證值是否大于等于最小指定小數值
- @AssertTrue 被注釋的元素必須為true
- @AssertFalse 被注釋的元素必須為false
Hibernate Validator 是 JSR 303 的一個參考實作,除支援所有标準的校驗注解外,它還支援以下的擴充注解
HibernateValidator 擴充
- @Email 被注釋的元素必須是電子郵箱位址
- @Length 被注釋的字元串的大小必須在指定的範圍内
- @NotEmpty 被注釋的字元串的必須非空
- @Range 被注釋的元素必須在合适的範圍内
2. SpringMVC資料校驗架構
Spring 4.0 擁有自己獨立的資料校驗架構,同時支援 JSR303 标準的校驗架構。Spring 在進行資料綁定時,可同時調用校驗架構完成資料校驗工作。在 Spring MVC 中,可直接通過注解驅動的方式進行資料校驗。
Spring 本身并沒有提供 JSR303 的實作,是以必須将JSR303 的實作者的 jar 包放到類路徑下,Hibernate Validator 是經常被使用的JSR303校驗架構。
<mvc:annotation-driven/> 會預設裝配好一個LocalValidatorFactoryBean,通過在處理方法的入參上标注 @valid 注解即可讓 Spring MVC 在完成資料綁定後執行資料校驗的工作。在已經标注了 JSR303 注解的表單/指令對象前标注一個@Valid,Spring MVC 架構在将請求參數綁定到該入參對象後,就會調用校驗架構根據注解聲明的校驗規則實施校驗。Spring MVC 是通過對處理方法簽名的規約來儲存校驗結果的前一個表單/指令對象的校驗結果儲存到随後的入參中,這個儲存校驗結果的入參必須是 BindingResult 或Errors 類型。
需要聲明的是,需校驗的 Bean 對象和其綁定結果對象或錯誤對象時成對出現的,它們之間不允許聲明其他的入參。

在表單/指令對象類的屬性中标注校驗注解,在處理方法對應的入參前添加 @Valid,Spring MVC 就會實施校驗并将校驗結果儲存在被校驗入參對象之後的 BindingResult 或Errors入參中。
常用的方法有:
- FieldError getFieldError(String field)
- List<FieldError> getFieldErrors()
- Object getFieldValue(String field)
- Int getErrorCount()
補充說明:
Spring MVC 除了會将表單/指令對象的校驗結果儲存到對應的 BindingResult或 Errors 對象中外,還會将所有校驗結果儲存到“隐含模型”,即使處理方法的簽名中沒有對應于表單/指令對象的結果入參,校驗結果也會儲存在 “隐含對象” 中。隐含模型中的所有資料最終将通過HttpServletRequest的屬性清單暴露給JSP 視圖對象,是以在 JSP 中可以擷取錯誤資訊,在 JSP 頁面上可通過 <form:errors path=“userName”> 顯示錯誤消息。
3. 示例示範
在背景接收實體類中進行如下配置,詳細代碼可見附件:
@NotEmpty
private String username;
@Past
private Date birth;
@Email
private String email;
如果配置了<mvc:annotation-driven/>,會預設支援上述校驗注解。用起來比較簡單,
測試結果如下:
代碼下載下傳來源:http://super-wangj.iteye.com/blog/2388430