前言
在我们工作业务当中,参数校验是一项必不可少的步骤,虽然 javax.validation
包下面自带了很多校验注解,但是很多情况下我们根据业务会出现自己特有的校验方式,这时候就需要我们使用注解来实现自定义校验的方式。
一、遇到的问题
我现在想要校验某个入参的一个字段的取值范围是否正确,他的取值范围可能记录在数据库,也可能记录在redis,也可能是列举尽的固定几个,总之需要根据不同情况判断.
二、操作
1.自定义一个注解,设置好作用域和内置属性等等
代码如下(示例):
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = {DictValidator.class}) // 校验规则写在DictValidator类
public @interface DictValid {
String message() default "";
// 分组校验
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
/**
* mysql ->写一个能从mysql分辨找出的标识即可
* redis -> key
* 固定列举 -> 逗号隔开,如(1,2,3)
*
* @return
*/
String target() default "";
/**
* 根据type判断是从什么地方取值校验合法性,1:mysql,2:redis,3:固定列举
*
* @return
*/
String type() default "1";
}
2.编写校验规则DictValidator类
代码如下(示例):
public class DictValidator implements ConstraintValidator<DictValid, Object> {
private DictValid annotation;
@Override
public void initialize(DictValid constraintAnnotation) {
annotation = constraintAnnotation;
}
@Override
public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) {
boolean result = false;
String target = annotation.target();
String type = annotation.type();
if (o != null && !"".equals(o.toString().trim())) {
String value = o.toString();
if ("1".equals(type)) {
result = checkTypeByDB(target, value);
}
if ("2".equals(type)) {
result = checkTypeByRedis(target, value);
}
if ("3".equals(type)) {
result = checkTypeByEnumerate(target, value);
}
}
return result;
}
private boolean checkTypeByDB(String target, String value) {
// 从数据库取值作比
}
private boolean checkTypeByRedis(String target, String value) {
// target为key,直接从redis取值作比
}
private boolean checkTypeByEnumerate(String target, String value) {
List<String> dictList = Arrays.asList(target.split(","));
return dictList.contains(value);
}
}
3.使用
代码如下(示例):
// 实体类字段的写法
@DictValid(target = RedisConstants.BOOK_TYPE, message = "bookType is error", type = "2")
private String bookType;
// 在入参加上@Valid即可
public Response<Object> save(@Valid @RequestBody BookVo bookVo ){
}
总结
本文讲述了自定义参数校验的简单使用,重点在于注解的实现类(本文为ConstraintValidator
类)的写法,他得实现泛型接口ConstraintValidator<A extends Annotation, T>
,第一个参数为我们的自定义的注解,第二个参数即为入参的类型。此接口的核心方法为boolean isValid(T var1, ConstraintValidatorContext var2)
,我们实现此接口主要就是在此方法写写我们的校验规则。