天天看點

Java Bean 校驗 API

本文翻譯自 Java Bean Validation Basics

概述

在這個文章裡,我們簡單介紹一如何使用标準校驗架構來完成基本的Java Bean校驗,該架構即JSR380,也被稱為Bean Validation 2.0。

校驗使用者輸入,在大多是應用程式中是超級常見的需求,Java Bean校驗架構即是處理這部分邏輯的标準工具。

JSR308-Bean Validation 2.0

JSR 308是JavaBean校驗API規範,它是JavaEE和JavaSE的一部分。該規範使用@NotNull,@Min和@Max這樣的注解來確定一個Bean的屬性符合特定的條件。

這個版本要求使用Java8或更高版本,利用Java8提供的新特性例如類型注解,并且支援新的類型例如Optional和LocalDate。

要獲得更完整的資訊,可以進一步閱讀

JSR 308的文檔

依賴

  1. JSR 308規範的的标準API包含在validation-api中:
    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
        <version>2.0.1.Final</version>
    </dependency>           
  2. Hibernate Validator是validation-api的參考實作:
    <dependency>
        <groupId>org.hibernate.validator</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>6.0.2.Final</version>
    </dependency>           

另外,Hibernate Validator還提供了一個注解處理器,利用Java編譯時注解處理機制,幫助開發人員發現校驗注解使用的錯誤。僅需要添加如下依賴即可:

<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator-annotation-processor</artifactId>
    <version>6.0.2.Final</version>
    <scop>provided</scop>
</dependency>           
hibernate-validator與hibernate的持久化架構支援是完全分離的,引入hibnernate-validator依賴并不會間接引入hibernate持久化相關的依賴。
  1. 表達式語言依賴

JSR 308規範支援違約資訊的變量解析,并允許使用表達式。

為了解析表達式,我們必須添加表達式語言API和它的某個實作,GlassFish項目提供了表達式語言API的參考實作:

<dependency>
    <groupId>javax.el</groupId>
    <artifactId>javax.el-api</artifactId>
    <version>3.0.0</version>
</dependency>
 
<dependency>
    <groupId>org.glassfish.web</groupId>
    <artifactId>javax.el</artifactId>
    <version>2.2.6</version>
</dependency>           

如果沒有添加這些依賴到應用中,您會在運作時得到如下錯誤資訊:

HV000183: Unable to load ‘javax.el.ExpressionFactory'. Check that you have the EL dependencies on the classpath, or use ParameterMessageInterpolator instead

使用校驗注解

我們在這裡使用UserBean作為例子,為它添加一些簡單的校驗。

import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import javax.validation.constraints.Email;

public class User {
 
    @NotNull(message = "Name cannot be null")
    private String name;
 
    @AssertTrue
    private boolean working;
 
    @Size(min = 10, max = 200, message 
      = "About Me must be between 10 and 200 characters")
    private String aboutMe;
 
    @Min(value = 18, message = "Age should not be less than 18")
    @Max(value = 150, message = "Age should not be greater than 150")
    private int age;
 
    @Email(message = "Email should be valid")
    private String email;
 
    // standard setters and getters 
}           

該例子中使用的所有注解都是标準JSR注解:

  • @NotNull-校驗被注解的屬性不能為null
  • @AssertTrue-校驗被注解的屬性值必須為true
  • @Size-校驗被注解的屬性的尺寸必須在min和max之間,該注解可以在String,Collection,Map和數組屬性上使用
  • @Min,@Max-校驗備注解的屬性值必須大于或小于指定的值
  • @Email-校驗備注接的屬性必須是有效的emal位址

JSR中還包含其他一些注解:

  • @NotEmpty-校驗屬性不能為null或空;可以在String,Collection,Map或數組類型屬性上使用
  • @NotBlank-隻能使用在文本類型的屬性上,校驗該屬性不能為null或空白
  • @Positive,@PositiveOrZero-使用在數值屬性上,校驗該屬性必須為正數或0
  • @Negative,@NegativeOrZero-使用在數值屬性上,校驗該屬性必須為負數或0
  • @Past,@PastOrPresent-校驗日期類型值必須是過去的時間或現在;支援Java8中新增加的日期類型,例如LocalDateTime
  • @Future,@FutureOrPresent-校驗日期類型值必須在未來或現在

所有注解都可以設定messge屬性,這個屬性的值在校驗失敗時被用來渲染違約消息。

Validation-API提供的标準注解的message屬性大都有預設值,使用者如無特别需求,無須設定該屬性。

校驗注解可以施加在集合的元素上

List<@NotBlank String> preferences;           

在這個例子中,集合中的的所有元素都會被校驗不能為null或空白

規範也支援Java8中新增的Optional類型:

private LocalDate dateOfBirth;
 
public Optional<@Past LocalDate> getDateOfBirth() {
    return Optional.of(dateOfBirth);
}           

這個例子中,校驗架構會自動将LocalDate值取出并校驗。

程式設計校驗

  1. 一些架構,例如Spring,僅僅使用注解即可出發校驗過程。讓我們不必直接程式設計使用校驗API。但我們應當對其有所了解,以了解架構的運作原理。

下面讓我們來手動程式設計配置一個校驗環境:

ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();           

我們必須首先建構一個校驗器(validator)對象,才能校驗一個Bean。

  1. 定義一個待校驗的Bean
    User user = new User();
    user.setWorking(true);
    user.setAboutMe("Its all about me!");
    user.setAge(50);           
  2. 對上面定義的Bean進行校驗
    Set<ConstraintViolation<User>> violations = validator.validate(user);           

将user對象作為validate方法的參數傳遞給校驗器對象,所有違背User對象定義的限制條件的資訊包裝為ConstraintViolation對象集合傳回。

周遊違約資訊,我們可以得到所有的違約消息

for (ConstraintViolation<User> violation : violations) {
    log.error(violation.getMessage()); 
}           

在我們的例子中,違約對象集合中隻會包含一個違約資訊,“Name cannot be null”。

這個違約消息可以通過校驗注解的message屬性進行定義。

總結

本教程聚焦于标準Java校驗API的基本内容,展示了使用基本javax.validation注解和API的使用方法。

所有的示例代碼可以在

GitHub

上擷取。