运用标准结构验证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”。