1. java验证器
在java开发中我们有很多场景都会对java的属性值进行验证,如web开发中表单提交数据后台数据处理中需要对传入的值进行验证,当然目前java有很多开源属性值验证框架,如hibernate validation,spring框架中也提供了相应注解验证spring validation,相比两款验证本人觉得hibernate的提供的正则数据验证比较好用,但是这些验证比较通用,很多时候也没办法完全支持我们一些特殊场景的使用,比如我想要验证某个属性的值是否存在于某个枚举类中,有些特殊值想要特殊验证处理等,基于这些场景自己不得不另起炉灶,实现一些简单的java注解验证功能。
2. java验证案例
下面通过注解构建两种简单验证方式来完成自定义验证器的简单实现,如下面要实现该数据类TestObject的验证,通过自定义注解构建验证验证策略进行验证:
package com.annotation.validate; /** * 注解验证对象 * @author xmong */ public class TestObject { /** * 注解验证名字只能是字母下划线 */ @PatternType(pattern="^\\w*$") String name; /** * 注解验证性别值是否为性别枚举类型中的值 */ @EnumType(classType=Sex.class) String sex; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSex() { return sex; } public void setSex(String sex) { this.sex = sex; } }
自定义注解
package com.annotation.validate; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 正则类型的注解 * @author xmong */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface PatternType { /** * 注解正则 * @return */ public String pattern(); /** * 注解提示信息 * @return */ public String info() default AnnotationConfig.DEFAULT_INFO; }
package com.annotation.validate; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 枚举类型注解 * @author xmong */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface EnumType { /** * 注解class类型 * @return */ @SuppressWarnings("rawtypes") public Class classType(); /** * 注解提示信息 * @return */ public String info() default AnnotationConfig.DEFAULT_INFO; }
package com.annotation.validate; /** * 枚举类 * @author xmong */ public enum Sex { MAN,WOMEN }
要实现对不同注解的验证采用策略模式来实现,不同的验证实现类不同。
package com.annotation.validate; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.util.HashMap; import java.util.Map; /** * 验证测类,不同的验证类型需要不同验证服务来完成 * @author xmong */ public class AnnotationValidationStrategy { static Map<String, AnnotationValidationService> annotationValidationServiceMap; //静态资源初始化加载 static{ init();//初始化测类 } public static void init(){ /** * 构建验证测类服务Map,根据注解类型关联相应的验证服务 */ annotationValidationServiceMap = new HashMap<String, AnnotationValidationService>(); annotationValidationServiceMap.put(EnumType.class.getSimpleName(), new AnnotationValidationEnum()); annotationValidationServiceMap.put(PatternType.class.getSimpleName(), new AnnotationValidationPattern()); } //默认验证方法 public static boolean validateAnnotation(Object obj) throws ValidateException{ return validateAnnotation(obj, false); } /** * 遍历对象属性,根据不同的注解类型调用对应的验证服务对属性值进行验证 * @param obj 验证对象 * @param flag 值为null时是否验证 * @return 验证通过返回true,反之既然 * @throws ValidateException */ public static boolean validateAnnotation(Object obj, boolean flag) throws ValidateException{ if(null == obj) return false; Field[] fields = obj.getClass().getDeclaredFields(); //遍历对象属性 for (Field field : fields) { /** * 遍历属性注解,根据注解类型名调用相应的验证服务验证该属性 */ Annotation[] annotations = field.getAnnotations(); for (Annotation annotation : annotations) { String type = annotation.annotationType().getSimpleName(); AnnotationValidationService annotationValidationService = annotationValidationServiceMap.get(type); //判断服务是否存在,不存在则抛出异常 if(null == annotationValidationService){ String msg = String.format("AnnotationValidationService '%s' is null!", type); throw new ValidateException(msg); }else if(!annotationValidationService.validate(field, obj, flag)){ return false; } } } return true; } public Map<String, AnnotationValidationService> getAnnotationValidationServiceMap() { return annotationValidationServiceMap; } }
验证服务接口
package com.annotation.validate; import java.lang.reflect.Field; /** * 验证接口 * @author xmong */ public interface AnnotationValidationService { /** * 验证接口方法 * @param field 需要验证的域 * @param obj 需要验证的 * @param flag 是特殊值标识通过位 * @return */ public boolean validate(Field field, Object obj, boolean flag) throws ValidateException; }
验证实现类
package com.annotation.validate; import java.lang.reflect.Field; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * 正则验证 * @author xmong */ public class AnnotationValidationPattern implements AnnotationValidationService{ public boolean validate(Field field, Object obj, boolean flag)throws ValidateException { //判断该属性是否有改验证注解 if(!field.isAnnotationPresent(PatternType.class)) return false; return validateValue(field.getAnnotation(PatternType.class), field, obj, flag); } public boolean validateValue(PatternType patternType, Field field, Object obj, boolean flag) throws ValidateException{ try { //设置属性的读取值权限 field.setAccessible(true); Object object = field.get(obj); //根据标识判断属性值是否为null if(object == null && flag) return flag; //正则表达式验证属性值 Pattern pattern = Pattern.compile(patternType.pattern()); Matcher matcher = pattern.matcher(object.toString()); return matcher.matches(); } catch (IllegalArgumentException e) { e.printStackTrace(); throw new ValidateException(e.getMessage()); } catch (IllegalAccessException e) { e.printStackTrace(); throw new ValidateException(e.getMessage()); } catch(Exception e){ e.printStackTrace(); throw new ValidateException(e.getMessage()); } } }
package com.annotation.validate; import java.lang.reflect.Field; /** * 枚举类型验证 * @author xmong */ public class AnnotationValidationEnum implements AnnotationValidationService{ public boolean validate(Field field, Object obj, boolean flag) throws ValidateException { if(!field.isAnnotationPresent(EnumType.class)) return false; return validateEnum(field.getAnnotation(EnumType.class), field, obj, flag); } @SuppressWarnings("unchecked") public boolean validateEnum(EnumType enumType, Field field, Object obj, boolean flag) throws ValidateException{ try { field.setAccessible(true); Object object = field.get(obj); if(object == null && flag) return flag; //验证值是否为该注解枚举类中的值 if(null == Enum.valueOf(enumType.classType(), object.toString()))return false; return true; } catch (IllegalArgumentException e) { e.printStackTrace(); throw new ValidateException(e.getMessage()); } catch (IllegalAccessException e) { e.printStackTrace(); throw new ValidateException(e.getMessage()); } catch (Exception e){ e.printStackTrace(); throw new ValidateException(e.getMessage()); } } }
package com.annotation.validate; /** * @author xmong */ public class Test { public static void main(String[] args) { TestObject to = new TestObject(); to.setName("xmong"); to.setSex("MAN"); try { boolean flag = AnnotationValidationStrategy.validateAnnotation(to); System.out.println(flag); } catch (ValidateException e) { e.printStackTrace(); } } }
运行结果为: true