一、JSR 303 定义
Java 为 Bean 数据合法性校验提供的标准框架,包含于 JavaEE 6.0 标准中。
- 核心机制:通过在 Bean 属性上标注
@NotNull、@Max 等标准注解定义校验规则,通过标准接口完成校验。
二、数据校验使用流程
引入依赖:
spring-boot-starter-validation(整合 JSR 303 实现,如 Hibernate Validator)。
定义数据封装 Bean(VO):
通常为接收前端参数的实体类(如 EmployeeAddVo)。
标注校验注解:
在 Bean 字段上添加标准注解(如 @NotBlank、@Email)或自定义注解,指定错误提示消息。
开启校验:
在 Controller 方法参数上使用 @Valid 或 @Validated 触发校验。
处理校验结果:
- 方式 1:通过
BindingResult 手动获取校验错误(需紧跟被校验参数)。
- 方式 2:结合全局异常处理,统一捕获校验失败异常(推荐)。
自定义校验规则:
通过 “自定义注解 + 校验器” 实现复杂校验(如性别只能为 “男” 或 “女”)。
错误消息国际化:
校验注解的 message 属性使用占位符(如 {gender.message}),结合 i18n 配置文件实现多语言提示。
全局异常处理:
捕获 MethodArgumentNotValidException 异常,统一封装并返回校验错误信息。
三、自定义校验实现(以性别校验为例)
1. 定义自定义注解 @Gender
java
运行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| package com.atguigu.practice.annotation;
import com.atguigu.practice.vaildator.GenderValidator; import jakarta.validation.Constraint; import jakarta.validation.Payload; import java.lang.annotation.*;
@Documented @Constraint(validatedBy = {GenderValidator.class}) @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface Gender { String message() default "{jakarta.validation.constraints.NotNull.message}"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
|
2. 实现校验器 GenderValidator
需实现 ConstraintValidator<注解类型, 校验字段类型> 接口:
java
运行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package com.atguigu.practice.vaildator;
import com.atguigu.practice.annotation.Gender; import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext;
public class GenderValidator implements ConstraintValidator<Gender, String> {
@Override public boolean isValid(String value, ConstraintValidatorContext context) { return "男".equals(value) || "女".equals(value); } }
|
3. 在 VO 中使用自定义注解
java
运行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| package com.atguigu.practice.vo.req;
import com.atguigu.practice.annotation.Gender; import jakarta.validation.constraints.*; import lombok.Data; import java.math.BigDecimal;
@Data public class EmployeeAddVo { @NotBlank(message = "姓名不能为空") private String name;
@NotNull(message = "年龄不能为空") @Max(value = 150, message = "年龄不能大于150岁") @Min(value = 0, message = "年龄不能小于0岁") private Integer age;
@Email(message = "邮箱格式不正确") private String email;
@Gender(message = "{gender.message}") private String gender;
private String address; private BigDecimal salary; }
|
4. Controller 中开启校验
java
运行
1 2 3 4 5 6 7 8 9 10
| @PostMapping("/employee")
public R add(@RequestBody @Valid EmployeeAddVo vo) { Employee employee = new Employee(); BeanUtils.copyProperties(vo, employee); employeeService.addEmp(employee); return R.ok(); }
|
5. 全局异常处理校验错误
java
运行
1 2 3 4 5 6 7 8 9 10 11 12 13
| @ExceptionHandler(MethodArgumentNotValidException.class) public R handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { BindingResult result = e.getBindingResult(); List<FieldError> fieldErrors = result.getFieldErrors(); Map<String, String> errorsMap = new HashMap<>(); for (FieldError error : fieldErrors) { errorsMap.put(error.getField(), error.getDefaultMessage()); } return R.error(500, "参数不正确", errorsMap); }
|
核心说明
- 标准注解(如
@NotBlank、@Email)适用于通用校验,自定义注解适用于业务特定规则。
- 全局异常处理替代手动处理
BindingResult,简化代码并统一响应格式。
- 国际化通过
message 占位符 + i18n 文件实现,支持多语言场景。