天天看點

Hibernate Validator簡介

Hibernate項目中不僅有ORM一個架構,這裡介紹的是它的另一個架構Validator,用來驗證明體類是否滿足需求。Validator實作了Java的一項标準Bean Validation。

如果使用Maven,就需要在pom.xml中添加如下一段,Hibernate需要Java EL表達式,是以需要添加EL的依賴項。

<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-validator</artifactId>
   <version>5.3.4.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>
           

如果使用Gradle,需要将上面的依賴項轉換一下。

compile group: 'org.hibernate', name: 'hibernate-validator', version: '5.3.4.Final'
compile group: 'javax.el', name: 'javax.el-api', version: '3.0.1-b04'
compile group: 'org.glassfish.web', name: 'javax.el', version: '2.2.6'
           

添加依賴之後,就可以在實體類中添加條件注解了。常用的幾個注解如下:

注解 作用
AssertTrue 布爾值為真
AssertFalse 布爾值為假
Null 引用為空
NotNull 引用不為空
NotEmpty 字元串引用和值都不是空
Min 數字的最小值
Max 數字的最大值
Past 日期必須是過去
Future 日期必須是未來
Pattern 字元串必須比對正規表達式
Valid 遞歸驗證引用
Size 驗證字元串是否在Size範圍内
Email 驗證字元串是否是一個有效的電子郵箱
URL 字元串是否是一個有效的URL

需要注意最後兩個注解是Hibernate Validator自定義的,假如使用其他的Bean Validation實作,可能沒有這兩個注解。

下面向兩個實體類添加了驗證注解,其他方法已經省略了。和JPA注解一樣,如果驗證注解添加到字段上,Hibernate就會直接讀取字段的值。如果注解到Getter方法上,Hibernate就會調用方法取得值。在一個類中不要同時應用這兩種方式,會導緻重複驗證的問題。如果在一個集合上應用Valid注解, Hibernate就會遞歸驗證集合中的每一個元素。

public class Author {
    @NotNull
    @Size(min = 6, max = 15)
    @Pattern(regexp = "([a-zA-Z]+\d*)+")
    private String username;
    @NotNull
    @Size(min = 6, max = 20)
    private String password;
    @NotNull
    private String nickname;
    @Email
    private String email;
    @Min(0)
    private int age;
    @Size(max = 500)
    private String address;
    @Past
    @NotNull
    private Date birthday;
    @Valid
    @NotNull
    private List<Article> articles = new ArrayList<>();
}
           
public class Article {
    @NotNull
    private String title;
    @NotNull
    private String content;
    @NotNull
    private Author author;
    @Past
    private Date createTime;
    @Past
    private Date modifyTime;
}
           

向實體類添加了驗證注解之後,我們就可以開始驗證了。首先需要構造一個ValidatorFactory,然後使用構造出的ValidatorFactory生成一個Validator,然後調用這個Validator的validate方法,就可以驗證明體類了。validate方法會傳回一個Set<ConstraintViolation>,每一個ConstraintViolation都是一個驗證結果,如果實體類沒有錯誤,那麼這個集合的大小就是0,表示驗證通過。如果存在錯誤,我們就可以通過這個集合來檢視存在什麼錯誤。

public class ValidatorTest {
    private static ValidatorFactory factory;
    private static Validator validator;
    private static Logger logger;

    @BeforeClass
    public static void init() {
        factory = Validation.buildDefaultValidatorFactory();
        validator = factory.getValidator();
        logger = LoggerFactory.getLogger(ValidatorTest.class);
    }

    @AfterClass
    public static void clean() {
        factory.close();
    }

    @Test
    public void testKindsOfErrors() {
        Author author = new Author();
        author.setUsername("123");
        author.setPassword("1234");
        author.setAddress("");
        author.setEmail("");
        author.setArticles(null);
        author.setAge(-20);
        Set<ConstraintViolation<Author>> set = validator.validate(author);
        for (ConstraintViolation<Author> c : set) {
            logger.info(c.toString());
        }
    }

    @Test
    public void testAllRight() {
        Author author = new Author();
        author.setUsername("yitian");
        author.setPassword("12345678");
        author.setAddress("");
        author.setNickname("");
        author.setEmail("[email protected]");
        author.setBirthday(new Date());
        Set<ConstraintViolation<Author>> set = validator.validate(author);
        for (ConstraintViolation<Author> c : set) {
            logger.info(c.toString());
        }
        Assert.assertEquals(0, set.size());
    }

    @Test
    public void testOneProperty() {
        Author author = new Author();
        author.setUsername("yitian");
        Set<ConstraintViolation<Author>> set = validator.validateProperty(author, "username");
        for (ConstraintViolation<Author> c : set) {
            logger.info(c.toString());
        }
    }

    @Test
    public void testCustomMessage() {
        Article article = new Article();
        LocalDate date = LocalDate.of(2099, 1, 1);
        article.setModifyTime(Date.from(date.atStartOfDay(ZoneId.systemDefault()).toInstant()));
        Set<ConstraintViolation<Article>> set = validator.validateProperty(article, "modifyTime");
        for (ConstraintViolation<Article> c : set) {
            logger.info(c.toString());
        }
    }
}
           

以上就是一個簡單的驗證的例子。通過這個例子,大家應該明白了Hibernate Validator的基本内容。很多架構比如Spring也提供了相關的内容,能友善的将Hibernate Validator整合到項目中。如果希望了解更多資訊,可以檢視一下它們的相關文檔。這裡就起到一個抛磚引玉的作用。