前两天刚学完hibernate.validator验证器框架,通过在字段上打@Max @Min @Pattern等注解来实现字段的验证。感觉使用特别方便,于是自己做了一个简单的验证。
流程介绍:
1.首先自定义注解:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
//非空注解
public @interface NotNull{
}
2.定义解析器:
/**
* 解析字段
*
*/
public interface Parser {
/**
* 通过该字段的值进行解析判断,并且设置错误
* @param field 字段
* @param value 字段的值
* @param errors 错误
*/
public void doParse(Field field, Object value, Errors errors);
}
3.定义验证器:
/**
* 验证器
*
*/
public interface Validator {
/**
* 验证该对象
* @param obj 对象
* @return 总的错误
*/
public Errors validate(Object obj);
}
4.实现解析器:
public class NotNullParser implements Parser{
@Override
public void doParse(Field field, Object value, Errors errors) {
if(field.isAnnotationPresent(NotNull.class) && value == null) {
errors.addError(field);
}
}
}
5.实现验证器:
public class AnnotationValidator implements Validator {
//使用缓存提高反射效率
private WeakHashMap<Object, Field[]> cacheFields = new WeakHashMap<>();
private static final List<Parser> parserList = new ArrayList<>();
static {
parserList.add(new NotNullParser());
}
@Override
public Errors validate(Object obj) {
if(!cacheFields.containsKey(obj)) {
cacheFields.put(obj, obj.getClass().getDeclaredFields());
}
Errors errors = new Errors();
try{
for (Field field : cacheFields.get(obj)) {
field.setAccessible(true);
for (Parser parser : parserList) {
parser.doParse(field, field.get(obj), errors);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return errors;
}
}
6:Errors集合类:
public class Errors {
/**
* 验证产生错误的字段
*/
private List<Field> errorFieldList;
public void addError(Field field) {
ensureListNotNull();
if(!errorFieldList.contains(field))
errorFieldList.add(field);
}
public void ensureListNotNull() {
if(errorFieldList == null)
errorFieldList = new ArrayList<>();
}
public boolean existedError() {
return errorFieldList != null && errorFieldList.size() > 0;
}
}
7.最后来个测试:
public class User {
@NotNull
private String name;
private String password;
public static void main(String[] args) {
Validator validator = new AnnotationValidator();
Errors error = validator.validate(new User());
System.out.println(error.existedError()); //true
}
}