Java Validate 参数验证

前言

讲到 Validate API 你应该不陌生,尤其是在 web 应用中,作为前后端接口的参数校验,通过注解可以非常方便的校验参数的类型、长度、参数值等。

你是否还在对 Java Bean Validation 与 Hibernate validate,@Valid 与 @Validated 概念模糊?本文带你一同理清这些概念以及最基本的使用方式。

Java Bean Validation

Java Bean Validation(JSR 380)是一个标准的Java规范,用于对Java Bean进行验证。

这个规范定义了一组注解和一些API,可以用来对Java Bean的属性进行约束定义和验证。

注意:JSR 380 只是定义了标准,如果要使用还需要找到相关实现该标准的组件。

目前使用比较多的实现 Hibernate Validator,当然也有其他的实现,如Apache BVal。

使用案例:

1、引用包:

xml 复制代码
<dependencies>
    <!-- javax validation-api -->
    <dependency>
        <groupId>javax.validation</groupId>
        <artifactId>validation-api</artifactId>
        <version>2.0.1.Final</version>
    </dependency>

    <!-- hibernate validator -->
    <dependency>
        <groupId>org.hibernate.validator</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>6.0.17.Final</version>
    </dependency>
</dependencies>

当然,大部分场景不需要你手动添加,当你引用 spring-boot-starter-web 包之后,默认就已经引入了,如:

2、定义字段约束:

java 复制代码
import javax.validation.constraints.*;

public class User {

    @NotNull(message = "Name cannot be null")
    private String name;

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

    // getters and setters...
}

3、验证:

java 复制代码
import javax.validation.*;
import java.util.Set;

public class Main {

    public static void main(String[] args) {
        ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
        Validator validator = factory.getValidator();

        User user = new User();
        user.setName(null);
        user.setAge(17);
        user.setEmail("invalid");

        Set<ConstraintViolation<User>> violations = validator.validate(user);
        for (ConstraintViolation<User> violation : violations) {
            System.out.println(violation.getMessage());
        }
    }
}

当有字段属性不满足字段约束时,通过 validator.validate(user) 方法验证时会检测出来,即 violations 结果集不为空,则说明存在字段不满足约束条件。

还需要自己定义 Validator 验证器,并且手动调用 validate 方法进行验证,看起来显得很麻烦?

手动使用的常见也比较多,比如内部参数验证excel上传数据时参数验证等。

当然,对于 web 接口,在 Spring 环境下,我们也可以通过注解的方式,让接口参数能够自动触发约束校验,我们继续看下文~

@Valid

@Valid 是来自 Java Bean Validation 的标准注解,可以用于触发对方法参数(如Controller方法参数)的验证。

它可以用在任何需要验证的对象上,包括嵌套的对象和集合。但是,它不能用于分组验证。

在 Spring 场景下,这也是最常使用的方式之一,在接口验证的参数前加上 @Valid 注解即可生效:

基本使用

还是使用上文定义的 User 实体类(对字段进行了约束定义),我们继续定义接口使用:

java 复制代码
import javax.validation.Valid;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/users")
public class UserController {

    @PostMapping
    public String createUser(@Valid @RequestBody User user) {
        // 创建用户...
        return "success";
    }
}

加上 @Valid 注解后,Spring 会自动使用 java validate 实现类的校验能力,即:基于字段上的约束条件进行校验。

如果 User 对象违反了任何约束,Spring 将抛出一个 MethodArgumentNotValidException 异常。

你也可以定义全局的异常处理,使用@ExceptionHandler 注解来处理这个特殊异常,并向客户端返回一个有用的错误消息。

小知识:Spring处理 @Valid 注解的基本步骤:

  1. 数据绑定:当一个HTTP请求到达一个Spring MVC控制器方法时,Spring首先尝试将请求参数绑定到方法参数。

  2. 验证:如果方法参数上有@Valid注解,Spring将触发对这个参数的验证。验证通过Java Bean Validation API的实现进行。

  3. 处理验证结果:如果有任何验证错误,Spring将抛出一个MethodArgumentNotValidException。

@Validated

@Validated 是 Spring 的特有注解,就常见的使用能力上看,和 @Valid 差别不大,不过,它提供了一种分组验证的功能,这是 @Valid 注解所不具备的。

@Validated 可以用在类型、方法和方法参数上。当用在方法参数上时,@Validated 和 @Valid 的功能是一样的。

我们看一个简单的例子:

java 复制代码
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/users")
public class UserController {

    @PostMapping
    public String createUser(@Validated @RequestBody User user) {
        // 创建用户...
        return "success";
    }
}

这种方式和使用 @Valid 没啥区别。

再看一个分组验证的例子:

java 复制代码
import javax.validation.groups.Default;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/users")
public class UserController {

    public interface NewUserGroup {}

    @PostMapping
    public String createUser(@Validated(NewUserGroup.class) @RequestBody User user) {
        // 创建用户...
        return "success";
    }
}

public class User {

    @NotNull(groups = {Default.class, NewUserGroup.class})
    private String name;

    // getters and setters...
}

在这个例子中,NewUserGroup 是一个空接口,用作分组验证的标记。createUser 方法接受一个 User 对象作为参数,并指定只验证 NewUserGroup 组。

User 类的 name 属性上的 @NotNull 注解指定了它应该在 Default 组和 NewUserGroup 组中进行验证。因此,当调用 createUser 方法时,Spring 将验证 name 属性是否不为 null。

小知识:Spring 处理 @Validated 注解的基本步骤:

  1. 数据绑定:当一个 HTTP 请求到达一个 Spring MVC 控制器方法时,Spring 首先尝试将请求参数绑定到方法参数。

  2. 验证 :如果方法参数上有 @Validated 注解,Spring 将触发对这个参数的验证,验证通过 Java Bean Validation API 的实现进行。如果 @Validated 注解指定了一个或多个组,Spring 将只验证那些指定了相同组的约束。

  3. 处理验证结果:如果有任何验证错误,Spring将抛出一个MethodArgumentNotValidException

可以发现,和 @Valid 注解的处理流程上基本一致,只是多了分组的校验。

相关推荐
站大爷IP1 分钟前
python3如何使用QT编写基础的对话框程序
后端
守护者1702 分钟前
JAVA学习-练习试用Java实现“一个词频统计工具 :读取文本文件,统计并输出每个单词的频率”
java·学习
老夫运道一向好8 分钟前
【YashanDB监控运维平台(YCM)】登录安全设置
后端
bing_15813 分钟前
Spring Boot 中ConditionalOnClass、ConditionalOnMissingBean 注解详解
java·spring boot·后端
ergdfhgerty15 分钟前
斐讯N1部署Armbian与CasaOS实现远程存储管理
java·docker
凌览20 分钟前
斩获 7k Star,这个桌宠项目火了🔥
前端·javascript·后端
勤奋的知更鸟28 分钟前
Java性能测试工具列举
java·开发语言·测试工具
三目君32 分钟前
SpringMVC异步处理Servlet
java·spring·servlet·tomcat·mvc
用户05956611920932 分钟前
Java 基础篇必背综合知识点总结包含新技术应用及实操指南
java·后端