Spring MVC 3 中的 Bean Validate

  原文

JSR  303  - Bean  Validation  - 爲實體驗證定義了元數據模型和API. 默認的元數據模型是通過Annotations來描述的,但是也可以使用XML來重載或者擴展. Bean Validation API 並不侷限於應用程序的某一層或者哪種編程模型, Bean Validation 可以被用在任何一層, 或者是像類似Swing的富客戶端程序中.

Hibernate Validate 4 是Bean Validate 最好的實現.這裏主要講Hibernate Validate 在Spring MVC 中怎麼去驗證數據.Bean Validation 的約束是通過Java註解(annotations)來標註的.約束條件能夠被標註在類的字段,屬性,方法以及類上面,沒有對象可以有多個約束.當約束被定義在字段上的時候,這個字段的值是通過字段訪問策略來獲取並驗證的.也就是說Bean  Validation的實現者會直接訪問這個實例變量而不會調用屬性的訪問器(getter)即使這個方法存在.(靜態字段或者屬性是不會被校驗的.這個字段的訪問級別( private,protected 或者 public) 對此沒有影響.)


通常的屬性,方法,字段的約束有:

@AssertFalse Checks thatthe annotated element is false.

@AssertTrue Checks thatthe annotated element is true.

@DecimalMax 被標註的值必須不大於約束中指定的最大值. 這個約束的參數是一個通過BigDecimal定義的最大值的字符串表示.

@DecimalMin 被標註的值必須不小於約束中指定的最小值. 這個約束的參數是一個通過BigDecimal定義的最小值的字符串表示.

@Digits(integer=,fraction=)Checks whetherthe annoted value is a number having up to integer digitsand fraction fractional digits.

@Future 檢查給定的日期是否比現在晚.

@Max 檢查該值是否小於或等於約束條件中指定的最大值.

@Min 檢查該值是否大於或等於約束條件中規定的最小值.

@NotNull Checks thatthe annotated value is not null.

@Null Checks thatthe annotated value is null.

@Past檢查標註對象中的值表示的日期比當前早.

@Pattern(regex=,flag=) 檢查該字符串是否能夠在match指定的情況下被regex定義的正則表達式匹配.

@Size(min=, max=) Checks ifthe annotated element's size is between min andmax (inclusive).

@Valid遞歸的對關聯對象進行校驗, 如果關聯對象是個集合或者數組,那麼對其中的元素進行遞歸校驗,如果是一個map,則對其中的值部分進行校驗.(是否進行遞歸驗證)

@CreditCardNumber信用卡驗證

@Email Checks whetherthe specified string is a valid email address.

@Length(min=,max=)Validates that the annotated string is between min andmax included.

@NotBlank檢查約束字符串是不是Null還有被Trim的長度是否大於0,與@NoEmpty不同的是該約束只對字符串且會自動忽略尾空格.

@NotEmpty檢查約束元素是否爲NULL或者是EMPTY.

@Range(min=,max=)Checks whether the annotated value lies between (inclusive)the specified minimum and maximum.

@ScriptAssert(lang= ,script=,alias=)

@URL(protocol=,host=,port=,regexp=, flags=)


驗證組

驗證組就是把一個域模型對象中的驗證規則劃分到不同的組別,分開驗證,這對於複雜的業務情況很有用。每一個約束註解都有一個groups屬性,用於指定一個接口的Class對象,沒有傳遞這個組別參數的約束也就是默認爲javax.validation.groups.Default。一旦一個約束註解使用了groups 屬性,那麼它將不再屬於默認的組別。其實每一個組別就是一個空的接口,這裏爲什麼使用接口而不是字符串呢?因爲字符串不能被編譯器識別。例如:某個組別改變了,使用接口,編譯器會編譯出錯,這樣就會提醒你改變原來的組別。如果要是字符串呢?那就很麻煩了,你需要找遍所有的JAVA 源文件,去改曾經用過的組別字符串名稱。

(1)組別序列組別序列可以把一系列的組別按照一定的順序排列在一起,然後逐個驗證,只要有一個組別驗證失敗,就不繼續驗證剩餘的組別。使用javax.validation.GroupSequence的好處是驗證順序有了保證,另外,“短路”驗證也可以生效,也就是隻要遇到不合法的約束,就不繼續其他的約束驗證。但要注意的是驗證序列中的引用關係不要形成閉環,也就是G3裏包含G1、G2,而G1裏又包含G3,這樣就會形成死循環,JSR 303會拋出javax.validation.GroupDefinitionException異常。

(2)覆蓋javax.validation. groups.Default如果你想覆蓋默認的 Default 驗證,那麼可以在驗證的類上使用@GroupSequence 註解,但要注意序列中必須包含當前的類,且不能包含 Default組別。


Spring MVC中應用Hibernate Validate:

1.User.class

@GroupSequence({ User.class, GroupB.class, GroupC.class })
public class User {

	@NotEmpty(message = "用戶名不能爲空")
	private String name;// message可以用來指定ErrorMessage.否則由Hibernate Validate默認.

	@NotEmpty(message = "密碼不能爲空")
	@Size(min = 4, max = 20, message = "密碼長度必須在{min}-{max}範圍內", groups = GroupB.class)
	private String password;

	// setter andgetter

}

interface GroupB {
}

interface GroupC {
}


 

@NotEmpty沒有定義Group,則爲默認的User.class,則會優先驗證,如果不通過則不會繼續驗證GroupB.class組的,以及GroupC.class組的.

 

2.Controller中方法的處理.

  
@RequestMapping(method =RequestMethod.POST)
public ModelAndViewaddUser(@Valid User user,BindingResult result){
	//@Valid Useruser 會將驗證user,然後把結果賦值給result.當參數傳進來.
	...
	if(result.hasFieldErrors()){ //判斷驗證是否出錯.
		List<FieldError> fes= result.getFieldErrors();
		for(FieldError fe : fes){
			System.out.println("FieldError : "+fe.getField()+" :"+fe.getDefaultMessage());
			//getField()獲取出錯的對象名.
			//getDefaultMessage()獲取出錯的信息.
			model.put(fe.getField()+"msg",fe.getDefaultMessage()); 
		}
	}
	...
	return ... ;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章