相对于传统的流水账式的校验,使用注解好处很多,提高开发效率,减少出错率,极大的减少代码量,统一在实体类管理维护,直观清晰。
以下是一个示例。 两个校验,1、校验值只能存在于指定的枚举值内 2、校验时间是否合理。
第一步,自定义注解,起到标记作用。 (注解在这里只起到标记和设定参数的作用)
/**
* 类型枚举校验
* @author caixl
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface TypeEnumValid {
public String value() default "";
}
/**
校验时间的合理性,如证件有效期必须在今天以后
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface DateValid {
public DateTypeEnum value() default DateTypeEnum.All;
}
------另外一个类 DateTypeEnum的枚举 -----
/**
* Past 过去
* @author caixl
*/
public enum DateTypeEnum {
Futher, TodateOrFuther, Todate, Past, TodateOrPast, All
}
第二步,在实体类标记某个字段。 如下片段,两种类型的校验都用到了。
@DateValid(DateTypeEnum.Futher)
@Size(max=10)
@NotEmpty
private String doc_expire;
@TypeEnumValid("0;1;2;3;4;5")
private int business_type;
@Size(max=80)
@NotEmpty
private String address;
@TypeEnumValid("1;2")
private int bpremises_type;
@NotEmpty
@Size(max=20)
@TypeEnumValid("1;2;3;4;5;6;7;8;9;10")
第三步,对所有自定义注解的校验逻辑, 这里抽象出来为一个方法。 主要用到反射,和固定校验逻辑。
/**
* 对自定义的注解进行校验
* @author caixl
*/
@Slf4j
public class AnnotationValid {
public static String valid(Object object) {
StringBuffer errorStr = new StringBuffer();
try {
errorStr.append(vaildDateAnnotation(object));
} catch (Exception e) {
log.info("校验时发生异常", e);
errorStr.append("校验时发生异常");
}
return errorStr.toString();
}
public static String vaildDateAnnotation(Object object) {
StringBuffer errorStr = new StringBuffer();
Field[] fields = object.getClass().getDeclaredFields();
for (Field field : fields) {
String fieldname = field.getName();
Annotation[] allFAnnos= field.getAnnotations();
if(null ==allFAnnos || allFAnnos.length ==0) continue;
//开始时间格式的校验
DateValid dateValid = field.getAnnotation(DateValid.class);
if(null != dateValid) {
try {
field.setAccessible(true);
String fieldval = (String)field.get(object);
if(! StringUtils.hasLength(fieldval)) continue; //空则不做校验
if(! DateUtil.validDateFormat(fieldval)) {
errorStr.append(fieldname+"日期格式不正确");
}else if(dateValid.value() == DateTypeEnum.Futher) {
if(!(DateUtil.dateMinusNowDate(fieldval) > 0)) {
errorStr.append(fieldname+"日期需大于今天;");
}
}else if(dateValid.value() == DateTypeEnum.TodateOrFuther) {
if(!(DateUtil.dateMinusNowDate(fieldval) >= 0)){
errorStr.append(fieldname+"日期需等于或大于今天;");
}
}else if(dateValid.value() == DateTypeEnum.Past) {
if(!(DateUtil.dateMinusNowDate(fieldval) < 0)) {
errorStr.append(fieldname+"日期需小于今天;");
}
}else if(dateValid.value() == DateTypeEnum.TodateOrPast) {
if(!(DateUtil.dateMinusNowDate(fieldval) <= 0)) {
errorStr.append(fieldname+"日期需小于或等于今天;");
}
}
} catch (Exception e) {
log.info("日期校验异常", e);
errorStr.append(fieldname+"日期校验异常");
}
}
//校验枚举
TypeEnumValid enumValid = field.getAnnotation(TypeEnumValid.class);
if(null != enumValid) {
try {
field.setAccessible(true);
Object fieldObject = field.get(object);
String fieldval = fieldObject.toString();
/*
* if((fieldObject.getClass()). equals(String.class)) { fieldval =
* (String)fieldObject; }else
* if((fieldObject.getClass()).equals(Integer.class)){ fieldval =
* ((Integer)fieldObject).toString() ; }
*/
if(! StringUtils.hasLength(fieldval)) continue; //空则不做校验
String annoStr = enumValid.value();
String[] allEnum = annoStr.split(";");
if(! vaildStrInArr(fieldval,allEnum)) {
errorStr.append(fieldname+"不在取值范围内;");
}
} catch (Exception e) {
log.info("枚举校验异常", e);
errorStr.append(fieldname+ "枚举校验异常");
}
}
}
return errorStr.toString();
}
public static boolean vaildStrInArr(String str , String[] arr) {
if(!StringUtils.hasText(str ) || null ==arr || ! (arr.length>0) ) {
return false;
}
for(String arrstr : arr) {
if(null != arrstr && str.equals(arrstr)) {
return true;
}
}
return false;
}
}
第四步,在业务代码中,使用我们前面封装的内容。 一行代码即可,无错误则返回的是一个空字符串。
String validMsg = AnnotationValid.valid(sendMerchantVo); //注解校验,这里传入的是要校验的实体类
另外附上DateUtil的内容,上面用到了,在另外一个文件中。
https://www.yuque.com/caixl/java/wg2n4r