在对外暴露接口中,我们通常会对入参进行验证,比如一些字符串非空判断、数字最小值最大值这些基础的判断在java验证规范中已经提供了,然而这些只是常规的验证,我们可以通过自定义注解以及验证器来进行我们自己业务上的一些验证,这样可以避免在业务逻辑中添加过多的验证,降低代码的可读性。
仅需引入验证包即可,当然,如果使用的springboot,可以直接管理依赖,不用指定版本
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
这里添加一个银行卡验证的注解,其实核心注解就是@Constraint,这个注解要求我们的注解中必须有message()groups()以及payload()这三个方法
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
/**
* 银行卡号校验注解
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
// 这里指定验证器
@Constraint(validatedBy = {BankCardValidator.class})
@Target({ElementType.FIELD,ElementType.ANNOTATION_TYPE,ElementType.PARAMETER})
public @interface BankCardValidity {
/**
* 提示信息
* @return String
*/
String message() default "";
/**
* 是否验证
* @return boolean
*/
boolean required() default true;
/**
* groups
* @return []
*/
Class<?>[] groups() default {};
/**
* payload
* @return []
*/
Class<? extends Payload>[] payload() default {};
}
验证器的核心是实现ConstraintValidator这个类,第一个参数是指定注解,第二个则是指定的入参
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 银行卡号校验器
*/
public class BankCardValidator implements ConstraintValidator<BankCardValidity,String> {
/**
* 是否强制验证
*/
private boolean required = false;
/**
* 银行卡号正则校验,这里就是一个正则验证
*/
private static Pattern patternForBankCardNo = Pattern.compile("^([1-9]{1})(\\d{15}|\\d{18})$");
/**
* 这里就是验证逻辑,返回true验证通过,返回false验证不通过
*/
@Override
public boolean isValid(String bankCardNo, ConstraintValidatorContext context) {
if (required) {
return isBankCardNo(bankCardNo);
} else {
if (StrUtil.isBlank(bankCardNo)) {
return false;
}
return isBankCardNo(bankCardNo);
}
}
@Override
public void initialize(BankCardValidity validity) {
required = validity.required();
}
/**
* 验证是否为银行卡号
* @param bankCardNo 输入内容
* @return boolean
*/
private static boolean isBankCardNo(String bankCardNo) {
// 使用的hutool工具包,也可以使用其它工具包
if (StrUtil.isBlank(bankCardNo)) {
return false;
}
Matcher matcherForBankCardNo = patternForBankCardNo.matcher(bankCardNo);
return matcherForBankCardNo.matches() ;
}
}
至此编码就完成了,我们可以在注解中添加新的方法,在initialize()方法中使用,或者取值等操作,这都是根据业务场景来进行的。
当然,在入参校检中,我们肯定也需要把@Valid等注解加上,验证器才会去验证。