本文目录导读:

针对Java请求校验流程的统一,核心在于利用框架的校验注解 + 全局异常处理 + 自定义校验器,形成标准化的处理模式,以下是目前最主流、最推荐的统一实现方案:
核心思路:三层统一
1 注解层:统一校验规则
- 使用
javax.validation或jakarta.validation标准注解 - 通过
@Valid或@Validated触发校验
2 处理层:统一异常捕获
- 全局异常处理器
@RestControllerAdvice - 统一处理
MethodArgumentNotValidException等校验异常
3 响应层:统一返回格式
- 自定义统一响应体
Result<T> - 封装错误信息返回
完整实现代码
1 统一响应体
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Result<T> {
private Integer code;
private String message;
private T data;
public static <T> Result<T> success(T data) {
return new Result<>(200, "success", data);
}
public static <T> Result<T> error(Integer code, String message) {
return new Result<>(code, message, null);
}
}
2 请求体DTO(使用校验注解)
@Data
public class UserCreateRequest {
@NotBlank(message = "用户名不能为空")
@Length(min = 2, max = 20, message = "用户名长度必须在{min}-{max}之间")
private String username;
@NotNull(message = "年龄不能为空")
@Min(value = 0, message = "年龄不能小于0")
@Max(value = 150, message = "年龄不能超过150")
private Integer age;
@Email(message = "邮箱格式不正确")
private String email;
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
private String phone;
}
3 控制器层(触发校验)
@RestController
@RequestMapping("/api/users")
@Validated // 开启类级别校验
public class UserController {
@PostMapping
public Result<User> create(@Valid @RequestBody UserCreateRequest request) {
// 只有校验通过才会执行到这里
User user = userService.create(request);
return Result.success(user);
}
@GetMapping("/{id}")
public Result<User> getById(@PathVariable @Min(1) Long id) {
// 路径参数校验
return Result.success(userService.getById(id));
}
}
4 全局统一异常处理
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
/**
* 处理 @RequestBody 参数校验异常
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public Result<Void> handleValidationExceptions(MethodArgumentNotValidException ex) {
BindingResult bindingResult = ex.getBindingResult();
// 获取第一个错误信息(或拼接所有错误)
String message = bindingResult.getAllErrors().stream()
.map(DefaultMessageSourceResolvable::getDefaultMessage)
.collect(Collectors.joining("; "));
log.error("参数校验失败: {}", message);
return Result.error(400, message);
}
/**
* 处理 @PathVariable 和 @RequestParam 校验异常
*/
@ExceptionHandler(ConstraintViolationException.class)
public Result<Void> handleConstraintViolationException(ConstraintViolationException ex) {
Set<ConstraintViolation<?>> violations = ex.getConstraintViolations();
String message = violations.stream()
.map(v -> v.getMessage())
.collect(Collectors.joining("; "));
return Result.error(400, message);
}
/**
* 处理参数类型转换异常
*/
@ExceptionHandler(HttpMessageNotReadableException.class)
public Result<Void> handleHttpMessageNotReadableException(HttpMessageNotReadableException ex) {
return Result.error(400, "请求体格式错误");
}
/**
* 处理通用异常
*/
@ExceptionHandler(Exception.class)
public Result<Void> handleException(Exception ex) {
log.error("系统异常", ex);
return Result.error(500, "服务器内部错误");
}
}
进阶技巧:分组校验
针对不同场景(如新增、修改)使用不同校验规则:
@Data
public class UserRequest {
@NotNull(groups = Update.class, message = "ID不能为空")
private Long id;
@NotBlank(groups = {Create.class, Update.class}, message = "用户名不能为空")
private String username;
@Email(groups = {Create.class}, message = "邮箱格式不正确")
private String email;
// 定义分组接口
public interface Create {}
public interface Update {}
}
// 控制器使用
@PostMapping
public Result<User> create(@Validated(UserRequest.Create.class) @RequestBody UserRequest request) {
// ...
}
@PutMapping
public Result<User> update(@Validated(UserRequest.Update.class) @RequestBody UserRequest request) {
// ...
}
自定义校验注解
当标准注解不够用时,创建自己的校验器:
// 1. 定义注解
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = IdCardValidator.class)
public @interface IdCard {
String message() default "身份证号格式不正确";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
// 2. 实现校验器
public class IdCardValidator implements ConstraintValidator<IdCard, String> {
private static final Pattern ID_CARD_PATTERN =
Pattern.compile("^[1-9]\\d{5}(18|19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[0-9Xx]$");
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (value == null) return true; // 不为空交给 @NotBlank 处理
return ID_CARD_PATTERN.matcher(value).matches();
}
}
// 3. 使用
@Data
public class UserRequest {
@IdCard(groups = Create.class)
private String idCard;
}
最佳实践总结
| 组件 | 推荐方案 | 说明 |
|---|---|---|
| 校验框架 | Hibernate Validator | Spring Boot默认集成 |
| 注解方式 | @Valid + @Validated |
@Validated支持分组 |
| 异常处理 | @RestControllerAdvice |
统一拦截 |
| 响应格式 | 统一Result对象 | 保证API一致性 |
| 复杂校验 | 自定义注解 | 复用性强 |
Maven依赖(Spring Boot已内置)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
通过这种方式,所有请求校验逻辑都遵循注解定义规则 → 框架自动校验 → 全局统一处理的标准流程,大大减少了重复的if-else判断,提高了代码的可维护性和可读性。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播