@Validate注解使用原理详解

1. 基本使用

平时写rest接口的时候大家肯定用过@Validated注解,对rest的提交的数据进行校验

类似如下的写法,post接口对body里面的json字符串进行校验。

定义一个接口,

@Controller
public class HelloController {

    @Autowired
    private PriceCityDao priceCityDao;
    @Autowired
    private OrderItemDao orderItemDao;

    @ResponseBody
    @PostMapping(value = "/hello")
    public MyRequesst hello(@Validated @RequestBody MyRequesst po) {
        return po;
    }
}
@Data
@Accessors(chain = true)
public class MyRequesst {
    /**
     * 城市名称
     */
   @NotBlank
    private String cityName;
    @NotNull
    @Max(100)
    private String cityId;
}

在请求发送之后,会去校验json字符串的字段,如果cityName,或者cityid不符合注解定义的规则,就会直接报错。请求在dispatchServlet阶段就会被拦截掉,对应的controller方法都进不来。使用这种方式校验远比自己写个方法在controller中校验参数方便优雅多了

以上介绍的是@Validate注解的基本用法,大家知道怎么用了之后,就可以去使用不同的注解有什么作用了。

2. 自定义注解使用

自定义注解使用,可以仿照现有的直接仿写自己的注解。注解要配置自己的注解验证类,这样在验证的时候才会找到使用什么validator验证。上述类,加一个自定义的注解,

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {MyValidateAnnotationValidator.class})
public @interface MyValidateAnnotation {
    String message() default "不符合固定枚举类型";

    Class<?>[] groups() default { };

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

    String min();

    String max();
}
@Slf4j
public class MyValidateAnnotationValidator implements ConstraintValidator<MyValidateAnnotation, String> {
    private Integer min;
    private Integer max;

    public MyValidateAnnotationValidator() {
    }

    @Override
    public void initialize(MyValidateAnnotation parameters) {
        this.min = Integer.parseInt(parameters.min());
        this.max = Integer.parseInt(parameters.max());
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (StringUtils.isEmpty(value)) {
            return true;
        }
        int integer;
        try {
            integer = Integer.parseInt(value);
        }
        catch (NumberFormatException var4) {
            return false;
        }
        return integer >= min && integer <= max;
    }
}

使用的时候就这样,加上@MyValidateAnnotation(min=”1″,max = “2”)

@Data
@Accessors(chain = true)
public class MyRequesst {
    @NotBlank
    /**
     * 城市名称
     */
    private String cityName;
    @NotNull
    @Max(100)
    @MyValidateAnnotation(min="1",max = "2")
    private String cityId;
}

上述介绍的是自定义注解,需要注意的点是需要给注解配置对应的validator.class。下面介绍的是注解找到对应的validator的过程

3. 注解原理

刚才大家应该都看到了,自定义注解需要配置验证器的class,但是内置的注解并不需要例如@Max,那么他对应的验证器是什么时候注册的呢?

@Validate注解使用原理详解

编辑可以看到max注解对应了许多class,在使用的过程中更具field的参数类型去匹配具体的class。如下所示,1是更具注解找到注册的class的集合,2是更具参数类型确定的选择哪一个

@Validate注解使用原理详解

这个是内置注解的匹配过程,自定义的注解如下,通过自定义注解的validateby拿到对应的class

@Validate注解使用原理详解

5 结论

经过上述过程,大家基本上对@validate的过程熟悉了。在dispatchServlet的过程中有一个验证的环节。验证过程一开始,肯定是更具要验证的class此处就是myRequest.class拿到字段上上面的注解。解析注解发现有@Max注解修饰,然后匹配到具体的validator.class, 通过class实例化对象去做具体的字段验证。大家可以根据上图的一些关键类,debug看下,辅助学习

© 版权声明

相关文章

暂无评论

none
暂无评论...