💡 前言
在开发 RESTful 接口时,接口参数校验是保障系统健壮性和安全性的重要一环 。Spring Boot 提供了对 Bean Validation 的开箱即用支持 ------ 通过 spring-boot-starter-validation 模块,我们可以非常方便地使用 JSR-380 标准定义的注解(如 @NotNull
、@NotBlank
、@Email
等)进行参数校验。
本文将带你从零开始掌握如何在 Spring Boot 中使用 spring-boot-starter-validation
,并通过多个实际案例演示其强大功能,包括:
- 单个参数校验
- 对象嵌套校验
- 自定义校验规则
- 全局异常统一处理
- 多语言错误信息支持
无论你是初学者,还是有一定经验的开发者,这篇文章都能让你写出更规范、更健壮的接口!
📦 一、什么是 spring-boot-starter-validation
?
✅ 定义:
spring-boot-starter-validation
是 Spring Boot 提供的一个 starter 模块,它默认集成了 Hibernate Validator,实现了 Java 的 Bean Validation 规范(JSR-380),可以用于对 Java Bean 的字段进行自动校验。
✅ 特性:
特性 | 描述 |
---|---|
零配置 | 默认集成 Hibernate Validator |
注解驱动 | 支持 @NotNull , @Size , @Email 等丰富注解 |
分组校验 | 可以根据业务场景分组验证 |
异常统一处理 | 结合 @ControllerAdvice 统一处理校验失败 |
多语言支持 | 支持国际化错误提示 |
🔧 二、快速入门:引入与使用
Step 1:添加依赖
如果你创建的是一个标准的 Spring Boot Web 项目,spring-boot-starter-web
已经默认包含了 spring-boot-starter-validation
,无需额外添加。
xml
<!-- 如果你想显式添加 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
Step 2:定义请求对象并添加校验注解
java
import javax.validation.constraints.*;
public class UserRequest {
@NotBlank(message = "用户名不能为空")
private String username;
@Email(message = "邮箱格式不正确")
private String email;
@Min(value = 18, message = "年龄不能小于18岁")
@Max(value = 120, message = "年龄不能大于120岁")
private int age;
// getters and setters...
}
Step 3:在 Controller 中启用校验
在 Controller 方法中,使用 @Valid
注解开启校验逻辑,并结合 @RequestBody
使用。
java
@RestController
@RequestMapping("/users")
public class UserController {
@PostMapping
public String createUser(@Valid @RequestBody UserRequest request) {
return "用户提交成功:" + request.toString();
}
}
📌 注意:
@Valid
必须写在方法参数上;- 如果校验失败,会抛出
MethodArgumentNotValidException
异常;
🎯 三、实战:全局异常统一处理
为了统一返回错误信息,我们可以使用 @ControllerAdvice
来捕获所有校验异常。
示例代码:
java
@ControllerAdvice
public class GlobalValidationHandler {
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MethodArgumentNotValidException.class)
public Map<String, String> handleValidationExceptions(MethodArgumentNotValidException ex) {
Map<String, String> errors = new HashMap<>();
ex.getBindingResult().getAllErrors().forEach((error) -> {
String fieldName = ((org.springframework.validation.FieldError) error).getField();
String errorMessage = error.getDefaultMessage();
errors.put(fieldName, errorMessage);
});
return errors;
}
}
返回示例:
json
{
"username": "用户名不能为空",
"email": "邮箱格式不正确"
}
🧪 四、高级用法详解
✅ 1. 嵌套对象校验
你可以对嵌套的对象也进行校验:
java
public class AddressRequest {
@NotBlank(message = "地址不能为空")
private String detail;
// getter/setter
}
public class UserRequest {
@NotBlank(message = "用户名不能为空")
private String username;
@NotNull(message = "地址信息不能为空")
private AddressRequest address;
// getter/setter
}
只要加上 @Valid
注解,Spring 会自动递归校验嵌套对象。
✅ 2. 分组校验(Group Validation)
有时候你希望同一个对象在不同接口中使用不同的校验规则?这时就可以使用分组校验。
第一步:定义分组接口
java
public interface OnCreate {}
public interface OnUpdate {}
第二步:在实体类中指定分组
java
public class UserRequest {
@NotBlank(groups = OnCreate.class, message = "创建时用户名不能为空")
@NotBlank(groups = OnUpdate.class, message = "更新时用户名不能为空")
private String username;
@NotBlank(groups = OnCreate.class, message = "邮箱不能为空")
private String email;
}
第三步:在 Controller 中指定分组
java
@PostMapping("/create")
public String createUser(@Validated(OnCreate.class) @RequestBody UserRequest request) {
return "创建用户";
}
@PostMapping("/update")
public String updateUser(@Validated(OnUpdate.class) @RequestBody UserRequest request) {
return "更新用户";
}
📌 注意:此时必须使用 @Validated
注解(来自 org.springframework.validation.annotation.Validated
),而非 @Valid
。
✅ 3. 自定义校验规则
当内置注解不能满足需求时,可以自定义校验器。
步骤如下:
Step 1:创建注解
java
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = MobileValidator.class)
public @interface Mobile {
String message() default "手机号格式不正确";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Step 2:实现校验器
java
public class MobileValidator implements ConstraintValidator<Mobile, String> {
private static final String MOBILE_REGEX = "^1[3-9]\\d{9}$";
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
return value != null && value.matches(MOBILE_REGEX);
}
}
Step 3:使用注解
java
@Mobile(message = "手机号格式错误")
private String mobile;
📘 五、国际化支持(i18n)
你可以为不同语言提供不同的错误提示信息:
在 messages.properties
文件中定义:
properties
NotBlank.userRequest.username=用户名不能为空
Mobile.userRequest.mobile=手机号格式错误
再配合 Spring 的 MessageSource
和 LocaleResolver
,即可实现多语言错误提示。
🧩 六、常见问题与解决方案
问题 | 解决方案 |
---|---|
校验不生效 | 确保使用 @Valid 或 @Validated |
嵌套对象未校验 | 确保子对象字段也加了注解 |
分组无效 | 确保使用 @Validated 并指定分组 |
错误信息乱码 | 设置响应编码或使用 JSON 序列化 |
无法获取字段名 | 使用 FieldError 获取具体字段 |
📊 七、总结对比表
功能 | 描述 |
---|---|
校验方式 | 注解驱动,声明式校验 |
异常处理 | @ControllerAdvice 统一处理 |
嵌套对象 | 支持递归校验 |
分组校验 | 支持按业务场景定制 |
自定义规则 | 支持自定义注解和校验器 |
国际化 | 支持多语言提示 |
🎁 八、结语
Spring Boot 提供的 spring-boot-starter-validation
模块极大简化了接口参数校验的开发流程,使得我们能够以最小的成本写出安全、规范、可维护性强的接口代码。
无论是构建企业级后台系统,还是搭建高并发 API 平台,都应该合理使用参数校验来提升系统的稳定性与用户体验。
🎯 点赞、收藏、转发本文,让更多开发者受益!