在基於SpringMVC框架的開發中,我們經常要對使用者提交的欄位進行合法性驗證,比如整數型別的欄位有個範圍約束,我們會用@Range(min=1, max=4)
。在實際應用開發中,我們經常碰到一些自己業務的場景要自定義一些驗證規則,而這是標準的JSR-303
和Hibernate Validation
所不具備的,所以我們就要根據JSR-303
的規範來擴充套件我們自定義的驗證規則註釋
.
假設我們現在有個介面要接收一個手機
的欄位, 它的約束規則是13位數字字元. 我們可以通過正規表示式完成: ^\d{13}$
來驗證. 下面是個javabean程式碼:
public class Person{
@Phone
private String phone;
}
我們再來看下@Phone
的程式碼.
@Documented
@Constraint(validatedBy = PhoneConstraintValidator.class)
@Target( { ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Phone {
String message() default "{Phone}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
這個註解類看起來複雜, 其實不然. 因為這基本上每個擴充套件驗證註解都必需定義的三個方法, 是規範定義的, 所以我們可以像個模板一樣copy過來改下. 這裡要注意的是這個message
方法, 定義瞭如果驗證出錯時要顯示的訊息內容. 對於訊息格式和規範, 可以使用標準的Spring Message Resource Bindle
來, 可以參考這篇. 現在定義了註解, 正如你所料, 我們要定義下具體的業務規則:
public class PhoneConstraintValidator implements ConstraintValidator<Phone, String> {
@Override
public void initialize(Phone phone) { }
@Override
public boolean isValid(String phoneField, ConstraintValidatorContext cxt) {
if(phoneField == null) {
return false;
}
return phoneField.matches("^\d{13}$");
}
}
所有驗證規則方法類都要實現ConstraintValidator<V,F>
這個介面, 裡面第一個方法initialize
的引數是所關聯的註解物件, 所以這個方法裡可以取出使用註解的地方傳進來的值, 後面一個例子會講到這一點. 第二個最核心的方法isValid
第一個引數就是我們要驗證的欄位值, 大家看下上面的程式碼就知道怎樣使用了.
下面我們來看第二種形式的註解. 假如我們對使用者的生日欄位進行驗證, 限制只滿足1989年出生的人。 如下:
public class Person {
@Year(1989)
private Date birthday;
// getters setters ...
}
現在自定義驗證註解Year
有要傳入一個引數, 用預設的value
方法接收:
@Documented
@Constraint(validatedBy = YearConstraintValidator.class)
@Target( { ElementType.METHOD, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface Year {
int value();
String message() default "{Year}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
還是要上面的一樣, 要定義一個規則約束描述類:
public class YearConstraintValidator implements ConstraintValidator<Year, Date> {
private int annotationYear;
@Override
public void initialize(Year year) {
this.annotationYear = year.value();
}
@Override
public boolean isValid(Date target, ConstraintValidatorContext cxt) {
if(target == null) {
return true;
}
Calendar c = Calendar.getInstance();
c.setTime(target);
int fieldYear = c.get(Calendar.YEAR);
return fieldYear == annotationYear;
}
}
可以看到initiallize
方法中可以接收關聯的註解Year
, 這裡可以取出裡面的引數資訊用於約束規則方法呼叫.
原文: http://www.javacodegeeks.com/2013/07/spring-mvc-custom-validation-annotations.html