基于注解的方式校验其实很多,但是在复杂模型方式方面,貌似未查询到,所以自己写了一个,主要是复杂的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方式进行表达式强校验,可以查阅我其它文章。