在項目開發過程當中,後臺在不少場景都須要進行校驗操做,好比:前臺表單提交到後臺,系統接口調用,數據傳輸等等。並且不少項目都採用MVC分層式設計,每層還有須要進行相應地校驗,這樣在項目較大,多人協做開發的時候,會形成大量重複校驗代碼,且出錯率高。javascript
針對這個問題,JCP出臺一個JSR 303-Bean Validation規範,而Hibernate Validator 做爲Bean Validation的參考實現,提供了JSR 303規範中全部內置constraint的實現,除此以外還有一些附加的constraint。html
Hibernate Validation的使用很是簡單,只用在相應的實體類中加上註解,再調用對應的校驗API方法便可。java
Hibernate Validation目前最新的穩定版本是:5.1.3。下載地址git
官網地址
官方英文使用手冊
官方中文使用手冊地址(中文版目前最新的是4.3版本)github
具體使用方法請查看上面的官方使用手冊地址,每一個註解對應的含義在官方手冊2.4章節有詳細介紹,內容太多我就不貼過來了。下面直接上最經常使用狀況(實體類校驗)的示例代碼。web
1、依賴包api
J2SE環境下除了須要引入Hibernate Validation包外,還須要額外引入兩個實現表達式語言的包。J2EE環境若是容器提供不須要再引入。下面是J2SE環境下的依賴包:app
Xml代碼 框架
![收藏代碼](http://static.javashuo.com/static/loading.gif)
- <dependency>
- <groupId>org.hibernate</groupId>
- <artifactId>hibernate-validator</artifactId>
- <version>5.1.3.Final</version>
- </dependency>
- <dependency>
- <groupId>javax.el</groupId>
- <artifactId>javax.el-api</artifactId>
- <version>2.2.4</version>
- </dependency>
- <dependency>
- <groupId>org.glassfish.web</groupId>
- <artifactId>javax.el</artifactId>
- <version>2.2.4</version>
- </dependency>
2、校驗工具類ide
工具類提供了校驗實體類、實體字段的方法,返回一個自定義的校驗對象。
Java代碼
![收藏代碼](http://static.javashuo.com/static/loading.gif)
- /**
- * 校驗工具類
- * @author wdmcygah
- *
- */
- public class ValidationUtils {
-
- private static Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
-
- public static <T> ValidationResult validateEntity(T obj){
- ValidationResult result = new ValidationResult();
- Set<ConstraintViolation<T>> set = validator.validate(obj,Default.class);
- if( CollectionUtils.isNotEmpty(set) ){
- result.setHasErrors(true);
- Map<String,String> errorMsg = new HashMap<String,String>();
- for(ConstraintViolation<T> cv : set){
- errorMsg.put(cv.getPropertyPath().toString(), cv.getMessage());
- }
- result.setErrorMsg(errorMsg);
- }
- return result;
- }
-
- public static <T> ValidationResult validateProperty(T obj,String propertyName){
- ValidationResult result = new ValidationResult();
- Set<ConstraintViolation<T>> set = validator.validateProperty(obj,propertyName,Default.class);
- if( CollectionUtils.isNotEmpty(set) ){
- result.setHasErrors(true);
- Map<String,String> errorMsg = new HashMap<String,String>();
- for(ConstraintViolation<T> cv : set){
- errorMsg.put(propertyName, cv.getMessage());
- }
- result.setErrorMsg(errorMsg);
- }
- return result;
- }
- }
3、校驗返回對象
Java代碼
![收藏代碼](http://static.javashuo.com/static/loading.gif)
- <span style="line-height: 22.3999996185303px;">/**
- * 校驗結果
- * @author wdmcygah
- *
- */
- public class ValidationResult {
-
- //校驗結果是否有錯
- private boolean hasErrors;
-
- //校驗錯誤信息
- private Map<String,String> errorMsg;
-
- public boolean isHasErrors() {
- return hasErrors;
- }
-
- public void setHasErrors(boolean hasErrors) {
- this.hasErrors = hasErrors;
- }
-
- public Map<String, String> getErrorMsg() {
- return errorMsg;
- }
-
- public void setErrorMsg(Map<String, String> errorMsg) {
- this.errorMsg = errorMsg;
- }
-
- @Override
- public String toString() {
- return "ValidationResult [hasErrors=" + hasErrors + ", errorMsg="
- + errorMsg + "]";
- }
-
- }</span>
4、被校驗實體
Java代碼
![收藏代碼](http://static.javashuo.com/static/loading.gif)
- public class SimpleEntity {
-
- @NotBlank(message="名字不能爲空或者空串")
- @Length(min=2,max=10,message="名字必須由2~10個字組成")
- private String name;
-
- @Past(message="時間不能晚於當前時間")
- private Date date;
-
- @Email(message="郵箱格式不正確")
- private String email;
-
- @Pattern(regexp="(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{5,10}",message="密碼必須是5~10位數字和字母的組合")
- private String password;
-
- @AssertTrue(message="字段必須爲真")
- private boolean valid;
-
- //get set方法省略,本身添加
- }
有些狀況下,Hibernate Validation自帶的註解不可以知足需求,咱們想定製一個註解進行使用,此時能夠參考下面的示例(自定義密碼註解及校驗規則)。
1、密碼註解
Java代碼
![收藏代碼](http://static.javashuo.com/static/loading.gif)
- package research.hibernate.validation.extend;
-
- import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
- import static java.lang.annotation.ElementType.FIELD;
- import static java.lang.annotation.ElementType.METHOD;
- import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
- import java.lang.annotation.Documented;
- import java.lang.annotation.Retention;
- import java.lang.annotation.Target;
-
- import javax.validation.Constraint;
- import javax.validation.Payload;
-
- @Target( { METHOD, FIELD, ANNOTATION_TYPE })
- @Retention(RUNTIME)
- @Constraint(validatedBy = PasswordValidator.class)
- @Documented
- public @interface Password {
-
- String message() default "{密碼必須是5~10位數字和字母組合}";
-
- Class<?>[] groups() default {};
-
- Class<? extends Payload>[] payload() default {};
- }
2、密碼校驗類
Java代碼
![收藏代碼](http://static.javashuo.com/static/loading.gif)
- /**
- * 自定義密碼校驗類
- * @author wdmcygah
- *
- */
- public class PasswordValidator implements ConstraintValidator<Password, String> {
-
- //5~10位的數字與字母組合
- private static Pattern pattern = Pattern.compile("(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{5,10}");
-
- public void initialize(Password constraintAnnotation) {
- //do nothing
- }
-
- public boolean isValid(String value, ConstraintValidatorContext context) {
- if( value==null ){
- return false;
- }
- Matcher m = pattern.matcher(value);
- return m.matches();
- }
- }
3、被校驗實體
Java代碼
![收藏代碼](http://static.javashuo.com/static/loading.gif)
- public class ExtendEntity {
-
- @Password
- private String password;
-
- public String getPassword() {
- return password;
- }
-
- public void setPassword(String password) {
- this.password = password;
- }
-
- }
對應的測試類以下:
Java代碼
![收藏代碼](http://static.javashuo.com/static/loading.gif)
- public class ValidationUtilsTest extends TestCase{
-
- public void validateSimpleEntity() {
- SimpleEntity se = new SimpleEntity();
- se.setDate(new Date());
- se.setEmail("123");
- se.setName("123");
- se.setPassword("123");
- se.setValid(false);
- ValidationResult result = ValidationUtils.validateEntity(se);
- System.out.println("--------------------------");
- System.out.println(result);
- Assert.assertTrue(result.isHasErrors());
- }
-
- public void validateSimpleProperty() {
- SimpleEntity se = new SimpleEntity();
- ValidationResult result = ValidationUtils.validateProperty(se,"name");
- System.out.println("--------------------------");
- System.out.println(result);
- Assert.assertTrue(result.isHasErrors());
- }
-
- public void validateExtendEntity() {
- ExtendEntity ee = new ExtendEntity();
- ee.setPassword("212");
- ValidationResult result = ValidationUtils.validateEntity(ee);
- System.out.println("--------------------------");
- System.out.println(result);
- Assert.assertTrue(result.isHasErrors());
- }
- }
代碼在JDK1.8下測試經過。完整代碼可查看個人Github倉庫:https://github.com/wdmcygah/research-J2SE
備註:
(1)上述示例只是展現了Hibernate Validation比較經常使用的示例,框架其實還支持方法返回值、方法參數校驗,另外也能夠經過XML進行配置,校驗還能夠分組、合併等等。這些內容請查閱官方使用手冊。
(2)另外還有一個也還不錯的校驗框架:OVAL。OVAL源碼地址