1. Hibernate Validator介紹
1.1 背景
在任何時候,當你要處理一個應用程序的業務邏輯,數據校驗是你必須要考慮和面對的事情。應用程序必須通過某種手段來確保輸入進來的數據從語義上來講是正確的。在通常的情況下,應用程序是分層的,不同的層由不同的開發人員來完成。很多時候同樣的數據驗證邏輯會出現在不同的層,這樣就會導致代碼冗余和一些管理的問題,比如說語義的一致性等。為了避免這樣的情況發生,最好是將驗證邏輯與相應的域模型進行綁定。
Bean Validation 為 JavaBean 驗證定義了相應的元數據模型和API。缺省的元數據是 Java Annotations,通過使用 XML 可以對原有的元數據信息進行覆蓋和擴展。Bean Validation 是一個運行時的數據驗證框架,在驗證之后驗證的錯誤信息會被馬上返回。
Hibernate Validator 是 Bean Validation 的參考實現 . Hibernate Validator 提供了 JSR 303 規范中所有內置 constraint 的實現,除此之外還有一些附加的 constraint。
1.2 Bean Validation 中的 constraint

1.3 Hibernate Validator 附加的 constraint

1.4 Hibernate Validator 的優點
a) 驗證邏輯與業務邏輯之間進行了分離,降低了程序耦合度;
b) 統一且規范的驗證方式,無需你再次編寫重復的驗證代碼;
c) 你將更專注於你的業務,將這些繁瑣的事情統統丟在一邊。
2. Hibernate Validator實踐
2.1 引入相關jar包
maven依賴:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.2.0.Final</version>
</dependency>
2.2 SpringMvc中配置
本篇文章的demo是基於springmvc的,需要進行相關配置。


2.3 為JavaBean添加constraint
如圖為User添加了幾個constraint:對name添加了不為空和長度的約束;對sex添加了自定義的約束,后面會加以介紹;對role的約束為對象內嵌約束。JSR-303的校驗是基於注解的,它內部已經定義好了一系列的限制注解,我們只需要把這些注解標記在需要驗證的實體類的屬性上或是其對應的get方法上。
2.4 自定義的 constraint

如圖定義了一個ValidSex的注解,而且該注解上標注了@Constraint注解,使用@Constraint注解標注表明我們定義了一個用於限制的注解。@Constraint注解的validatedBy屬性用於指定我們定義的當前限制類型需要被哪個ConstraintValidator進行校驗。在上面代碼中我們指定了ValidSex限制類型的校驗類是ValidSexValidator。另外需要注意的是我們在定義自己的限制類型的注解時有三個屬性是必須定義的,如上面代碼所示的message、groups和payload屬性。
2.5 自定義的 constraint實現類

如圖,ConstraintValidator是使用了泛型的。它一共需要指定兩種類型,第一個類型是對應的initialize方法的參數類型,第二個類型是對應的isValid方法的第一個參數類型。從上面的兩個方法我們可以看出initialize方法是可以獲取到當前的限制類型的屬性,isValid方法是用於進行校驗的。
2.6 對參數進行校驗

在上圖中我們可以看到我們定義了一個LoginController,該Controller有一個處理validator操作的處理器方法validator,它需要接收客戶端發送的一個User對象,我們就是要利用前面的Validator對該User對象進行校驗。首先我們可以看到我們validator方法接收的參數user是用@Valid進行標注的。另外我們的處理器方法必須給定包含Errors的參數,這可以是Errors本身,也可以是它的子類BindingResult,使用了Errors參數就是告訴Spring關於表單對象數據校驗的錯誤將由我們自己來處理,否則Spring會直接拋出異常。這樣當我們請求處理器方法validator時就會對user對象進行校驗,並把相關的校驗信息存放到當前的Errors對象中。接着我們就可以在我們的處理器方法中根據是否有校驗異常信息來做不同的操作。在上面代碼中我們定義了在有異常信息的時候就跳轉到登陸頁面。這樣我們就可以在登陸頁面上通過errors標簽來展示這些錯誤信息了。
2.7 注意事項
a) 如果驗證的是屬性(getter 方法),那么必須遵從 Java Bean 的命名習慣(JavaBeans 規范);
b) 靜態的字段和方法不能進行約束驗證;
c) 約束適用於接口和基類;
d) 約束注解定義的目標元素可以是字段、屬性或者類型等;
e) 可以在類或者接口上使用約束驗證,它將對該類或實現該接口的實例進行狀態驗證;
f) 字段和屬性均可以使用約束驗證,但是不能將相同的約束重復聲明在字段和相關屬性(字段的 getter 方法)上。
結束語:善待身邊每一個人,因為,是他們成就了你的人生。
可愛博主:AlanLee
博客地址:http://www.cnblogs.com/AlanLee
本文出自博客園,歡迎大家加入博客園。

