在基于Spring Boot的Java项目中,对前端传来的QO(Query Object)对象进行参数校验是保障数据有效性和安全性的核心步骤。以下是具体的实现方法、常用校验类型及示例:
一、校验实现步骤
1. 添加依赖
确保项目中引入Spring Boot Validation依赖(基于Hibernate Validator实现):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
2. 在QO类中声明校验注解
在QO对象的字段上使用JSR 303规范提供的校验注解。 (一开始知道简单的就可以了,没必要记住,不会的现查就ok,用多了就熟了)
示例:定义一个接收用户查询条件的QO类:
public class UserQueryQo {
@NotBlank(message = "用户名不能为空")
@Size(min = 2, max = 20, message = "用户名长度需在2-20之间")
private String username;
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式错误")
private String phone;
@Email(message = "邮箱格式错误")
private String email;
@NotNull(message = "用户类型不能为空")
@Range(min = 1, max = 3, message = "用户类型需为1-3")
private Integer userType;
@Valid // 嵌套对象校验
private AddressQo address;
}
3. 在Controller中触发校验
在接口方法的QO参数前添加@Valid或@Validated注解,以触发自动校验:
@RestController
public class UserController {
@PostMapping("/query")
public Result queryUsers(@RequestBody @Validated UserQueryQo qo) {
// 业务逻辑
return Result.ok();
}
}
二、常用校验类型及注解
| 校验类型 | 注解 | 作用 | 示例 |
|---|---|---|---|
| 非空校验 | @NotBlank | 校验字符串非空且长度>0(仅适用于String) | @NotBlank(message = "用户名不能为空") |
| 数值范围校验 | @Min / @Max | 限制数值的最小/最大值 | @Min(value = 18, message = "年龄需≥18") |
| 正则表达式校验 | @Pattern | 校验字符串是否符合正则表达式 | `@Pattern(regexp = "^[男 |
| 集合/数组校验 | @NotEmpty | 校验集合/数组非空 | @NotEmpty(message = "角色列表不能为空") |
| 日期校验 | @Future / @Past | 校验日期是否为未来/过去时间 | @Future(message = "生效时间必须为未来时间") |
| 嵌套对象校验 | @Valid | 递归校验嵌套对象的字段 | @Valid private AddressQo address; |
三、高级校验场景
1. 分组校验
为不同接口场景定义不同的校验规则:
// 定义分组接口
public interface CreateGroup {}
public interface UpdateGroup {}
// QO类中使用分组
public class UserQo {
@NotNull(groups = {UpdateGroup.class}, message = "用户ID不能为空")
private Long id;
@NotBlank(groups = {CreateGroup.class, UpdateGroup.class}, message = "用户名不能为空")
private String username;
}
// Controller中指定分组
@PostMapping("/create")
public Result createUser(@RequestBody @Validated(CreateGroup.class) UserQo qo) { ... }
2. 自定义校验
通过自定义注解实现复杂逻辑(如跨字段校验):
// 定义注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = DateRangeValidator.class)
public @interface ValidDateRange {
String message() default "结束时间必须晚于开始时间";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
// 实现校验逻辑
public class DateRangeValidator implements ConstraintValidator<ValidDateRange, UserQueryQo> {
@Override
public boolean isValid(UserQueryQo qo, ConstraintValidatorContext context) {
return qo.getEndTime().after(qo.getStartTime());
}
}
// 在QO类上应用注解
@ValidDateRange
public class UserQueryQo { ... }
四、统一异常处理
校验失败时,Spring Boot会抛出MethodArgumentNotValidException,需全局捕获并返回友好提示:
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result handleValidationException(MethodArgumentNotValidException ex) {
BindingResult result = ex.getBindingResult();
String errorMsg = result.getFieldErrors().stream()
.map(error -> error.getField() + ": " + error.getDefaultMessage())
.collect(Collectors.joining(", "));
return Result.fail(400, errorMsg);
}
}
五、完整示例
QO类:
public class OrderQueryQo {
@NotBlank(message = "订单号不能为空")
private String orderId;
@NotNull(message = "用户ID不能为空")
@Min(value = 1, message = "用户ID需为正整数")
private Long userId;
@Pattern(regexp = "^(pending|shipped|delivered)$", message = "状态值不合法")
private String status;
@Valid
private PaymentInfoQo paymentInfo;
}
Controller接口:
@PostMapping("/orders")
public Result queryOrders(@RequestBody @Validated OrderQueryQo qo) {
// 业务逻辑
return Result.ok();
}
2850

被折叠的 条评论
为什么被折叠?



