在spring boot中实现参数强校验需三步:一是在实体类用@notblank、@min等jsr-303注解声明规则;二是在controller入参加@valid/@validated并配bindingresult捕获错误;三是引入spring-boot-starter-validation依赖,推荐用@restcontrolleradvice统一处理methodargumentnotvalidexception异常。

在初级 MVC 脚手架(如 Spring Boot + Spring MVC)中,用实体类实现接收参数的合法性强校验,核心是借助 JSR-303/JSR-380(Bean Validation)规范,配合框架自动绑定与拦截机制,无需手动写 if 判断。关键不在“能不能”,而在“怎么配、怎么写、怎么接”。
实体类上加标准校验注解
这是强校验的起点——把规则声明在数据模型本身,而非 Controller 里。使用 javax.validation.constraints 下的注解,语义清晰且可复用:
-
@NotBlank:适用于 String,非 null 且 trim 后长度 > 0(比@NotNull更严格) -
@Min(1) / @Max(100):用于数值型字段,如订单数量、分页 size -
@Email、@Pattern(regexp = "^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}$"):邮箱和自定义正则校验 -
@Size(min = 5, max = 20):同时约束 String 长度和集合大小 -
@PastOrPresent:日期类字段(如创建时间不能是未来)
示例:
public class UserRequest {
@NotBlank(message = "用户名不能为空")
private String username;
@Min(value = 6, message = "密码长度至少6位")
private Integer passwordLength;
@Email(message = "邮箱格式不正确")
private String email;
// 必须有 getter/setter
}
Controller 中启用校验并捕获结果
仅加注解不会触发校验,必须在入参前加 @Valid 或 @Validated,并紧跟 BindingResult 接收错误:
- 用
@Valid:基于 Hibernate Validator,支持级联校验(如字段类型也是带注解的实体) - 用
@Validated:Spring 原生支持,可指定校验组(适合不同接口复用同一实体但校验规则不同) -
BindingResult必须紧挨着被校验参数,顺序不能错;否则校验失败会直接返回 400 错误,无法自定义响应
示例:
@PostMapping("/user")
public ResponseEntity> createUser(@Valid @RequestBody UserRequest req, BindingResult result) {
if (result.hasErrors()) {
String errorMsg = result.getAllErrors().stream()
.map(e -> e.getDefaultMessage())
.collect(Collectors.joining("; "));
return ResponseEntity.badRequest().body(Map.of("error", errorMsg));
}
// 正常业务逻辑
return ResponseEntity.ok().build();
}
确保项目已引入校验依赖
Spring Boot 2.3+ 默认移除了 spring-boot-starter-validation 的自动依赖,需显式添加:
<dependency><groupid>org.springframework.boot</groupid><artifactid>spring-boot-starter-validation</artifactid></dependency>
该依赖会自动拉取 jakarta.validation-api 和 hibernate-validator,无需额外配置验证器 Bean。
进阶:统一异常处理避免重复判断
每个接口都写 if (result.hasErrors()) 易出错且冗余。推荐全局捕获 MethodArgumentNotValidException,统一格式化返回:
@RestControllerAdvice
public class ValidationExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<map string>> handleValidationExceptions(
MethodArgumentNotValidException ex) {
Map<string string> errors = new HashMap();
ex.getBindingResult().getAllErrors().forEach((error) -> {
String fieldName = ((FieldError) error).getField();
String errorMessage = error.getDefaultMessage();
errors.put(fieldName, errorMessage);
});
return ResponseEntity.badRequest().body(errors);
}
}</string></map>
这样 Controller 就可以彻底去掉 BindingResult 参数,专注业务逻辑。











