Spring Boot中@Valid 与 @Validated 注解的详解

Spring Boot中@Valid 与 @Validated 注解的详解

引言

在Spring Boot应用中,参数校验是确保数据完整性和一致性的重要手段。@Valid和@Validated注解是Spring Boot中用于参数校验的两个核心注解。本文将详细介绍这两个注解的用法、区别以及代码样例。

@Valid注解
功能介绍

@Valid是Java EE提供的标准注解,它是JSR 303规范的一部分,主要用于Hibernate Validation等场景。在Spring Boot中,@Valid注解用于触发参数校验,确保请求参数的合法性。

使用场景

@Valid注解可以用于方法参数、构造函数、方法参数和成员属性上。它主要用于嵌套校验,即对于对象中的属性值(可能是另一个对象)进行校验。

代码样例
java 复制代码
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.Valid;

public class User {
    @NotBlank(message = "用户名不能为空")
    private String username;

    @NotNull(message = "密码不能为空")
    private String password;

    @Valid
    private Address address;

    // Getter 和 Setter
}

public class Address {
    @NotBlank(message = "国家不能为空")
    private String country;

    @NotBlank(message = "城市不能为空")
    private String city;

    // Getter 和 Setter
}

import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @PostMapping("/addUser")
    public String addUser(@Valid @RequestBody User user, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return "参数校验失败: " + bindingResult.getAllErrors().get(0).getDefaultMessage();
        }
        return "用户添加成功";
    }
}

在上述代码中,User类中的address属性使用了@Valid注解,表示对address对象进行嵌套校验。在UserController中,addUser方法使用了@Valid注解对传入的User对象进行校验,并使用BindingResult捕获校验错误。

@Validated注解
功能介绍

@Validated是Spring框架特有的注解,属于Spring的一部分,也是JSR 303的一个变种。它提供了一些@Valid所没有的额外功能,比如分组验证。@Validated注解可以用在类、方法和方法参数上,但不能用于成员属性。

使用场景

@Validated注解主要用于支持分组验证,可以更细致地控制验证过程。此外,由于它是Spring专有的,因此可以更好地与Spring的其他功能(如Spring的依赖注入)集成。

代码样例
java 复制代码
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.groups.Default;

public interface ValidationGroups {
    interface Insert extends Default {}
    interface Update {}
}

public class Project {
    @NotBlank(message = "ID不能为空", groups = ValidationGroups.Update.class)
    private String id;

    @NotBlank
    private String name;

    @Min(value = 1, message = "预算不能小于1", groups = ValidationGroups.Insert.class)
    private int budget;

    // Getter 和 Setter
}

import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.validation.annotation.Validated;

@RestController
public class ProjectController {

    @PostMapping("/insertProject")
    public String insertProject(@Validated(value = ValidationGroups.Insert.class) @RequestBody Project project, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return "参数校验失败: " + bindingResult.getAllErrors().get(0).getDefaultMessage();
        }
        return "项目插入成功";
    }

    @PostMapping("/updateProject")
    public String updateProject(@Validated(value = ValidationGroups.Update.class) @RequestBody Project project, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return "参数校验失败: " + bindingResult.getAllErrors().get(0).getDefaultMessage();
        }
        return "项目更新成功";
    }
}

在上述代码中,我们定义了一个ValidationGroups接口,用于分组验证。Project类中的id属性在Update分组下必填,而budget属性在Insert分组下必填且不能小于1。在ProjectController中,insertProject方法使用@Validated(value = ValidationGroups.Insert.class)注解对传入的Project对象进行Insert分组的校验,而updateProject方法则使用@Validated(value = ValidationGroups.Update.class)注解进行Update分组的校验。

@Valid与@Validated的区别
  1. 嵌套校验:@Valid支持嵌套校验,而@Validated不支持。在需要嵌套校验的场景下,应使用@Valid。
  2. 分组校验:@Validated支持分组校验,而@Valid不支持。在需要根据不同场景应用不同校验规则的情况下,应使用@Validated。
  3. 使用范围:@Valid可以用在方法、构造函数、方法参数和成员属性上,而@Validated只能用在类、方法和方法参数上。
结论

@Valid和@Validated注解在Spring Boot的参数校验中扮演着重要角色。掌握这两个注解的用法和区别,可以帮助开发者更灵活地进行参数校验,确保数据的完整性和一致性。

相关推荐
BD_Marathon2 小时前
【Flink】部署模式
java·数据库·flink
鼠鼠我捏,要死了捏5 小时前
深入解析Java NIO多路复用原理与性能优化实践指南
java·性能优化·nio
ningqw5 小时前
SpringBoot 常用跨域处理方案
java·后端·springboot
你的人类朋友5 小时前
vi编辑器命令常用操作整理(持续更新)
后端
superlls5 小时前
(Redis)主从哨兵模式与集群模式
java·开发语言·redis
胡gh5 小时前
简单又复杂,难道只能说一个有箭头一个没箭头?这种问题该怎么回答?
javascript·后端·面试
一只叫煤球的猫6 小时前
看到同事设计的表结构我人麻了!聊聊怎么更好去设计数据库表
后端·mysql·面试
uzong6 小时前
技术人如何对客做好沟通(上篇)
后端
叫我阿柒啊7 小时前
Java全栈工程师面试实战:从基础到微服务的深度解析
java·redis·微服务·node.js·vue3·全栈开发·电商平台
颜如玉7 小时前
Redis scan高位进位加法机制浅析
redis·后端·开源