前言
java annotation校验器,使用简单,可扩展,可以显著提升开发效率,参考网上例子写了个小例子,比较简单,明白即可
我的理解
Annotation信息可以被编译进class文件,也可以保留在Java 虚拟机中,从而在运行时可以获取,这里充分展示了反射的魅力
实例
注解类
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.FIELD, ElementType.PARAMETER })
public @interface Validate {
//是否可以为空
boolean nullable() default false;
//最大长度
int maxLength() default 0;
//最小长度
int minLength() default 0;
//参数或者字段描述,这样能够显示友好的异常信息
String description() default "";
}
校验器
public class ValidateService {
private static Validate validate;
//解析的入口
public static void valid(Object object) throws Exception {
//获取object的类型
Class<? extends Object> clazz = object.getClass();
//获取该类型声明的成员
Field[] fields = clazz.getDeclaredFields();
//遍历属性
for (Field field : fields) {
//对于private私有化的成员变量,通过setAccessible来修改器访问权限
field.setAccessible(true);
validate(field, object);
//重新设置会私有权限
field.setAccessible(false);
}
}
public static void validate(Field field, Object object) throws Exception {
//获取对象的成员的注解信息
validate = field.getAnnotation(Validate.class);
Object value = field.get(object);
if (validate == null)
return;
String description = validate.description().equals("") ? field.getName() : validate.description();
/*************注解解析工作开始******************/
if (!validate.nullable()) {
if (value == null || StringUtils.isBlank(value.toString())) {
throw new Exception(description+"不能为空");
}
}
if (value != null) {
if (value.toString().length() > validate.maxLength() && validate.maxLength() != 0) {
throw new Exception(description+"长度不能超过" + validate.maxLength());
}
if (value.toString().length() < validate.minLength() && validate.minLength() != 0) {
throw new Exception(description+"长度不能小于" + validate.minLength());
}
}
/*************注解解析工作结束******************/
}
}
要校验的类
public class User {
@Validate(description = "用户名", minLength = 2, maxLength = 32)
private String name;
@Validate(description = "用户住址", minLength = 2, maxLength = 32)
private String address;
@Validate(description = "用户年龄", nullable = false)
private Integer age;
public User(String name, String address, Integer age) {
this.name = name;
this.address = address;
this.age = age;
}
/**
* Getter method for property <tt>name</tt>.
*
* @return property value of name
*/
public String getName() {
return name;
}
/**
* Setter method for property <tt>name</tt>.
*
* @param name value to be assigned to property name
*/
public void setName(String name) {
this.name = name;
}
/**
* Getter method for property <tt>address</tt>.
*
* @return property value of address
*/
public String getAddress() {
return address;
}
/**
* Setter method for property <tt>address</tt>.
*
* @param address value to be assigned to property address
*/
public void setAddress(String address) {
this.address = address;
}
/**
* Getter method for property <tt>age</tt>.
*
* @return property value of age
*/
public Integer getAge() {
return age;
}
/**
* Setter method for property <tt>age</tt>.
*
* @param age value to be assigned to property age
*/
public void setAge(Integer age) {
this.age = age;
}
}
测试
public class AnnotationTest {
public static void main(String[] args) {
User user = new User("kobebryant", "la.lakers", null);
try {
ValidateService.valid(user);
System.out.println("符合输入规则!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
执行结果
总结
1.可以看到程序运行时,通过反射读取待校验类的信息,进行校验
2.关于里面元注解和反射的东西自己理解吧
3. 可以看到,这种校验方式非常方便,但有一个很不好的缺点,嵌入代码太深,要修改的话会比较麻烦。所以使用根据具体业务来吧