自定義註解完成引數校驗
在現在的專案開發中,經常會用到註解,比如Spring的@Autowired,SpringMVC的@Controller,@RequestMapping等等,大部分人只知道用,不知道這些註解的怎麼發揮作用。有沒有想過手動寫一個註解,完成引數校驗呢?
簡介
註解(Annotation),也叫元資料。一種程式碼級別的說明。它是JDK1.5及以後版本引入的一個特性,與類、介面、列舉是在同一個層次。它可以宣告在包、類、欄位、方法、區域性變數、方法引數等的前面,用來對這些元素進行說明,註釋。
作用分類:
①編寫文件:通過程式碼裡標識的元資料生成文件【生成文件doc文件】
②程式碼分析:通過程式碼裡標識的元資料對程式碼進行分析【使用反射】
③編譯檢查:通過程式碼裡標識的元資料讓編譯器能夠實現基本的編譯檢查【Override】
分類
Java註解根據標記位置分為三類。
標記在類上
標記在變數上
標記在方法上
註解類上需要加入:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
依次是,標記的位置,註解生存週期。
標記在方法上
執行時有效
實戰
在編寫註解之前需要了解,你的引數校驗需要做哪些工作。
此次校驗是標記在變數上的,主要功能包括:
非空校驗
長度校驗
正則校驗
這幾條包含了大部分的資料校驗的功能。
開始
編寫註解:Validation.java
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Validation {
//校驗失敗報錯資訊
String value();
//最大值
String max();
//最小值
String min();
//正則表示式
String pattern();
}
編寫校驗程式碼:
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Check {
public static void check(Object o) {
if (null == o) {
return;
}
Class clazz = o.getClass();
ListField fieldList = new ArrayListField();
while (clazz != null) {
fieldList.addAll(new ArrayList(Arrays.asList(clazz.getDeclaredFields())));
clazz = clazz.getSuperclass();
}
fieldList.forEach(field - {
field.setAccessible(true);
try {
Object value = field.get(o);
Validation annotation = field.getAnnotation(Validation.class);
if (null == annotation) {
return;
}
checkNotNull(value, annotation);
checkPattern(value, annotation);
checkMax(value, annotation);
checkMin(value, annotation);
} catch (IllegalArgumentException e) {
e.printStackTrace();
//資料解析失敗
} catch (IllegalAccessException e) {
e.printStackTrace();
}
});
}
private static double objectToDubule(Object o) {
return Double.valueOf(o.toString());
}
private static void checkNotNull(Object value, Validation validation) {
if (validation.notNull() value == null) {
throw new RuntimeException(validation.value());
}
}
private static void checkPattern(Object value, Validation validation) {
if (null != validation.pattern() validation.pattern().length() 0) {
Pattern p = Pattern.compile(validation.pattern());
Matcher m = p.matcher(value.toString());
if (!m.matches()) {
throw new RuntimeException(validation.value());
}
}
}
private static void checkMax(Object value, Validation validation) {
if (validation.max() 0) {
if (value instanceof String) {
if (value.toString().length() validation.max()) {
throw new RuntimeException(validation.value());
}
} else {
if (objectToDubule(value) validation.max()) {
throw new RuntimeException(validation.value());
}
}
}
}
private static void checkMin(Object value, Validation validation) {
if (validation.max() = 0) {
if (value instanceof String) {
if (value.toString().length() validation.min()) {
throw new RuntimeException(validation.value());
}
} else {
if (objectToDubule(value) validation.min()) {
throw new RuntimeException(validation.value());
}
}
}
}
}
測試
編寫CheckTest.java
import org.junit.Test;
public class CheckTest {
@Test
public void check() {
TestData data = new TestData();
data.arg = 20;
data.setMobile(1368989889);
data.setName(test);
Check.check(data);
System.out.println(校驗通過);
}
class TestData {
@Validation(value = 名稱校驗失敗, notNull = true)
private String name;
@Validation(value = 手機號校驗失敗, notNull = true, pattern = ^1(3[0-9]|4[0-9]|5[0-35-9]|8[0-9]|7[0-9]|6[0-9]|9[0-9])\\d{8}$)
private String mobile;
@Validation(value = 年齡校驗失敗, notNull = true, max = 60, min = 18)
private Integer arg;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public Integer getArg() {
return arg;
}
public void setArg(Integer arg) {
this.arg = arg;
}
}
}
執行截圖:
手機號錯誤
資料正確