相对于传统的流水账式的校验,使用注解好处很多,提高开发效率,减少出错率,极大的减少代码量,统一在实体类管理维护,直观清晰。
以下是一个示例。 两个校验,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)@NotEmptyprivate String doc_expire;@TypeEnumValid("0;1;2;3;4;5")private int business_type;@Size(max=80)@NotEmptyprivate 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*/@Slf4jpublic 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
