Validator 使用笔记

1 Validator作用

提高 spring mvc http 参数校验开发效率,有效避免如下复杂代码使用:
if(StringUtils.isBlank(name)){
   return new ReponseEntity(HttpStatus.BAD_REQUEST);
}

2 配置校验器,发现错误立即返回,可以减少无效校验

@Configuration
public class ValidationConfig {

    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor() {
        MethodValidationPostProcessor methodValidationPostProcessor =  new MethodValidationPostProcessor();
        methodValidationPostProcessor.setValidator(validator());
        return methodValidationPostProcessor;
    }

    @Bean
    public static Validator validator() {
        return Validation
                .byProvider(HibernateValidator.class)
                .configure()
                //快速返回模式,有一个验证失败立即返回错误信息
                .failFast(true)
                .buildValidatorFactory()
                .getValidator();
    }
}

3 配置全局controller异常拦截器,参数检查异常以比较统一的形式返回

@ControllerAdvice
public class ValidatorExceptionHandler {

    /**
     * 在实体中使用注解校验异常拦截
     * @param exception
     * @return
     */
    @ExceptionHandler
    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Object handle(MethodArgumentNotValidException exception) {
        return exception.getBindingResult().getAllErrors();
    }


    /**
     * controller接口方法中校验异常拦截
     * @param exception
     * @return
     */
    @ExceptionHandler
    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Object handle(ConstraintViolationException exception) {
        return exception.getConstraintViolations().stream().map(ConstraintViolation::getMessage)
                .collect(Collectors.toList());
    }
}

4 单个参数验证
@GetMapping("/list")
public ResponseEntity list(@RequestParam("name") @Validated @NotBlank String name){

}

5 分组验证

5.1创建空的interface接口

 

public interface RoleUpdateGroup{
}

publica interface RoleAddGroup{
}

public class RoleDTO {

    @NotNull(groups = {RoleUpdateGroup.class})
    private Long id;

    @NotNull(groups = {RoleUpdateGroup.class, RoleAddGroup.class})
    @Length(groups = {RoleUpdateGroup.class, RoleAddGroup.class} , min = 3, max = 10, message = "角色名称在3-10位之间")
    private String roleName;

    @NotNull
    private Integer age【注】age没有指定自定义分组,自动属于Default.class默认组
}

5.2 分组校验有两种互斥的

1)
@GroupSequence + @Validated  【注】@Validated本身groups不起效

@GroupSequence({RoleAddGroup.class, RoleUpdateGroup.class, RoleDTO.class})
class RoleDTO {
}

@PostMapping(value = "/add")
public ResponseEntity add(@Validated @RequestBody RoleDTO roleDTO){
}
按照顺序 RoleAddGroup.class -> RoleUpdateGroup.class -> Default.class

2) 
@Validated(Group.class) 【注】仅使用@Validated

@PostMapping(value = "/add")
public ResponseEntity add(@Validated(RoleAddGroup.class) @RequestBody RoleDTO roleDTO){
}

仅仅检查RoleAddGroup.class组的属性,如果检查时不指定组group,则只检查默认组Default.class组的age属性

【注】当RoleDTO 指定@GroupSequence后,会覆盖@Validated(RoleAddGroup.class)的分组检查效果

6 自定义验证
(1)自定义脚本

// 必须要关联自定义的validator处理器MyValidator
@Constraint(validatedBy = MyValidator.class)
@Target( { java.lang.annotation.ElementType.METHOD, java.lang.annotation.ElementType.FIELD })
@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@Documented
public @interface MyValidate {

    //提示信息,可以写死,可以填写国际化的key
    String message() default "{Cannot.contain.Spaces}";

    int length() default 5;

    //下面这两个属性必须添加
    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

(2)自定义校验处理器

// 关联自定义的注解
public class MyValidator implements ConstraintValidator<MyValidate, String> {

    private int length;

    // 初始化,MyValidator实例化时候执行调用一次
    @Override
    public void initialize(MyValidate myValidate) {
        length = myValidate.length();
    }

    // s 就是你请求绑定到参数的值
    @Override
    public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
        return false;
    }
}

7 @Validated Vs. @Valid

@Validated 支持分组group,但不能支持验证POJO的属性
@Valid不支持分组,但支持POJO属性验证,进一步完成嵌套对象的验证,如:
两者都可以放在方法的参数、类上

fun(@Valid UserDTO user) 正确
fun(@Validated(grroups={Grp1.class,Grp2.class}) UserDTO user) 正确

class UserDTO {
  @Valid  
  Address address
}  

正确

@Valid是标准的JSR-303规范,@Validated是JSR-303规范变种,并增加一些扩展功能

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值