基于注解的方式校验其实很多,但是在复杂模型方式方面,貌似未查询到,所以自己写了一个,主要是复杂的json串,将其生成Object,然后对于Object校验...
注解申明不过于进行介绍,主要谈下配合反射进行递归校验过程,校验
?这里以UrlParser校验,当然接口提供后可以有无数个比如money、date、身份证等,
注解类
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface ValidationDriver { public ValidationType type(); }
?
/** * * @author Young * */ public enum ValidationType { // support multi type Length, Email, NotBlank, URL, Phone, Money, Date; }
?
核心的校验过程
public static ValidateMsg validate(Object field) throws Exception { ValidateMsg result = null; for (Field f : field.getClass().getDeclaredFields()) { if (f.isAnnotationPresent(ValidationDriver.class)) { ValidationDriver driver = f .getAnnotation(ValidationDriver.class); f.setAccessible(true); Object value = null; try { value = f.get(field); } catch (IllegalArgumentException e) { } catch (IllegalAccessException e) { } IAnnotationParser parse = fetchValidateParser(driver); result = parse.validate(f, value); if (result != null && !result.isResult()) break; } else if (f.getType().getName().contains("hundsun")) { result = recursiveCheck(field, f); if (result != null && !result.isResult()) break; } else if (f.getType().getName().equals("java.util.List")) { // 获取泛型 Type fc = f.getGenericType(); f.setAccessible(true); if (fc == null) { continue; } Method m = (Method) field.getClass().getMethod( "get" + getMethodName(f.getName())); //当类型中是List,获取list的数据,再进行校验 List list = (List) m.invoke(field); if (list != null && list.size() > 0) { for (Object object : list) { result = validate(object); if (result != null && !result.isResult()) break; } } if (result != null && !result.isResult()) break; } } if (result == null) { result = new ValidateMsg(); result.setMessage("everything is ok"); } return result; } /** * 递归校验 * * @param field * @param f * @return * @throws IllegalAccessException * @throws InvocationTargetException * @throws InstantiationException * @throws IllegalArgumentException */ private static ValidateMsg recursiveCheck(Object field, Field f) throws Exception { ValidateMsg result = null; f.setAccessible(true); Field[] fields = f.getType().getDeclaredFields(); for (Field fieldSon : fields) { if (fieldSon.isAnnotationPresent(ValidationDriver.class)) { ValidationDriver driver = fieldSon .getAnnotation(ValidationDriver.class); fieldSon.setAccessible(true); Object valSon = fieldSon.get(f.get(field)); IAnnotationParser parse = fetchValidateParser(driver); result = parse.validate(fieldSon, valSon); if (result != null && !result.isResult()) break; } else if (fieldSon.getType().getName().equals("java.util.List")) { // 获取泛型 Type fc = fieldSon.getGenericType(); fieldSon.setAccessible(true); if (fc == null) { continue; } Method m = (Method) f.get(field).getClass() .getMethod("get" + getMethodName(fieldSon.getName())); List list = (List) m.invoke(f.get(field)); if (list != null && list.size() > 0) { for (Object object : list) { result = validate(object); if (result != null && !result.isResult()) break; } } } } return result; } private static String getMethodName(String fildeName) throws Exception { byte[] items = fildeName.getBytes(); items[0] = (byte) ((char) items[0] - ‘a‘ + ‘A‘); return new String(items); }
?上述方式支持
public class A{ @ValidationDriver(type = ValidationType.NotBlank) private int age; private List<B> list; get/set } public class B{ @ValidationDriver(type = ValidationType.NotBlank) private int id; private List<C> list get/set } public class C{ @ValidationDriver(type = ValidationType.NotBlank) private int id; @ValidationDriver(type = ValidationType.URL) private String name; }
?最终URLparser校验
public class UrlParser implements IAnnotationParser { @Override public ValidateMsg validate(Field field, Object value) { ValidateMsg msg = null; if (value != null) { Pattern p = Pattern .compile( "^(http|www|ftp|)?(://)?(\\w+(-\\w+)*)(\\.(\\w+(-\\w+)*))*((:\\d+)?)(/(\\w+(-\\w+)*))*(\\.?(\\w)*)(\\?)?(((\\w*%)*(\\w*\\?)*(\\w*:)*(\\w*\\+)*(\\w*\\.)*(\\w*&)*(\\w*-)*(\\w*=)*(\\w*%)*(\\w*\\?)*(\\w*:)*(\\w*\\+)*(\\w*\\.)*(\\w*&)*(\\w*-)*(\\w*=)*)*(\\w*)*)$", Pattern.CASE_INSENSITIVE); Matcher m = p.matcher(value.toString()); if (!m.matches()) { msg = new ValidateMsg(); msg.setMessage(field.getName() + " url is invalid"); msg.setResult(false); } } return msg; } }
?
结论:
能够支持多种复杂类型,然后进行成员变量的校验,基本能够完成其校验工作。通过学习反射了解到很多知识点,弥补过多if else判断,当然这里其实校验过程也可以使用antlr方式进行表达式强校验,可以查阅我其它文章。
原文:http://cywhoyi.iteye.com/blog/2232104