1、创建对于参数校验的自定义注解
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
/**
* 数据参数合法性注解
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = DateValidator.class)
public @interface DataCheck {
/*** 是否必填*/
boolean require() default false;
/*** 字段的类别 从枚举类ValidTypeEnum中选取*/
String type() default "";
/*** 日期格式*/
String pattern() default "yyyy-MM-dd";
/*** 如果校验不通过,返回的报错信息*/
String message() default "";
// 进行接口有效性校验必加的属性
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
2、实现ConstraintValidator接口对自定义注解进行校验
1)、实现接口的第一个方法initialize() 实例化实现类,解析获取注解的信息,初始化实现类(注意:该实现类相同的注解信息只会有一个实例化对象,第二次再调用的时候并不会再初始化)
2)、实现接口的第二个方法
import com.guochu.common.pojo.enumation.ValidTypeEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @ClassName DateValidator
* @Description 对注解进行字段有效性校验
* // todo 做成统一的校验接口,
* 参考博客:https://segmentfault.com/a/1190000021422157?utm_source=tag-newest
* @Author hql
* @Date 2020/6/1 17:52
* @Version 1.0
*/
@Component
public class DateValidator implements ConstraintValidator<DataCheck, String> {
private final static Logger logger = LoggerFactory.getLogger(DateValidator.class);
private volatile boolean required = false;
private volatile String type = "";
private volatile String pattern = "";
private volatile String message = "";
/**
* 初始化时获取注解信息
*
* @param constraintAnnotation 注解信息
*/
@Override
public void initialize(DataCheck constraintAnnotation) {
required = constraintAnnotation.require();
type = constraintAnnotation.type();
pattern = constraintAnnotation.pattern();
//message = constraintAnnotation.message();
}
/**
* 实现接口验证值的有效性
*
* @param date 字段数据值
*
* @param constraintValidatorContext
* @return
*/
@Override
public boolean isValid(String date, ConstraintValidatorContext constraintValidatorContext) {
// todo 枚举类
switch (ValidTypeEnum.getValidTypeEnumByType(type)) {
case MOBILE:
message = ValidTypeEnum.MOBILE.getDesc();
return isValidMobile(date, pattern);
case DATE:
return isValidDate(date, pattern);
default:
return true;
}
}
/**
* 校验日期
*
* @param str
* @param pattern
* @return
*/
private boolean isValidDate(String str, String pattern) {
boolean convertSuccess = true;
if (str != null && str.length() == pattern.length()) {
// 指定日期格式为四位年/两位月份/两位日期,注意yyyy/MM/dd区分大小写;
SimpleDateFormat format = new SimpleDateFormat(pattern);
try {
// 设置lenient为false.
// 否则SimpleDateFormat会比较宽松地验证日期,比如2007/02/29会被接受,并转换成2007/03/01
format.setLenient(false);
Date dateStr = format.parse(str);
} catch (Exception e) {
logger.error("字段校验不通过 {}", message);
// 如果throw java.text.ParseException或者NullPointerException,就说明格式不对
convertSuccess = false;
}
} else {
convertSuccess = false;
}
return convertSuccess;
}
/**
* 校验手机号
*/
// todo 完善校验手机号的规则
private boolean isValidMobile(String mobile, String pattern) {
this.message = "777";
if ("156766001971".equals(mobile)){
return true;
}else {
return false;
}
}
}
3、创建一个实体对象用上该注解
import com.guochu.config.annotation.DataCheck;
public class ParamDTO {
@DataCheck(type = "mobile", require = true, message = "手机号非法")
private String mobile;
@DataCheck(type = "date", require = true, message = "日期非法")
private String date;
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
}
4、在controller层接口使用该参数,注意需要使用@Valid 和@RequestBody注解
@RequestMapping("/checkDate")
public void checkDate(@Valid @RequestBody ParamDTO paramDTO) {
System.out.println(paramDTO.getDate());
}
5、使用postman验证其是否有效
最后:这个报错信息是由第二步的实现ConstraintValidator接口中的方法isValid返回结果为false,则触发错误信息,触发信息是注解上方的message定义的信息。