SpringBoot的controller层使用Validated注解做接口参数校验

博客介绍了常用的校验规则,涉及entity层、controller层和util工具,还展示了在控制台和postman中的打印情况,与Java开发相关。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

@Validated注解@Valid注解
用在类型、方法和方法参数上。但是不能用在成员属性(字段)上用在方法、构造函数、方法参数和成员属性(字段)上

常用的校验规则如下:

注解说明
@Null限制只能为null
@NotNull限制必须不为null
@AssertFalse限制必须为false
@AssertTrue限制必须为true
@DecimalMax(value)限制必须为一个不大于指定值的数字
@DecimalMin(value)限制必须为一个不小于指定值的数字
@Digits(integer,fraction)限制必须为一个小数,且整数部分的位数不能超过integer,小数部分的位数不能超过fraction
@Future限制必须是一个将来的日期
@Max(value)限制必须为一个不大于指定值的数字
@Min(value)限制必须为一个不小于指定值的数字
@Past限制必须是一个过去的日期
@Pattern(value)限制必须符合指定的正则表达式
@Size(max,min)限制字符长度必须在min到max之间
@NotEmpty验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0)
@NotBlank验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的空格
@Email证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式

entity层
在这里插入图片描述
controller层
在这里插入图片描述

在这里插入图片描述
util工具

package com.yyy.demo.util;


public class validResult {
    private Integer code;   //返回编码
    private String msg;     //返回信息
    private Object data;    //返回数据

    public validResult() {
    }
    public validResult(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }
    public validResult(Integer code, String msg, Object data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }
}

控制台打印
在这里插入图片描述
postman打印
在这里插入图片描述

<think>我们正在讨论SpringBoot使用@Validated注解对List<对象>类型的参数进行校验的问题。根据提供的引用,我们可以总结出:-引用[1]说明了SpringBoot使用@Validated需要引入spring-boot-starter-validation依赖。-引用[2]展示了如何在一个对象中嵌入另一个对象进行校验使用@Valid)。-引用[3]展示了在Controller方法参数使用@Validated注解,并且指定分组校验。用户的问题:如何对List<对象>类型的参数进行校验?我们知道,在SpringBoot中,对于单个对象的校验,我们直接在对象前加上@Valid或@Validated即可。但是,对于List<对象>,我们需要额外的处理。解决方案:1.使用一个包装类,将List<对象>作为该包装类的一个属性,然后对这个属性标注@Valid(或@Validated注解。这样,Spring在绑定数据时会对List中的每个对象进行校验。2.使用自定义的校验注解校验器。这里我们采用第一种方式,因为它更符合SpringBoot校验机制,并且与引用[2]中嵌入校验的方式一致。步骤:①创建包装类,将List<对象>作为属性,并在该属性上添加@Valid注解(注意:不能直接使用@Validated在这里,@Validated是用在类和方法上的,而@Valid是用在字段、方法参数或方法返回值的)。②在Controller方法的参数使用@Validated注解(如果使用分组校验则需要,否则可以直接用@Valid)来触发校验。注意:SpringBoot在2.3版本之后,需要显式添加依赖spring-boot-starter-validation(如引用[1]所示)。下面通过一个例子说明:假设我们有一个StudentDTO类,其中有一些校验注解:```javapublicclassStudentDTO{@NotBlank(message="学生姓名不能为空")privateStringname;@Min(value=18,message="年龄必须大于18岁")privateintage;//省略getter和setter}```然后,我们创建一个包装类,用于封装List<StudentDTO>:```javapublicclassStudentListDTO{@ValidprivateList<StudentDTO>students;//必须提供setter和getterpublicList<StudentDTO>getStudents(){returnstudents;}publicvoidsetStudents(List<StudentDTO>students){this.students=students;}}```最后,在Controller中,我们接收这个包装类,并在参数前加上@Valid或@Validated(注意:这里不能直接使用@Validated校验包装类内部的List,但可以在参数使用@Validated来触发校验,不过更常见的法是使用@Valid):```java@RestController@RequestMapping("/students")publicclassStudentController{@PostMapping("/batch")publicResultaddBatch(@RequestBody@ValidStudentListDTOstudentList){//处理批量新增学生returnResult.ok();}}```这样,当请求中的List<StudentDTO>被传入时,Spring会为StudentListDTO中的students字段(因为标注了@Valid)进行校验,从而校验List中每一个StudentDTO对象。但是,如果不想使用包装类,可以直接在Controller方法的参数使用@Validated(在类上)配合@Valid在List<StudentDTO>参数前。然而,根据Spring的文档,对于直接是List类型的参数,我们需要在参数前同时使用@Valid和@Validated(在类上)?实际上,SpringBoot默认不支持直接对List<对象>进行校验,因为它是一个集合,而校验注解不能直接写在集合类型上。所以,使用包装类是最直接的方法。另一种方案:在Controller方法上使用@Validated(类级别),然后在参数使用@Valid(针对包装类)或者使用@Valid注解在List上?然而,当我们尝试在List参数前直接使用@Valid时,Spring并不会递归校验其中的对象(除非我们使用@Valid在包装类的字段上)。总结:为了对List<对象>进行校验,我们需要将List放入一个包装类中,并对该字段使用@Valid注解,然后在Controller方法的参数使用@Valid或@Validated(分组校验时)。另外,引用[3]提到了分组校验。如果我们需要在List中的对象上使用分组校验,那么可以在@Valid(在包装类字段上)后无法指定分组,因此需要改为在包装类字段上使用@Validated(分组.class)?但注意,@Valid不支持分组,而@Validated支持分组。所以我们可以这样调整:修改包装类:```javapublicclassStudentListDTO{@Validated(Insert.class)//但是,@Validated不能用在字段上,只能用在类型和方法上?所以这里不行!privateList<StudentDTO>students;//...}```这样写是错误的,因为@Validated注解不能用在字段上。因此,如果我们想对List中的对象进行分组校验,我们可以将@Validated注解放在Controller类上,然后在参数使用@Validated(分组.class)?但是,这样会作用于整个类,而且参数上的@Validated只能用于参数上(它也可以指定分组)。然而,在参数使用@Validated(分组.class)配合包装类字段上的@Valid是不行的,因为分组信息不会传递下去。正确的法是在包装类的字段上使用@Valid(不支持分组),然后在StudentDTO的校验注解上指定分组(这样如果没有激活该分组,则不会校验)。但如果我们激活了分组,那么在字段上使用@Valid会触发所有未指定分组的约束以及指定了当前激活分组的约束。因此,我们可以:在Controller方法参数使用@Validated(分组.class),并且参数是包装类(包装类的字段上使用@Valid):```java@RestController@RequestMapping("/students")@Validated//如果整个Controller需要分组校验,可以在类上添加@Validated,但这里我们不需要,因为我们要在方法参数上指定分组publicclassStudentController{@PostMapping("/batch")publicResultaddBatch(@RequestBody@Validated(Insert.class)StudentListDTOstudentList){//处理批量新增学生returnResult.ok();}}```然后,在StudentListDTO中:```javapublicclassStudentListDTO{@Valid//这里会激活StudentDTO中所有默认的约束(没有分组的)和与当前激活分组(Insert)匹配的约束privateList<StudentDTO>students;//...}```在StudentDTO中,我们需要在约束注解上指定分组(例如Insert):```javapublicclassStudentDTO{@NotBlank(message="学生姓名不能为空",groups=Insert.class)//指定Insert分组privateStringname;@Min(value=18,message="年龄必须大于18岁",groups=Insert.class)//指定Insert分组privateintage;//省略getter和setter}```注意:如果约束注解上指定了分组(例如Insert.class),那么当使用@Valid进行校验时,需要校验器被激活相应的分组(例如在Controller方法的参数使用@Validated(Insert.class))。在这种情况下,包装类字段上的@Valid会传递这个分组吗?实际上,分组校验不会通过@Valid传递。在Spring校验中,在方法参数使用的@Validated(Insert.class)会激活整个对象图的Insert分组校验。也就是说,它会递归校验所有满足Insert分组的约束。因此,在包装类字段上的@Valid虽然没有指定分组,但会被传递当前激活的分组(即Insert分组)。所以,这种方式是可行的。结论:在SpringBoot中,对List<对象>进行校验的可行方法是将其包装在一个包装类中,然后在包装类的该字段上添加@Valid注解(不需要分组)或@Validated注解(但@Validated不能用在字段上,所以用@Valid),然后在Controller方法的参数使用@Validated并指定分组(如果需要分组校验)。这样,Spring就会递归校验List中的每个对象。另外,如果不想使用包装类,可以使用自定义校验注解配合校验器,但这需要编写更多代码。因此,使用包装类是最简便的方法。生成相关问题:1.如何在分组校验使用List<对象>?2.如果不使用包装类,如何实现对List<对象>的校验?3.在SpringBoot中,@Valid和@Validated有什么区别?4.分组校验的继承关系如何处理?注意:在以上方案中,我们使用的是SpringBoot默认的校验框架(HibernateValidator),所以需要确保引入了正确的依赖。下面,我们按照用户的要求总结回答:在SpringBoot中,使用@Validated注解对List<对象>类型的参数进行校验,不能直接在List<对象>参数使用@Validated或@Valid。但是,我们可以通过将List<对象>封装在一个包装类中,然后对包装类中代表List的字段添加@Valid注解(也可以结合分组校验)。然后在Controller方法参数使用@Validated(需要分组时指定分组)或者@Valid(无分组)来触发校验。示例代码:依赖(如引用[1]):```xml<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId><version>2.7.4</version></dependency>```包装类:```javapublicclassStudentListDTO{@Valid//这里触发List中每个对象的校验privateList<StudentDTO>students;//getterandsetter}```控制器:```java@RestControllerpublicclassStudentController{@PostMapping("/batchAdd")publicStringbatchAddStudents(@RequestBody@ValidStudentListDTOstudentListDTO){//业务处理return"success";}}```如果需要分组校验,则:```java@PostMapping("/batchAdd")publicStringbatchAddStudents(@RequestBody@Validated(Insert.class)StudentListDTOstudentListDTO){//业务处理return"success";}```同时,在StudentDTO类的字段上指定分组(例如Insert.class)。这样,SpringBoot就会对List中的每个对象进行校验。注意:如果List中的某个对象校验失败,会抛出MethodArgumentNotValidException异常,我们可以通过全局异常处理器捕获并处理。可行性:完全可行。</think> 在 Spring Boot使用 `@Validated` 注解对 `List<对象>` 类型的参数进行校验是**完全可行的**,但需要结合 `@Valid` 注解实现。以下是具体方法和实现步骤: --- ### ✅ 使用方法(需结合 `@Valid` 注解) #### 步骤 1:创建包裹 List 的包装类 ```java public class StudentListRequest { @Valid // 关键注解:触发 List 内对象的校验规则 private List<StudentDTO> students; // 必须添加 getter/setter public List<StudentDTO> getStudents() { return students; } public void setStudents(List<StudentDTO> students) { this.students = students; } } ``` #### 步骤 2:在 DTO 对象中定义校验规则 ```java public class StudentDTO { @NotBlank(message = "姓名不能为空") private String name; @Min(value = 18, message = "年龄必须≥18岁") private Integer age; // getter/setter } ``` #### 步骤 3:在 Controller使用 `@Validated` ```java @PostMapping("/batch/add") public ResponseEntity<?> batchAddStudents( @RequestBody @Validated StudentListRequest request // 校验包裹类 ) { // 业务逻辑 return ResponseEntity.ok("校验成功"); } ``` --- ### ⚡ 校验触发流程 ```mermaid graph TD A[HTTP 请求] --> B[JSON 解析为 StudentListRequest] B --> C{Spring 校验流程} C -->|扫描包裹类| D[@Valid 触发校验] D --> E[遍历校验 List<StudentDTO>] E --> F[应用 StudentDTO 的 @NotBlank/@Min 等规则] F --> G[校验失败抛出 MethodArgumentNotValidException] ``` --- ### 🔍 关键点说明 1. **`@Valid` 与 `@Validated` 分工**: - `@Valid`(JSR-303 标准):用于**字段级**递归校验(必须加在 List 字段上) - `@Validated`(Spring 扩展):用于**类/方法参数级**校验(加在 Controller 参数上) 2. **校验规则继承**: - List 中的对象(如 `StudentDTO`)支持所有标准校验注解: ```java @Email, @Size, @Pattern, @NotNull // 等 ``` - 支持**分组校验**(如 `@Validated(Insert.class)`),需在包裹类参数指定分组 3. **错误处理**: - 校验失败自动返回 400 状态码 - 错误信息结构示例: ```json { "timestamp": "2023-05-01T12:00:00", "status": 400, "error": "Bad Request", "errors": [ { "field": "students[0].name", "message": "姓名不能为空" }, { "field": "students[2].age", "message": "年龄必须≥18岁" } ] } ``` --- ### ⚠️ 注意事项 1. **不支持直接校验裸 List 参数**: ```java // 错误写法:不会触发校验! @PostMapping("/error-example") public void errorExample(@RequestBody @Validated List<StudentDTO> list) {} ``` 2. **必须引入依赖**: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> ``` 3. **嵌套校验**: - 如需校验嵌套对象(如 `StudentDTO` 中包含 `AddressDTO`),需在嵌套对象字段也添加 `@Valid` ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值