自动化测试我爱编程

使用 Bean Validation 解决业务中参数校验

2018-04-03  本文已影响82人  crrrrw

痛点及现状

代码中常常见到如下代码:

if (Objects.equal(0L ,repertory)){
    return ApiResultMap.errorResult(-1 ,"操作数量不可为0") ;
}

这种参数校验写在模块里有如下缺点:

抛出问题:那么有没有一种方式可以简化代码呢?

JSR 303 - Bean Validation

Bean Validation是一个通过配置注解来验证参数的框架,它包含两部分Bean Validation API和Hibernate Validator。

QUICK START

  1. 引入pom
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.3.1.Final</version>
</dependency>
  1. dto入参对象属性加入注解
@Data
public class ValidDemo {
    @Size(min = 3, max = 12, message = "用户名必须的长度必须是3到12个字母之间")
    @Pattern(regexp = "^[a-z]+$", message = "用户名必须是a-z小字母")
    private String name;

    @Size(min = 6, max = 6, message = "密码必须是6位数字")
    @Pattern(regexp = "^[0-9]+$", message = "密码必须是6位数字")
    private String password;

    @Range(min = 1, max = 9, message = "范围只能1到9")
    private Integer range;

    @NotNull(message = "邮箱不能为Null")
    @Email(regexp = "(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\])",
            message = "邮箱格式有误")
    private String email;

}

  1. controller方法入参加入校验(@Valid)
@GetMapping("/validdemo")
public Map<String,Object> demo(@Valid ValidDemo validDemo){
    return ApiResultMap.successResult(validDemo);
}
  1. 精简出参,加入全局异常处理
@ExceptionHandler(value = { BindException.class })
public Map<String, Object> validationException(BindException ex) {
    log.error(ex.getBindingResult().getFieldError().getDefaultMessage());
    return ApiResultMap.errorResult(ex.getBindingResult().getFieldError().getDefaultMessage());
}
  1. 测试结果:
    curl http://localhost:8080/validdemo?email=xxxxx
{
    "message": {
        "code": -1,
        "message": "邮箱格式有误"
    }
}

另一种方式,使用 spring 的 @Validated 注解:

  1. 配置 MethodValidationPostProcessor
    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor() {
        return new MethodValidationPostProcessor();
    }

  1. 使用@Validated注解:
@Validated
@RestController
public class DemoController {}
  1. 方法上加上校验
@GetMapping("/validdemo3")
public Map<String,Object> demo3(@NotNull String str, @NotNull @Range(min = 0, max = 10) Integer a){
    return ApiResultMap.successResult(str + a);
}
  1. 测试 curl http://localhost:8080/validdemo?str=1&a=15
{
    "message": {
        "code": 202,
        "message": "需要在0和10之间"
    }
}

应用场景

java程序员张三和ios程序员李四开发某一需求,明天就要demo了,今天得抓紧联调。
李四:三哥,地址发下,调试绑卡。
张三启动服务...
李四:三哥,帮忙看下,这个接口报错 -1,看下上面错误呗。
张三打开控制台,看了一下日志与排查,数据库报错,身份证字段没传导致插入身份证为空报错。
张三:李四你身份证没传。...张三一边埋怨着一边加入一行if else,同时在思考别的接口是不是也有这种情况,也给加上if else.
没过一会儿,李四:三哥,帮我看下有报错-1了。
张三又去查看,同样的,这次是银行卡号没传。张三重复着以上操作可没过一会儿李四又....
就这样一天过去,伴随着晚霞下班的张三,心情却没那么高兴...

抛出问题:是什么导致张三忙碌一天却觉得碌碌无为?是道德的沦丧还是人性的丧失?

如果张三整合Bean Validation的话,可能就没有那么不愉快了。他只需要一次在入参model里加入校验,之后在控制器的通过轻松的 @Valid 注解,就可以省去李四重复的提问,也省去的检查其他接口是否也需要添加代码校验,代码又可以少些几行了,何乐而不为。

常用注解

Bean Validation 中内置的 constraint:

Hibernate Validator 附加的 constraint:

优势

总结

推荐使用 Bean Validation 的方式解决业务中参数校验;
这里只给出了一些基本的参数校验constraint,在实际业务中可根据业务情形自定义业务constraint。

上一篇 下一篇

猜你喜欢

热点阅读