【Java中如何优雅地校验项目中请求入参】

项目中如何优雅的搞定请求入参校验

业务场景:比如说咱们项目里面某个微服务下多个请求接口都要对手机号校验,项目里面一般大家都是协同开发,可能会存在这人写一套正则,另一个牛逼的同事写一套自己的校验算法等…巴拉巴拉,最终都能实现对这个手机号校验,本身没问题,这样项目上可能会显得比较臃肿,那如何优雅的统一做入参校验呢?
接下来就一起看个demo吧~

第一步:定义自定义注解@Mobile

@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = MobileValidator.class)
public @interface Mobile {
  boolean required() default true;
  /**
   * 校验不通过返回的提示信息
   */
  String message() default "不是一个手机号码格式";
  /**
   * Constraint要求的属性,用于分组校验和扩展,留空就好
   */
  Class<?>[] groups() default {};
  Class<? extends Payload>[] payload() default {};
}

相关元注解知识回顾:

注解的定义很像接口的定义,事实上与其他java接口一样,注解也会被编译成class文件,定义注解时需要一些元注解。

1.@Target详细介绍

@Target注解用于指定注解的使用目标

  • ElementType.TYPE: 接口、类、枚举、注解
  • ElementType.FIELD: 字段、枚举的常量
  • ElementType.METHOD: 方法
  • ElementType.PARAMETER: 方法参数
  • ElementType.CONSTRUCTOR: 构造函数
  • ElementType.LOCAL_VARIABLE: 局部变量
  • ElementType.ANNOTATION_TYPE: 注解
  • ElementType.PACKAGE: 包
2.@Relation详细介绍

@Relation用于指定注解的保留策略,即注解信息在class文件中的保留时间

  • RetentionPolicy.SOURCE: 注解只保留在源文件中,不会被编译到class文件中。
  • RetentionPolicy.CLASS: 注解保留在class文件中,但JVM在运行时不会保留这些信息。
  • RetentionPolicy.RUNTIME: 注解不仅保留在class文件中,而且在JVM运行时也可以通过反射来获取这些注解的信息。
3.@Documented介绍
  • 这个注解表示将此注解包含在javadoc中,使得注解的信息可以在生成的文档中被看到。
4.@Inherited介绍
  • 允许子类继承父类中的注解,千万不要误解是注解的嵌套,是Class类继承的时候,是否拥有父类的注解
5.@Constraint 注解介绍
  • @Constraint注解是Java Bean Validation框架中的一个注解,用于自定义约束注解,即自定义校验规则。
  • 通过在自定义注解上添加@Constraint注解,可以将该注解标记为一个自定义约束注解。同时,需要指定一个实现了ConstraintValidator接口的验证器类,用于验证该注解所标记的字段或参数是否符合自定义的校验规则。

@Constraint注解有以下属性:

  • validatedBy:用于指定实现了ConstraintValidator接口的验证器类。该属性的值是一个Class对象数组,可以指定多个验证器类。
  • message:用于指定当校验失败时,所返回的错误信息。可以使用占位符{},在校验器中使用具体的参数替换。
  • groups:用于指定分组,即根据不同的分组应用不同的校验规则。 payload:用于指定元数据,即可以通过该属性传递一些额外的验证信息。

使用@Constraint注解可以通过自定义注解的方式,为字段或参数添加自定义的校验规则,并实现校验逻辑。这样在进行参数校验时,可以方便地通过注解的方式来调用自定义的校验规则。

第二步:实现校验器

public class MobileValidator implements ConstraintValidator<Mobile, CharSequence> {

  private boolean required = false;

  private final Pattern pattern = Pattern.compile("^1[34578][0-9]{9}$"); // 验证手机号

  /**
   * 在验证开始前调用注解里的方法,从而获取到一些注解里的参数,required 默认为true也就是开启手机号校验
   * @param constraintAnnotation
   */
  @Override
  public void initialize(Mobile constraintAnnotation) {
    this.required = constraintAnnotation.required();
  }

  /**
   * 真正执行的校验方法 true? 开启校验 : 直接不校验=>通过
   * @param value object to validate
   * @param context context in which the constraint is evaluated
   * @return
   */
  @Override
  public boolean isValid(CharSequence value, ConstraintValidatorContext context) {
      return this.required ? isMobile(value) : Boolean.TRUE;
  }

  /**
   * 正则校验手机号
   * @param str
   * @return
   */
  private boolean isMobile(final CharSequence str) {
    return pattern.matcher(str).matches();
  }
}

第三步 接下来就可以开始愉快的测试啦

1.创建Controller控制器层接收请求

required 的布尔值属性指定要不要做校验,true ? 需要 : 不需要

/**
 * 测试自定义注解
 * @param phone
 * @return
 */
@GetMapping("/test-customValidation")
public CommonResult<String> testCustomValidation(@Mobile(required= true) String phone) {
    return CommonResult.success(phone);
}

2.使用ApiPost测试请求

  • required = true 需要校验的情况下测试:
    输入错误的手机号->失败
    提示testCustomValidation方法的phone参数异常
    输入正确的手机号->成功
    在这里插入图片描述

  • required = false 不需要校验的情况下测试:
    输入错误的手机号,成功->因为咱们设置了注解值对参数不校验
    在这里插入图片描述

好啦,今天的分享就到这,相信大家对类似场景都可以实现自己的校验器啦,小小拿捏。

内心os:把平凡的代码写完再优化好,像写诗一样,真的特别舒心。

今天在协助筛选求职者简历,同事发现有求职者有写csdn的好习惯,我以前一直是归纳总结到了github上孤芳自赏,针对国内环境感觉还是写csdn上好点,今天是第一天,后续会开启持续分享哒_

怀念以前:记得刚毕业实现那会儿我组长叫我去学下vue,接触过半年多的前端知识,css/js/vue组件、路由、vuex、axios等等 以前拿着代码一行一个注释,学的老认真了哈哈哈,那时候也真是无忧无虑好欢乐。
在这里插入图片描述
面对当下:下班健身完真的能去班味,轻松太多了,睡觉咯,明天又是新的打工day…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值