前言
参数校验是保证程序健壮性的重要环节,前端校验为用户体验,后端校验为系统安全。Spring Boot 中常用 @Valid
和 @Validated
实现参数校验,本文将详细解析两者的区别、用法及代码示例。
一、@Valid 注解
1. 功能与依赖
- 标准规范:属于 Java EE 标准注解(JSR 303 规范),用于触发参数合法性校验。
- 依赖引入:
- Spring Boot 项目:已包含在
spring-boot-starter-web
中,无需额外引入。 - 非 Spring Boot 项目:需手动添加
javax.validation
和hibernate-validator
依赖。
- Spring Boot 项目:已包含在
<!-- 非Spring Boot项目依赖 -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
2. 使用场景
- 适用位置:方法参数、构造函数、成员属性(field)、方法返回值。
- 核心功能:支持嵌套校验(对对象中的属性值,甚至嵌套对象进行校验)。
-
代码示例:
// 实体类 @Data public class SysUser { @NotBlank(message = "姓名不能为空") @Length(max = 10, message = "名称不能超过{max}字符") private String name; @NotNull(message = "年龄不能为空") @Range(min = 1, max = 100, message = "年龄范围为{min}到{max}岁") private Integer age; }
// 控制器 @RestController @RequestMapping("/sysUser") public class SysUserController { @PostMapping("/add") public String addUser(@RequestBody @Valid SysUser sysUser, BindingResult bindingResult) { if (bindingResult.hasErrors()) { return bindingResult.getAllErrors().get(0).getDefaultMessage(); // 返回第一条错误信息 } return "操作成功!"; } }
说明:需通过
BindingResult
手动捕获校验结果,若不处理错误,程序不会中断执行。
二、@Validated 注解
1. 功能与定位
- Spring 专属:Spring 框架特有的注解,是
@Valid
的增强版,支持分组验证。 - 无嵌套校验:仅能对单一对象进行校验,无法递归验证嵌套对象。
2. 使用场景
- 适用位置:类、方法、方法参数(不能用于成员属性)。
-
分组验证:针对同一对象的不同操作(如新增、更新),设置不同的校验规则。
// 分组接口 public interface CreationGroup {} // 新增分组 public interface UpdateGroup {} // 更新分组
// 实体类(分组校验示例) @Data public class SysUser { @NotNull(message = "更新时ID不能为空", groups = UpdateGroup.class) private String id; @NotBlank(message = "名字不能为空", groups = {CreationGroup.class, UpdateGroup.class}) @Size(min = 6, max = 12, message = "名字长度在6-12之间") private String name; }
// 控制器(分组校验应用) @RestController public class SysUserController { @PostMapping("/insert") public String insertUser(@Validated(CreationGroup.class) @RequestBody SysUser sysUser, BindingResult bindingResult) { if (bindingResult.hasErrors()) { return "插入失败:" + bindingResult.getFieldError().getDefaultMessage(); } return "插入成功"; } @PostMapping("/update") public String updateUser(@Validated(UpdateGroup.class) @RequestBody SysUser sysUser, BindingResult bindingResult) { // 同上逻辑 } }
3. 全局异常处理
- 自动抛异常:使用
@Validated
时,若校验失败,程序会自动抛出MethodArgumentNotValidException
。 - 统一捕获:通过
@RestControllerAdvice
全局捕获异常,返回友好提示。@RestControllerAdvice public class ValidatedExceptionHandler { @ExceptionHandler(MethodArgumentNotValidException.class) @ResponseBody @ResponseStatus(HttpStatus.BAD_REQUEST) public Result
handleValidationException(MethodArgumentNotValidException ex) { String errorMessage = ex.getBindingResult().getAllErrors().get(0).getDefaultMessage(); return Result.error("参数校验失败:" + errorMessage); } }
三、核心区别对比
维度 | @Valid | @Validated |
---|---|---|
所属框架 | Java EE(JSR 303) | Spring 框架 |
嵌套校验 | 支持(可校验嵌套对象) | 不支持 |
分组验证 | 不支持 | 支持(通过 groups 参数定义分组) |
适用位置 | 方法、构造函数、参数、成员属性 | 类、方法、参数(不能用于成员属性) |
校验结果处理 | 需手动通过 BindingResult 捕获 |
自动抛出异常,需全局捕获处理 |
代码简洁性 | 需显式处理错误结果 | 自动中断流程,代码更简洁 |
四、参数校验常用注解
1. 值校验
注解 | 说明 | 示例 |
---|---|---|
@Null |
必须为 null |
@Null(message = "人数必须为null") |
@NotNull |
不能为 null |
@NotNull(message = "人数不能为空") |
@NotBlank |
字符串非空(至少一个非空格字符) | @NotBlank(message = "姓名不能为空") |
@NotEmpty |
集合/数组非空 | @NotEmpty(message = "组织部门不能为空") |
@Positive |
必须为正数 | @Positive(message = "金额必须为正数") |
2. 范围校验
注解 | 说明 | 示例 |
---|---|---|
@Min |
最小值约束 | @Min(value = 18, message = "年龄≥18") |
@Max |
最大值约束 | @Max(value = 120, message = "年龄≤120") |
@Range |
范围约束(min/max) | @Range(min = 18, max = 80, message = "年龄范围") |
@Past |
必须为过去时间 | @Past(message = "日期必须为过去") |
3. 长度校验
注解 | 说明 | 示例 |
---|---|---|
@Size |
集合/数组长度约束 | @Size(min = 7, max = 11, message = "长度7-11") |
@Length |
字符串长度约束 | @Length(min = 6, max = 12, message = "姓名长度") |
4. 格式校验
注解 | 说明 | 示例 |
---|---|---|
@Pattern |
正则匹配 | @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式错误") |
@Email |
邮箱格式校验 | @Email(message = "请输入有效邮箱") |
@URL |
URL 格式校验 | @URL(message = "无效的URL地址") |
五、总结
- 选择建议:
- 需要嵌套校验(如对象中包含子对象)时,使用
@Valid
。 - 需要分组验证(如不同业务场景执行不同校验规则)时,使用
@Validated
。
- 需要嵌套校验(如对象中包含子对象)时,使用
- 最佳实践:
- 统一使用
@Validated
简化代码,通过全局异常处理统一返回错误信息。 - 复杂校验场景结合分组验证,提高代码可维护性。
- 统一使用
掌握 @Valid
和 @Validated
的区别,能更灵活地实现参数校验,保障系统数据的完整性和安全性。
除非注明,否则均为李锋镝的博客原创文章,转载必须以链接形式标明本文链接
文章评论
您好,请问您的自定义域名邮箱mailme@lifengdi.com是怎么实现的,自建的吗?
@lzj 用的是阿里云的企业邮箱。