孓访懔 发表于 2025-6-2 23:49:53

校验参数的6大神功!

新手司机翻车实录

"哥,注册接口又被刷爆了!
"某一个周末下午,我接到电话,打开日志一看,NullPointerException堆栈里有38个不同位置的校验逻辑。
原来新人小王在Controller里写满了这样的代码:
// 典型错误示范(转载自某小厂祖传代码)
public String register(UserDTO user) {
    if (user.getName() == null) {
      return "名字不能为空";
    }
    if (user.getAge() == null) {
      return "年龄不能为空";
    }
    if (user.getAge() < 18) {
      return "年龄不能小于18岁";
    }
    if (!user.getPhone().matches("^1\\d{9}$")) {
      return "手机号不合法";
    }
    // ...后续还有20个if...
}这才是代码界的"九转大肠"——每个入口都让人窒息。
作为一位有很多开发经验的老司机,今天,老夫带你修炼参数校验的6大神功。

希望对你会有所帮助。
第一重:JSR规范基础功

1.1 HibernateValidator瞬炼大法

可以使用Hibernate中Validator框架做参数校验,具体代码如下:
public class UserDTO {
    @NotBlank(message = "名称要填,皮这一下很开心?")
    private String name;

    @NotNull
    @Min(value = 18, message = "未成年禁止入内")
    @Max(60)
    private Integer age;

    @Pattern(regexp = "^1\\d{9}$", message = "这手机号是哪国来的?")
    private String phone;
}

// Controller层启用校验(新手必知第一步)
@PostMapping("/register")
public Result register(@Valid @RequestBody UserDTO user) {
    // 业务代码...
}技术要点:

[*]引入spring-boot-starter-validation依赖(调料包记得加)
[*]@Valid注解要放在入参侧(别贴在DTO类上)
[*]错误信息会进BindingResult(打扫战场需要手动处理)
第二重:全局异常擒龙手

2.1 统一异常拦截器

我们需要对异常进行统一拦截。
这样在出现参数校验异常,比如空指针时,不会把服务的内部错误信息直接输出给用户。
通过@RestControllerAdvice和@ExceptionHandler注解实现统一异常拦截器的功能。
具体代码如下:
@RestControllerAdvice
public class GlobalExceptionHandler {
   
    // 专治各种不服校验
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result handleValidException(MethodArgumentNotValidException e) {
      BindingResult result = e.getBindingResult();
      return Result.fail(result.getFieldError().getDefaultMessage());
    }
}

// 返回格式规范(示例)
public class Result<T> {
    private Integer code;
    private String msg;
    private T data;
   
    public static <T> Result<T> fail(String message) {
      return new Result<>(500, message, null);
    }
}反爬虫机制:

[*]禁止直接暴露字段名给前端(攻击者会利用字段名信息)
[*]错误信息字典化管理(后面会教国际化这招)
第三重:自定义校验屠龙技

3.1 手机/邮箱二元校验

有时候,Hibernate Validator框架或者其他校验框架定义的校验不满足需求,我们需要自定义校验规则。
则可以自定义注解,实现ConstraintValidator接口,来实现具体的自定义的校验逻辑。
自定义注解@Contact在字段上使用。
具体代码如下:
@Target({FIELD, PARAMETER})@Retention(RUNTIME)@Constraint(validatedBy = ContactValidator.class)public @interface Contact {    String message() default "联系方式格式错误";    Class[] groups() default {};    Class
页: [1]
查看完整版本: 校验参数的6大神功!