Java Bean 校验 API

简介: > 本文翻译自[Java Bean Validation Basics](https://www.baeldung.com/javax-validation) ## 概述 在这个文章里,我们简单介绍一如何使用标准校验框架来完成基本的Java Bean校验,该框架即JSR380,也被称为Bean Validation 2.0。 校验用户输入,在大多是应用程序中是超级常见的需求,Ja

本文翻译自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上获取。

目录
相关文章
|
22天前
|
Java API Spring
打造未来电商新引擎:揭秘Java可扩展API设计,让支付与物流灵活如丝,引领电商时代潮流!
【8月更文挑战第30天】本文通过电商平台案例,探讨了如何设计可扩展的Java API。首先定义支付和物流服务的接口与抽象类,然后实现具体服务,接着引入工厂模式或依赖注入管理服务实例,最后通过配置实现灵活扩展。这种设计确保了应用架构的灵活性和长期稳定性。
37 3
|
22天前
|
安全 Java API
告别繁琐编码,拥抱Java 8新特性:Stream API与Optional类助你高效编程,成就卓越开发者!
【8月更文挑战第29天】Java 8为开发者引入了多项新特性,其中Stream API和Optional类尤其值得关注。Stream API对集合操作进行了高级抽象,支持声明式的数据处理,避免了显式循环代码的编写;而Optional类则作为非空值的容器,有效减少了空指针异常的风险。通过几个实战示例,我们展示了如何利用Stream API进行过滤与转换操作,以及如何借助Optional类安全地处理可能为null的数据,从而使代码更加简洁和健壮。
56 0
|
30天前
|
Java 编译器 API
Java新手必看:轻松掌握API文档使用技巧!
API是预定义的接口,允许开发人员使用一组例程及协议而无需了解内部实现细节。Java API文档详述了标准类库,支持平台无关性和安全性,确保Java程序跨平台的一致性行为。Java类可通过单文件或多文件定义,并支持内部类及包组织。常用API如`Scanner`用于输入处理,`Random`生成随机数,`ArrayList`提供动态列表管理,而`Arrays`和`Math`分别简化数组操作和数学计算。掌握这些API能显著提升Java开发效率。
|
9天前
|
Java API C++
Java 8 Stream Api 中的 peek 操作
本文介绍了Java中`Stream`的`peek`操作,该操作通过`Consumer&lt;T&gt;`函数消费流中的每个元素,但不改变元素类型。文章详细解释了`Consumer&lt;T&gt;`接口及其使用场景,并通过示例代码展示了`peek`操作的应用。此外,还对比了`peek`与`map`的区别,帮助读者更好地理解这两种操作的不同用途。作者为码农小胖哥,原文发布于稀土掘金。
Java 8 Stream Api 中的 peek 操作
|
13天前
|
安全 Java API
【性能与安全的双重飞跃】JDK 22外部函数与内存API:JNI的继任者,引领Java新潮流!
【9月更文挑战第7天】JDK 22外部函数与内存API的发布,标志着Java在性能与安全性方面实现了双重飞跃。作为JNI的继任者,这一新特性不仅简化了Java与本地代码的交互过程,还提升了程序的性能和安全性。我们有理由相信,在外部函数与内存API的引领下,Java将开启一个全新的编程时代,为开发者们带来更加高效、更加安全的编程体验。让我们共同期待Java在未来的辉煌成就!
43 11
|
14天前
|
安全 Java API
【本地与Java无缝对接】JDK 22外部函数和内存API:JNI终结者,性能与安全双提升!
【9月更文挑战第6天】JDK 22的外部函数和内存API无疑是Java编程语言发展史上的一个重要里程碑。它不仅解决了JNI的诸多局限和挑战,还为Java与本地代码的互操作提供了更加高效、安全和简洁的解决方案。随着FFM API的逐渐成熟和完善,我们有理由相信,Java将在更多领域展现出其强大的生命力和竞争力。让我们共同期待Java编程新纪元的到来!
38 11
|
12天前
|
监控 Java 大数据
【Java内存管理新突破】JDK 22:细粒度内存管理API,精准控制每一块内存!
【9月更文挑战第9天】虽然目前JDK 22的确切内容尚未公布,但我们可以根据Java语言的发展趋势和社区的需求,预测细粒度内存管理API可能成为未来Java内存管理领域的新突破。这套API将为开发者提供前所未有的内存控制能力,助力Java应用在更多领域发挥更大作用。我们期待JDK 22的发布,期待Java语言在内存管理领域的持续创新和发展。
|
13天前
|
Java API 数据处理
【Java的SIMD革命】JDK 22向量API:释放硬件潜能,让Java应用性能飙升!
【9月更文挑战第7天】 JDK 22向量API的发布标志着Java编程语言在SIMD技术领域的重大突破。这一新特性不仅释放了现代硬件的潜能,更让Java应用性能实现了飙升。我们有理由相信,在未来的发展中,Java将继续引领编程语言的潮流,为开发者们带来更加高效、更加强大的编程体验。让我们共同期待Java在SIMD技术的推动下开启一个全新的性能提升时代!
|
14天前
|
Java API 开发者
【Java字节码操控新篇章】JDK 22类文件API预览:解锁Java底层的无限可能!
【9月更文挑战第6天】JDK 22的类文件API为Java开发者们打开了一扇通往Java底层世界的大门。通过这个API,我们可以更加深入地理解Java程序的工作原理,实现更加灵活和强大的功能。虽然目前它还处于预览版阶段,但我们已经可以预见其在未来Java开发中的重要地位。让我们共同期待Java字节码操控新篇章的到来!
|
12天前
|
Java API 开发者
【Java字节码的掌控者】JDK 22类文件API:解锁Java深层次的奥秘,赋能开发者无限可能!
【9月更文挑战第8天】JDK 22类文件API的引入,为Java开发者们打开了一扇通往Java字节码操控新世界的大门。通过这个API,我们可以更加深入地理解Java程序的底层行为,实现更加高效、可靠和创新的Java应用。虽然目前它还处于预览版阶段,但我们已经可以预见其在未来Java开发中的重要地位。让我们共同期待Java字节码操控新篇章的到来,并积极探索类文件API带来的无限可能!