自定義註解驗證引數
阿新 • • 發佈:2019-01-30
使用註解去驗證某個物件屬性是否按照我們的註解來賦值的。
例子:我們需要定義一個MyLimit的註解,這個註解裡面規定了類屬性的限制;編寫註解解析;在類中屬性使用註解;最後測試是否是我們需要的效果。
定義MyLimit註解:
[java] view plain copy print?- @Target({ ElementType.FIELD })
- // 標註只能放在類或介面的註解
- @Retention(RetentionPolicy.RUNTIME)
- // 在執行時有效
- public@interface MyLimit {
- //這個欄位是否為必填
- boolean isNotNull() default
- // 欄位描述
- String description() default“”;
- int MaxLength() default0;
- int MinLength() default0;
- //表示這個欄位是否為int型別
- boolean isInt() defaultfalse;
- int MaxNum() default30;
- int MinNum() default18;
- }
編寫註解的解析:VerifyAnnotationMyLimit類,這個裡面使用一個List來存放驗證的錯誤資訊,getListExceptions()方法返回這個List,可以通過annotationMyLimit.getListExceptions().size()!=0來判斷驗證是否成功,不成功可以取得錯誤資訊:@Target({ ElementType.FIELD }) // 標註只能放在類或介面的註解 @Retention(RetentionPolicy.RUNTIME) // 在執行時有效 public @interface MyLimit { //這個欄位是否為必填 boolean isNotNull() default false; // 欄位描述 String description() default ""; int MaxLength() default 0; int MinLength() default 0; //表示這個欄位是否為int型別 boolean isInt() default false; int MaxNum() default 30; int MinNum() default 18; }
VerifyAnnotationMyLimit:
[java] view plain copy print?- import java.lang.reflect.Field;
- import java.util.ArrayList;
- publicclass VerifyAnnotationMyLimit {
- private MyLimit limit;
- private Class obj;
- private ArrayList<Exception> ListExceptions;
- public VerifyAnnotationMyLimit(Object object) throws Exception {
- obj = object.getClass();
- ListExceptions = new ArrayList<Exception>();
- Field[] fields = obj.getDeclaredFields();
- for (Field field : fields) {
- // 設定field為private時設定可以訪問許可權,
- field.setAccessible(true);
- // 開始驗證
- verify(field, object);
- // 重新對field設定許可權
- field.setAccessible(false);
- }
- }
- public ArrayList<Exception> getListExceptions() {
- return ListExceptions;
- }
- privatevoid verify(Field field, Object object) throws Exception {
- limit = field.getAnnotation(MyLimit.class);
- // 檢查這個field是否被MyLimit註釋
- if (!field.isAnnotationPresent(MyLimit.class)) {
- return;
- }
- // 取出object物件中的field值
- Object objectvalue = field.get(object);
- String description = ”“.equals(limit.description()) ? field.getName()
- : limit.description();
- // 先驗證是否為必填,如果必填且value為空,則丟擲異常,如果不是必填,那我們
- if (limit.isNotNull()) {
- if (“”.equals(objectvalue) || objectvalue == null) {
- ListExceptions.add(new Exception(description + “不能為空”));
- }
- } else {
- // 不是必填項先檢查是否有值,沒有就直接返回,有就繼續向下驗證
- if (objectvalue == null) {
- return;
- }
- }
- if (limit.isInt()) {
- int value = Integer.valueOf(objectvalue.toString());
- if (value < limit.MinNum() || value > limit.MaxNum()) {
- ListExceptions.add(new Exception(description + “必須在”
- + limit.MinNum() + ”到” + limit.MaxNum() + “之間”));
- }
- return;
- }
- if (objectvalue.toString().length() < limit.MinLength()
- || objectvalue.toString().length() > limit.MaxLength()) {
- ListExceptions.add(new Exception(description + “長度必須在”
- + limit.MinLength() + ”到” + limit.MaxLength() + “之間”));
- }
- }
- }
import java.lang.reflect.Field;
import java.util.ArrayList;
public class VerifyAnnotationMyLimit {
private MyLimit limit;
private Class obj;
private ArrayList<Exception> ListExceptions;
public VerifyAnnotationMyLimit(Object object) throws Exception {
obj = object.getClass();
ListExceptions = new ArrayList<Exception>();
Field[] fields = obj.getDeclaredFields();
for (Field field : fields) {
// 設定field為private時設定可以訪問許可權,
field.setAccessible(true);
// 開始驗證
verify(field, object);
// 重新對field設定許可權
field.setAccessible(false);
}
}
public ArrayList<Exception> getListExceptions() {
return ListExceptions;
}
private void verify(Field field, Object object) throws Exception {
limit = field.getAnnotation(MyLimit.class);
// 檢查這個field是否被MyLimit註釋
if (!field.isAnnotationPresent(MyLimit.class)) {
return;
}
// 取出object物件中的field值
Object objectvalue = field.get(object);
String description = "".equals(limit.description()) ? field.getName()
: limit.description();
// 先驗證是否為必填,如果必填且value為空,則丟擲異常,如果不是必填,那我們
if (limit.isNotNull()) {
if ("".equals(objectvalue) || objectvalue == null) {
ListExceptions.add(new Exception(description + "不能為空"));
}
} else {
// 不是必填項先檢查是否有值,沒有就直接返回,有就繼續向下驗證
if (objectvalue == null) {
return;
}
}
if (limit.isInt()) {
int value = Integer.valueOf(objectvalue.toString());
if (value < limit.MinNum() || value > limit.MaxNum()) {
ListExceptions.add(new Exception(description + "必須在"
+ limit.MinNum() + "到" + limit.MaxNum() + "之間"));
}
return;
}
if (objectvalue.toString().length() < limit.MinLength()
|| objectvalue.toString().length() > limit.MaxLength()) {
ListExceptions.add(new Exception(description + "長度必須在"
+ limit.MinLength() + "到" + limit.MaxLength() + "之間"));
}
}
}
Students類時註解的使用者:
[java] view plain copy print?- publicclass Students {
- privateint id;
- @MyLimit(description=“學生的姓名”,MaxLength=5,MinLength=2,isNotNull=true)
- private String name;
- @MyLimit(description=“學生的年齡”,isNotNull=true,isInt=true)
- privateint age;
- @MyLimit(MaxLength=200,isNotNull=true)
- private String addr;
- @MyLimit(description=“學生所在城市”,MaxLength=20)
- private String city;
- set…get…
- @Override
- public String toString() {
- return“Students [id=” + id + “, name=” + name + “, age=” + age
- + ”, addr=” + addr + “, city=” + city + “]”;
- }
- }
public class Students {
private int id;
@MyLimit(description="學生的姓名",MaxLength=5,MinLength=2,isNotNull=true)
private String name;
@MyLimit(description="學生的年齡",isNotNull=true,isInt=true)
private int age;
@MyLimit(MaxLength=200,isNotNull=true)
private String addr;
@MyLimit(description="學生所在城市",MaxLength=20)
private String city;
set...get...
@Override
public String toString() {
return "Students [id=" + id + ", name=" + name + ", age=" + age
+ ", addr=" + addr + ", city=" + city + "]";
}
}
在Students類中我們沒有在id的屬性上設定註解,所以不會對id進行驗證;對name屬性設定規定了長度在2到5之間,而且是必填項;在age上規定了這個是必填項,是一個int型別的,所以會使用註解對int型別預設的範圍18到哦30之間;而對於addr屬性只是規定了200長度,但是必填。
最後到了測試部分:
[java] view plain copy print?- publicstaticvoid main(String[] args) {
- // TODO Auto-generated method stub
- Students students = new Students();
- students.setName(”abcdefghijklmn”);
- students.setAddr(”“);
- students.setAge(230);
- try {//傳人Students物件進行驗證
- VerifyAnnotationMyLimit annotationMyLimit = new VerifyAnnotationMyLimit(students);
- if(annotationMyLimit.getListExceptions().size()!=0){
- for (Exception exception : annotationMyLimit.getListExceptions()) {
- System.out.println(”錯誤:”+exception.getMessage());
- }
- }
- } catch (Exception e) {
- // TODO Auto-generated catch block
- System.out.println(e.getMessage());
- e.printStackTrace();
- }
- System.out.println(students.toString());
- }
public static void main(String[] args) {
// TODO Auto-generated method stub
Students students = new Students();
students.setName("abcdefghijklmn");
students.setAddr("");
students.setAge(230);
try {//傳人Students物件進行驗證
VerifyAnnotationMyLimit annotationMyLimit = new VerifyAnnotationMyLimit(students);
if(annotationMyLimit.getListExceptions().size()!=0){
for (Exception exception : annotationMyLimit.getListExceptions()) {
System.out.println("錯誤:"+exception.getMessage());
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
System.out.println(e.getMessage());
e.printStackTrace();
}
System.out.println(students.toString());
}
if(annotationMyLimit.getListExceptions().size()!=0)判斷是驗證有錯誤;
for (Exception exception : annotationMyLimit.getListExceptions()) {
System.out.println(“錯誤:”+exception.getMessage());//輸出錯誤資訊。
}
結果:
當我們改動一些值時:
[java] view plain copy print?- students.setName(“張三”);
- students.setAddr(”xxx省xxx市xxx縣”);
- students.setAge(23);
students.setName("張三");
students.setAddr("xxx省xxx市xxx縣");
students.setAge(23);
我們按照規定填寫時就沒有錯誤了,
但是這樣還是有弊端的,因為我們是使用已經設定好屬性的物件去驗證了,等於是先給Students賦值,再去驗證我們賦值是否正確,有了一些中間操作。