JSR 303(即 Bean Validation)是一个通过注解在 Java Bean 上定义和执行验证规则的规范
🛠️ 一、JSR 303是什么?
JSR 303(Java Specification Requests 303)是Java EE 6的子规范,全称Bean Validation。它通过注解方式对JavaBean的属性值进行标准化校验,例如检查非空、长度、格式等规则。其参考实现是Hibernate Validator(与Hibernate ORM无关)
核心价值:
✅ 将校验逻辑从业务代码剥离,提升代码可维护性
✅ 统一校验规则,避免重复编码
✅ 支持编译时和运行时校验,增强数据安全性(防止恶意绕过前端校验)
⚙️ 二、快速入门:基础使用
1️⃣ 环境搭建
- Spring Boot项目:添加依赖:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId>
</dependency>
- 非Spring项目:需手动引入
validation-api
和hibernate-validator
2️⃣ 常用内置注解
注解 | 适用类型 | 说明 | 示例 |
---|---|---|---|
@NotNull | 任意 | 值不能为null | @NotNull(message="ID不能为空") |
@NotBlank | String | 非null且去除空格后长度>0 | @NotBlank(message="用户名必填") |
@Size | 集合/String | 长度在指定范围内 | @Size(min=6, max=20, message="密码需6-20位") |
@Email | String | 邮箱格式校验 | @Email(message="邮箱格式无效") |
@Pattern | String | 正则表达式匹配 | @Pattern(regexp="^1[3-9]\\d{9}$", message="手机号格式错误") |
@Min /@Max | 数字类型 | 数值范围限制 | @Min(value=18, message="年龄需≥18") |
3️⃣ 在Controller中使用
通过@Valid
或@Validated
触发校验:
@PostMapping("/user")
public ResponseEntity<String> createUser(@Valid @RequestBody UserDTO user) {// 校验通过才执行业务逻辑return ResponseEntity.ok("创建成功");
}
- 校验失败会抛出
MethodArgumentNotValidException
,需全局异常处理
⚡ 三、进阶技巧
1️⃣ 分组校验
解决同一字段在不同场景(如新增/修改)下的差异化校验需求:
// 定义分组接口
public interface AddGroup {}
public interface UpdateGroup {}// 实体类中使用
public class User {@Null(groups = AddGroup.class, message = "新增时ID必须为空")@NotNull(groups = UpdateGroup.class, message = "修改时ID不能为空")private Long id;
}// Controller指定分组
@PostMapping("/update")
public R update(@Validated(UpdateGroup.class) @RequestBody User user) {// ...
}
注:未分组的注解在分组校验中不生效
2️⃣ 自定义校验
步骤:
- 定义注解:
@Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = ListValueConstraintValidator.class) public @interface ListValue {String message() default "值不在可选范围内";Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};int[] vals() default {}; // 允许的值列表,如[0,1] }
- 实现校验器:
public class ListValueConstraintValidator implements ConstraintValidator<ListValue, Integer> {private Set<Integer> set = new HashSet<>();@Overridepublic void initialize(ListValue constraintAnnotation) {for (int val : constraintAnnotation.vals()) {set.add(val);}}@Overridepublic boolean isValid(Integer value, ConstraintValidatorContext context) {return set.contains(value);} }
- 使用自定义注解:
@ListValue(vals = {0, 1}, message = "状态只能是0或1") private Integer status;
💎 四、常见问题
-
Q:
@Valid
vs@Validated
?@Valid
(JSR标准):不支持分组,可嵌套校验字段。@Validated
(Spring扩展):支持分组,不可用于字段
-
Q:校验失败如何获取具体错误?
在Controller参数中添加BindingResult result
,通过result.getFieldErrors()
遍历错误详情 -
Q:为什么int类型推荐用
Integer
?
@Min
等注解在基本类型(如int
)上无法处理空值,而Integer
可兼容null
校验
📚 总结
JSR 303通过声明式注解简化数据校验。初学者可逐步掌握:
1️⃣ 基础注解 → 2️⃣ Controller集成 → 3️⃣ 分组/自定义校验 → 4️⃣ 全局异常处理
结合Spring生态(如Spring MVC)能极大提升开发效率和系统健壮性
更多实践参考:Hibernate Validator文档或Spring官方教程。