SpringBoot解决方案之 参数校验
在以SpringBoot开发Restful接口时, 对于接口的查询参数后台也是要进行校验的,同时还需要给出校验的返回信息放到上文我们统一封装的结构中。那么如何优雅的进行参数的统一校验呢?
什么是不优雅的参数校验 后端对前端传过来的参数也是需要进行校验的,如果在 controller 中直接校验需要用大量的 if else 做判断
以添加用户的接口为例,需要对前端传过来的参数进行校验, 如下的校验就是不优雅的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @RestController @RequestMapping("/user") public class UserController { @PostMapping("add") public R add (User user) { if (user.getName()==null ) { return R.error("user name should not be empty" ); } else if (user.getName().length()<5 || user.getName().length()>50 ){ return R.error("user name length should between 5-50" ); } if (user.getAge()< 1 || user.getAge()> 150 ) { return R.error("invalid age" ); } return R.ok(); } }
针对这个普遍的问题,Java开发者在Java API规范 (JSR303) 定义了Bean校验的标准validation-api ,但没有提供实现。
hibernate validation 是对这个规范的实现 ,并增加了校验注解如@Email、@Length等。
Spring Validation 是对 hibernate validation 的二次封装 ,用于支持spring mvc参数自动校验。
接下来,我们以springboot项目为例,介绍Spring Validation的使用
实现案例
本例子采用 spring validation 对参数绑定进行校验,主要给你提供参数校验的思路。
POM
添加pom依赖 1 2 3 4 5 6 <dependency > <groupId > org.springframework.boot</groupId > <artifactId > spring-boot-starter-validation</artifactId > </dependency >
请求参数封装 单一职责,所以将查询用户的参数封装到 UserParam 中, 而不是 User(数据库实体)本身。
对每个参数字段添加 validation 注解约束和 message。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 @Data @Builder @ApiModel(value = "User", subTypes = {AddressParam.class}) public class UserParam implements Serializable { private static final long serialVersionUID = 1L ; @NotEmpty(message = "could not be empty") private String userId; @NotEmpty(message = "could not be empty") @Email(message = "invalid email") private String email; @NotEmpty(message = "could not be empty") @Pattern(regexp = "^(\\d{6})(\\d{4})(\\d{2})(\\d{2})(\\d{3})([0-9]|X)$", message = "invalid ID") private String cardNo; @NotEmpty(message = "could not be empty") @Length(min = 1, max = 10, message = "nick name should be 1-10") private String nickName; @NotEmpty(message = "could not be empty") @Range(min = 0, max = 1, message = "sex should be 0-1") private int sex; @Max(value = 100, message = "Please input valid age") private int age; @Valid private AddressParam address; }
Controller中获取参数绑定结果 使用 @Valid 或者 @Validated 注解,参数校验的值放在 BindingResult 中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 @Slf4j @Api(value = "User Interfaces", tags = "User Interfaces") @RestController @RequestMapping("/user") public class UserController { @ApiOperation("Add User") @ApiImplicitParam(name = "userParam", type = "body", dataTypeClass = UserParam.class, required = true) @PostMapping("add") public ResponseEntity<String> add (@Valid @RequestBody UserParam userParam, BindingResult bindingResult) { if (bindingResult.hasErrors()) { List<ObjectError> errors = bindingResult.getAllErrors(); errors.forEach(p -> { FieldError fieldError = (FieldError) p; log.error("Invalid Parameter : object - {},field - {},errorMessage - {}" , fieldError.getObjectName(), fieldError.getField(), fieldError.getDefaultMessage()); }); return R.error.message("invalid parameter" ); } return R.ok("success" ); } }