背景
项目中我们会经常使用JSR进行参数校验,配合SpringBoot的全局异常拦截,不要太方便,虽然JSR已经提供了需要很常用的注解,我们可以直接使用,但是需求是千变万化的,总会出现默认的注解无法满足的情况,这个时候我们就可以使用自定义Validation注解来进行实现,完成参数校验。
创建注解@inteface类,代码如下:
package com.test.common.validation;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* 校验一个字符串是否包含在指定字符数组内
* @author test
*/
@Documented
@Constraint(validatedBy = StringContainsValidator.class)
@Target({ FIELD })
@Retention(RUNTIME)
public @interface StringContains {
String message() default "字符串不符合规则";
String[] limitValues() default {};
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
类中相关注解解释:
名称 | 解释 |
---|---|
@Documented | 文档注释 |
@Constraint | 指定改注解的具体校验方式有那个类实现,一定要指定,否则会出现HV000030: No validator could be found错误 |
@Target | 注解可使用的位置,常用的有Type:可使用在类,接口,枚举类上,FIELD:可使用在类的字段属性上,METHOD:可使用在方法上,PARAMETER:可使用在参数上 |
@Retention | 注解生效范围,SOURCE:源码中,编译后丢失,CLASS:编译后保留,但JVM运行时丢失,RUNTIME:JVM运行中保留 |
创建注解的具体校验方式的实现类,代码如下:
package com.test.common.validation;
import cn.hutool.core.util.StrUtil;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @author test
*/
public class StringContainsValidator implements ConstraintValidator<StringContains, String> {
private Set<String> limitValues;
@Override
public void initialize (StringContains constraintAnnotation) {
limitValues = Arrays.stream(constraintAnnotation.limitValues()).map(String::toUpperCase).collect(Collectors.toSet());
}
@Override
public boolean isValid (String value, ConstraintValidatorContext context) {
if (StrUtil.isBlank(value)) {
return true;
}
return limitValues.contains(value.toUpperCase());
}
}
在类中使用,限定该字符串必须是指定的内容,为空和null不进行校验
public class Test{
@StringContains(limitValues = {"DESC", "ASC"})
private String direction;
}