spring boot 校验数组元素需要在 controller 方法参数上同时使用 @valid 和 @requestbody,并在实体类中为 list 或 array 字段添加 @valid 注解。这样 spring 会自动遍历集合中的每个对象并执行校验规则,任何元素校验失败都会抛出 methodargumentnotvalidexception。

如何配置 DTO 以支持嵌套校验
在 DTO 类中定义 List 或 Array 类型的字段时,必须在该字段上显式添加 @Valid 注解。如果没有这个注解,即使内部对象有校验规则,Spring 也不会触发递归校验。例如,定义一个包含用户列表的注册请求 DTO,其中 UserDTO 包含姓名和年龄字段,分别使用 @NotBlank 和 @Min 进行约束。

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Min;
public class UserDTO {
@NotBlank(message = "用户名不能为空")
private String name;
@Min(value = 18, message = "年龄必须大于等于18岁")
private Integer age;
// getters and setters
}
接下来是主 DTO,它包含一个 UserDTO 的列表:
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.List;
public class RegisterRequest {
@NotNull(message = "用户列表不能为空")
@Valid // 关键:启用对列表中元素的校验
private List<userdto> users;
// getters and setters
}</userdto>
Controller 层接收请求:
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
@RestController
@RequestMapping("/api")
public class UserController {
@PostMapping("/register")
public String register(@RequestBody @Valid RegisterRequest request) {
return "Validation passed";
}
}
当发送如下 JSON 时:
{
"users": [
{ "name": "Alice", "age": 20 },
{ "name": "", "age": 15 }
]
}
第二个用户因姓名为空且年龄小于18,将导致校验失败,返回 400 错误及具体消息。
如何自定义数组级别的校验逻辑
除了逐个元素校验,有时需要基于整个数组的状态进行校验,例如确保数组长度至少为1,或所有元素之和不超过阈值。此时可以创建自定义 Constraint 注解和 Validator 实现类。通过实现 ConstraintValidator 接口,可以在 isValid 方法中访问整个数组并进行复杂判断。

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
@Documented
@Constraint(validatedBy = SumLimitValidator.class)
@Target({ ElementType.FIELD, ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface SumLimit {
int max() default 100;
String message() default "总和不能超过最大值";
Class>[] groups() default {};
Class extends Payload>[] payload() default {};
}
对应的 Validator 实现:
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Arrays;
public class SumLimitValidator implements ConstraintValidator<sumlimit int> {
private int max;
@Override
public void initialize(SumLimit constraintAnnotation) {
this.max = constraintAnnotation.max();
}
@Override
public boolean isValid(int[] values, ConstraintValidatorContext context) {
if (values == null || values.length == 0) {
return true; // 允许空数组,由其他注解控制非空
}
int sum = Arrays.stream(values).sum();
return sum <p>在 DTO 中使用该注解:</p>
<pre class="brush:php;toolbar:false;">import javax.validation.constraints.NotNull;
public class ScoreRequest {
@NotNull
@SumLimit(max = 300, message = "总分不能超过300")
private int[] scores;
// getters and setters
}
当传入 scores: [100, 100, 100] 时,总和为300,校验通过;若传入 [100, 100, 101],则校验失败。
当数组中包含重复元素时校验行为如何
Spring Boot 的参数校验机制不关心数组或列表中是否存在重复元素。校验是针对每个独立实例执行的,无论是否重复,只要其属性违反约束,就会报错。例如,若 UserDTO 中要求 name 唯一,这不属于 Bean Validation 标准范围,需手动处理。但像 @NotBlank 这样的规则,对每个元素单独生效,重复值不会导致额外错误或忽略。











