统一参数校验validator 实战

一、单个基本类型的包装类进行校验

  1. @Validated 声明要检查的参数
    这里我们在控制器层进行注解声明

    @PostMapping("/save/valid")
    public RspDTO save(@RequestBody @Validated UserDTO userDTO) {
    userService.save(userDTO);
    return RspDTO.success();
    }

  2. 对参数的字段进行注解标注

/**

  • @Description: 用户传输对象
    */
    @Data
    public class UserDTO implements Serializable {

    private static final long serialVersionUID = 1L;

    /*** 用户ID*/
    @NotNull(message = "用户id不能为空")
    private Long userId;

    /** 用户名/
    @NotBlank(message = "用户名不能为空")
    @Length(max = 20, message = "用户名不能超过20个字符")
    @Pattern(regexp = "^[\u4E00-\u9FA5A-Za-z0-9\
    ]*$", message = "用户昵称限制:最多20字符,包含文字、字母和数字")
    private String username;

    /** 手机号*/
    @NotBlank(message = "手机号不能为空")
    @Pattern(regexp = "^[1][3,4,5,6,7,8,9][0-9]{9}$", message = "手机号格式有误")
    private String mobile;

    /*性别/
    private String sex;

    /** 邮箱*/
    @NotBlank(message = "联系邮箱不能为空")
    @Email(message = "邮箱格式不对")
    private String email;

    /** 密码*/
    private String password;

    /*** 创建时间 */
    @Future(message = "时间必须是将来时间")
    private Date createTime;

}

  1. 在全局校验中增加校验异常
    MethodArgumentNotValidException是springBoot中进行绑定参数校验时的异常,需要在springBoot中处理,其他需要
    处理ConstraintViolationException异常进行处理.

为了优雅一点,我们将参数异常,业务异常,统一做了一个全局异常,将控制层的异常包装到我们自定义的异常中
为了优雅一点,我们还做了一个统一的结构体,将请求的code,和msg,data一起统一封装到结构体中,增加了代码的复用性

/**

  • @Description: 全局异常处理器
    */
    @RestControllerAdvice
    public class GlobalExceptionHandler {

    private Logger logger = LoggerFactory.getLogger(getClass());

    private static int DUPLICATE_KEY_CODE = 1001;
    private static int PARAM_FAIL_CODE = 1002;
    private static int VALIDATION_CODE = 1003;

    /**

    • 处理自定义异常
      */
      @ExceptionHandler(BizException.class)
      public RspDTO handleRRException(BizException e) {
      logger.error(e.getMessage(), e);
      return new RspDTO(e.getCode(), e.getMessage());
      }

    /**

    • 方法参数校验
      */
      @ExceptionHandler(MethodArgumentNotValidException.class)
      public RspDTO handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
      logger.error(e.getMessage(), e);
      return new RspDTO(PARAM_FAIL_CODE, e.getBindingResult().getFieldError().getDefaultMessage());
      }

    /**

    • ValidationException
      */
      @ExceptionHandler(ValidationException.class)
      public RspDTO handleValidationException(ValidationException e) {
      logger.error(e.getMessage(), e);
      return new RspDTO(VALIDATION_CODE, e.getCause().getMessage());
      }

    /**

    • ConstraintViolationException
      */
      @ExceptionHandler(ConstraintViolationException.class)
      public RspDTO handleConstraintViolationException(ConstraintViolationException e) {
      logger.error(e.getMessage(), e);
      return new RspDTO(PARAM_FAIL_CODE, e.getMessage());
      }

    @ExceptionHandler(NoHandlerFoundException.class)
    public RspDTO handlerNoFoundException(Exception e) {
    logger.error(e.getMessage(), e);
    return new RspDTO(404, "路径不存在,请检查路径是否正确");
    }

    @ExceptionHandler(DuplicateKeyException.class)
    public RspDTO handleDuplicateKeyException(DuplicateKeyException e) {
    logger.error(e.getMessage(), e);
    return new RspDTO(DUPLICATE_KEY_CODE, "数据重复,请检查后提交");
    }

    @ExceptionHandler(Exception.class)
    public RspDTO handleException(Exception e) {
    logger.error(e.getMessage(), e);
    return new RspDTO(500, "系统繁忙,请稍后再试");
    }
    }

二、自定义对象的校验
自定义对象可能用在不同的场景,校验规则不一样,比如新增申请单的时候要求id可以为null,但是修改申请单的时候就必须要求修改的申请单的id不能为空,但是二者又是使用的同一个业务对象,这时候我们就是需要使用分组校验了。具体步骤如下:
定义校验分组
首先我们要定义为了分组校验所使用的分组,其实就是一些空的接口。


  • 然后在业务对象上定义校验规则和校验规则所生效的分组,如果不定义分组,则默认所有分组都生效。


    • 最后在需要校验的方法上去加上校验所使用的分组,然后参数校验规则就会生效了。


    • 为了给前端一个友好的提示,需要对参数校验不满足抛出的异常进行统一的处理,使不满足的规则具有易读性,大家可以看到我针对参数校验抛出的异常定义了二个异常处理器,因为不同的参数校验框架,抛出的异常不一样,而且抛出异常里面封装的对象格式不一样。因为我使用了多个参数校验框架,原生的validate-api抛出的是ConstraintViolationException,但是其支持的校验的规则有限,比如针对字符串只支持notNull,但是我们其实想的是NotEmpty,就是不仅仅是null,还不能是空字符串。这之后就要使用spring或者hibernate扩展的校验,这时候每个框架校验抛出的异常就不一样,需要做不同的处理。


      统一参数校验validator 注解
      https://www.jianshu.com/p/db2a735d9d2b

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,372评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,368评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,415评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,157评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,171评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,125评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,028评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,887评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,310评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,533评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,690评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,411评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,004评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,812评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,693评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,577评论 2 353