一. 引出问题
假设我们有下面一个Student类
public class Student{
private Long id; //学生学号
private String phoneNum; //手机号码
}
如果我们要对传入的数据做校验,你是不是首先想到用if语句去判断?例如
if(phone.length!=11)
return "手机应为11位"
这样会使我们的代码变得臃肿,不够简洁美观,这时我们可以自定义一个@Length注解,加载对应的实体类参数上即可。那么怎么自己实现一个呢?
|
|
V
二. 具体实现
1.编写一个注解
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Length{
int min();// 允许字符串长度的最小值
int max();// 允许字符串长度的最大值
String errorMsg();// 自定义的错误提示信息
}
tips:
- 注解中的成员变量只可以用基本类型,不能用包装类
- @Target()参数表达的含义
@Target(ElementType.FIELD) 作用于类的变量
@Target(ElementType.METHOD) 作用于类的方法
@Target(ElementType.TYPE) 作用于类、接口
- @Retention说明注解的生命周期
@Retention(RetentionPolicy.RUNTIME) 一直保留到运行时
@Retention(RetentionPolicy.CLASS) 编译进class文件,运行时忽略
@Retention(RetentionPolicy.SOURCE) 源文件有效,编译时忽略
2.对编写的注解,进行参数校验
public static String validate(Object object) throws IllegalAccessException {
// 首先通过反射获取obj ect对象的类有哪些字段
// 对本文来 说就可以获取到Phone类的id、name、mobile三个字段
Field[] fields = object.getClass().getDeclaredFields();
// for循环逐个字段校验,看哪个字段上标了注解
for(Field field : fields){
// if判断: 检查该字段上有没有标注了@Length注解
if(field.isAnnotationPresent(Length.class)){
// 通过反射获取到该字段上标注的@Length注解的详细信息
Length length = field.getAnnotation(Length.class);
// 让我们在反射时能访问到私有变量
field. setAccessible(true);
// 用过反射获取字段的实际值
int value =((String)field.get(object)).length();
// 将字段的实际值和注解上做标示的值进行比对
if(value<length.min() || value>length.max()){
return length.errorMsg();
}
}
}
return null;
}
3. 使用注解
@Length(min=11,max=11,errorMsg="手机编号应为11位")
public class Student{
@Length(min=11,max=11,errorMsg="手机编号应为11位")
private Long id; //学号
private String phoneNum; //学生手机号码
}