Java Bean Validation

qianmoQ發表於2019-01-23
案例概述

在這本文中,我們將介紹使用標準框架驗證Java bean的基礎知識 - JSR 380,也稱為Bean Validation 2.0。

當然,驗證使用者輸入在大多數應用程式中是一個超常見的要求,Java Bean Validation框架已經成為處理這種邏輯的事實上的標準。

JSR 380

JSR 380是用於bean驗證的Java API的規範,是JavaEE和JavaSE的一部分,它使用@NotNull、@Min和@Max等註釋確保bean的屬性滿足特定的標準。

此版本需要Java 8或更高版本,並利用Java 8中新增的新功能(如型別註釋),並支援Optional和LocalDate等新型別。

有關規範的完整資訊,請繼續閱讀JSR 380

依賴性

我們將使用Maven示例來顯示所需的依賴項,但當然,可以使用各種方式新增這些jar。

驗證API

根據JSR 380規範,validation-api依賴包含標準驗證API:

<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>2.0.0.Final</version>
</dependency>
驗證API參考實現

Hibernate Validator是驗證API的參考實現。

要使用它,我們必須新增以下依賴項:

<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.0.2.Final</version>
</dependency>
<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator-annotation-processor</artifactId>
    <version>6.0.2.Final</version>
</dependency>

這裡快速說明的是,hibernate-validator完全獨立於Hibernate的永續性方面,並且透過將其新增為依賴項,我們不會將這些永續性方面新增到專案中。

表示式語言依賴關係

JSR 380提供對變數插值的支援,允許在違規訊息中使用表示式。

要解析這些表示式,我們必須在表示式語言API和該API的實現上新增依賴項。GlassFish提供參考實現:

<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>

如果未新增這些JAR,您將在執行時收到錯誤訊息,如下所示:

HV000183:無法載入'javax.el.E​​xpressionFactory'。檢查您是否在類路徑上有EL依賴項,或使用ParameterMessageInterpolator

使用驗證註釋

我們將在這裡使用User bean作為主要示例,併為其新增一些簡單的驗證:

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 - 驗證帶註釋的屬性的值是否小於value屬性
  • @Max - 驗證帶註釋的屬性的值是否大於value屬性
  • @Email - 驗證帶註釋的屬性是否為有效的電子郵件地址

某些註釋接受其他屬性,但message屬性對所有屬性都是通用的。這是當相應屬性的值未透過驗證時通常會呈現的訊息。

可以在JSR中找到的一些其他註釋是:

  • @NotEmpty - 驗證屬性不為null或為空; 可以應用於String, Collection, Map或 Array值
  • @NotBlank - 只能應用於文字值,並驗證該屬性不是null或空格
  • @Positive和@PositiveOrZero - 適用於數值並驗證它們是嚴格正數還是正數,包括0
  • @Negative和@NegativeOrZero - 適用於數值並驗證它們是嚴格為負數,還是負數,包括0
  • @Past和@PastOrPresent - 驗證日期值是否過去,包括現在; 可以應用於日期型別,包括Java 8中新增的日期型別
  • @Future和@FutureOrPresent - 驗證日期值是否將來包括現在

驗證註釋也可以應用於集合的元素:

List<@NotBlank String> preferences;

在這種情況下,將驗證新增到選項列表中的任何值。

該規範還支援 Java 8中的新Optional型別:

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

在這裡,驗證框架將自動解包LocalDate值並對其進行驗證。

程式驗證

一些框架 - 例如Spring--只需使用註釋就可以透過簡單的方法觸發驗證過程。這主要是為了使我們不必與程式驗證API進行互動。

現在讓我們進入手動路線並以程式設計方式設定:

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

要驗證bean,我們必須首先擁有Validator物件,該物件使用ValidatorFactory構造。

定義Bean

我們現在要設定一個無效使用者 - 使用空名稱值:

User user = new User();
user.setWorking(true);
user.setAboutMe("Its all about me!");
user.setAge(50);
驗證Bean

現在我們有了一個Validator,我們可以透過將它傳遞給validate方法來驗證我們的bean 。任何違反User物件中定義的約束的行為都將作為Set返回。

Set<ConstraintViolation<User>> violations = validator.validate(user);

透過迭代違規,我們可以使用getMessage方法獲取所有違規訊息。

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

在我們的示例中(ifNameIsNull_nameValidationFails),該集合將包含一個ConstraintViolation,訊息“ Name not not null”。

案例結論

本文重點介紹了標準Java Validation API的簡單傳遞,並使用javax.validation註釋和API 說明了bean驗證的基礎知識。

相關文章