简介
后端常常会需要对参数进行校验,这里提供两种处理校验逻辑的方式。一种是使用Hibernate Validator来处理,另一种是使用全局异常来处理。对于前者,还可以使用自定义注解进行参数校验。
Hibernate Validator
Hibernate Validator是 SpringBoot 内置的校验框架,只要集成了 SpringBoot 就自动集成了它,我们可以通过在对象上面使用它提供的注解来完成参数校验。
常用注解
- @Null:被注释的属性必须为null;
- @NotNull:被注释的属性不能为null;
- @AssertTrue:被注释的属性必须为true;
- @AssertFalse:被注释的属性必须为false;
- @Min:被注释的属性必须大于等于其value值;
- @Max:被注释的属性必须小于等于其value值;
- @Size:被注释的属性必须在其min和max值之间;
- @Pattern:被注释的属性必须符合其regexp所定义的正则表达式;
- @NotBlank:被注释的字符串不能为空字符串;
- @NotEmpty:被注释的属性不能为空;
- @Email:被注释的属性必须符合邮箱格式。
使用方式
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class User { @ApiModelProperty(value = "用户名", required = true) @NotEmpty(message = "用户名不为空") private String username; @ApiModelProperty(value = "密码", required = true) @NotEmpty(message = "密码不为空") private String password; @ApiModelProperty(value = "邮箱", required = true) @Email(message = "邮箱格式不合法") private String email; @ApiModelProperty(value = "是否进行显示") @FlagValidator(value = {"0","1"}, message = "显示状态不正确") private Integer showStatus; }
|
- 添加@Validated注解,并注入一个BindingResult参数
1 2 3 4 5 6 7 8 9
| @Controller @RequestMapping("/test") publicclass TestController { @RequestMapping(value = "/t0", method = RequestMethod.POST) @ResponseBody public T create(@Validated @RequestBody User user, BindingResult result) { ... } }
|
- 然后在整个Controller层创建一个切面,在其环绕通知中获取到注入的BindingResult对象,通过hasErrors方法判断校验是否通过,如果有错误信息直接返回错误信息,验证通过则放行;
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
|
@Aspect
@Component
@Order(2) public class BindingResultAspect { @Pointcut("execution(public * cn.xlh.controller.*.*(..))") public void BindingResult() { }
@Around("BindingResult()") public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable { Object[] args = joinPoint.getArgs(); for (Object arg : args) { if (arg instanceof BindingResult) { ... } } return joinPoint.proceed(); } }
|
自定义注解
有时候框架提供的校验注解并不能满足我们的需要,此时我们就需要自定义校验注解。如User类的参数showStatus,我们希望它只能是0或者1,不能是其他数字,此时可以使用自定义注解来实现该功能。
- 首先自定义一个校验注解类FlagValidator
1 2 3 4 5 6 7 8 9
| @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD,ElementType.PARAMETER}) @Constraint(validatedBy = FlagValidatorClass.class) public @interface FlagValidator { String[] value() default {}; String message() default "flag is not found"; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
|
- 然后创建FlagValidatorClass作为校验逻辑的具体实现类,实现ConstraintValidator接口,这里需要指定两个泛型参数,第一个需要指定为你自定义的校验注解类,第二个指定为你要校验属性的类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public class FlagValidatorClass implements ConstraintValidator<FlagValidator,Integer> { private String[] values; @Override public void initialize(FlagValidator flagValidator) { this.values = flagValidator.value(); }
@Override public boolean isValid(Integer value, ConstraintValidatorContext constraintValidatorContext) { boolean isValid = false; if(value==null){ return true; } for(int i=0;i<values.length;i++){ if(values[i].equals(String.valueOf(value))){ isValid = true; break; } } return isValid; } }
|
1 2 3 4 5
| public class User { @ApiModelProperty(value = "是否进行显示") @FlagValidator(value = {"0","1"}, message = "显示状态不正确") private Integer showStatus; }
|