SpringBoot请求体校验:如何禁止传入空列表?
解决SpringBoot中列表非空且非空列表的校验问题
一、使用标准校验注解解决
你当前用的@NonNull是Lombok注解,它仅校验对象不为null,但空列表([])本身是一个存在的List对象,所以不会触发校验失败。要同时满足“属性必须存在、列表不为空列表”的要求,直接用JSR-380(或Jakarta Validation)的标准注解即可:
1. 选择合适的注解
@NotEmpty:同时校验对象不为null、集合/数组不为空(元素个数>0),完全匹配你的需求。@Size(min = 1):仅校验集合元素个数至少为1,若要同时确保属性存在,需配合@NotNull(不过@NotEmpty已经包含了@NotNull的逻辑)。
2. 修改BodyDto代码
根据你的SpringBoot版本选择对应的注解包:
- SpringBoot 2.x:使用
javax.validation.constraints包下的注解
@Getter @Setter @AllArgsConstructor public class BodyDto { @NotEmpty(message = "route不能为空且不能是空列表") private List<String> route; }
- SpringBoot 3.x:使用
jakarta.validation.constraints包下的注解(SpringBoot 3+切换到Jakarta EE规范)
@Getter @Setter @AllArgsConstructor public class BodyDto { @NotEmpty(message = "route不能为空且不能是空列表") private List<String> route; }
3. 确保依赖正确
如果之前没引入校验依赖,需要添加SpringBoot的validation starter:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency>
二、注解不生效的排查点
如果添加注解后仍然没触发校验,检查以下几点:
- 注解包是否导错:别误导入Lombok或Hibernate的同名注解,必须是
javax.validation.constraints(SpringBoot2)或jakarta.validation.constraints(SpringBoot3)下的@NotEmpty。 - 控制器方法是否正确标记:确保
@RequestBody前的@Valid(或Spring的@Validated)注解存在,你当前的控制器代码是正确的,但如果用了@Validated需要注意分组规则。 - 是否捕获校验异常:默认情况下,校验失败会抛出
MethodArgumentNotValidException,如果没有全局异常处理器,可能看不到明确的错误响应。可以添加全局异常处理器返回友好提示:
@RestControllerAdvice public class GlobalValidationExceptionHandler { @ExceptionHandler(MethodArgumentNotValidException.class) public ResponseEntity<Map<String, String>> handleValidationErrors(MethodArgumentNotValidException ex) { Map<String, String> errorMap = new HashMap<>(); ex.getBindingResult().getFieldErrors().forEach(error -> errorMap.put(error.getField(), error.getDefaultMessage()) ); return new ResponseEntity<>(errorMap, HttpStatus.BAD_REQUEST); } }
三、自定义校验(复杂场景可选)
如果需要更定制化的校验规则(比如同时校验列表元素不为空),可以自定义校验注解:
1. 定义自定义注解
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = NonEmptyListValidator.class) public @interface NonEmptyList { String message() default "列表不能为空且不能是空列表"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
2. 实现校验逻辑
public class NonEmptyListValidator implements ConstraintValidator<NonEmptyList, List<?>> { @Override public boolean isValid(List<?> list, ConstraintValidatorContext context) { // 校验列表不为null且元素个数>0 return list != null && !list.isEmpty(); } }
3. 在Dto中使用
@Getter @Setter @AllArgsConstructor public class BodyDto { @NonEmptyList private List<String> route; }
内容的提问来源于stack exchange,提问作者Oğuz Öztınaz
相关产品推荐
相关产品推荐

