首先關於反射的知識就不說了因為網上的資源實在是太多了,註解的基本知識也不說了,網上同樣有很多,好像都是廢話,咱們迴歸正題,今天的內容是通過自定義註解和反射實現參數值的自動驗證,那麼我們為什麼要做這個驗證呢?其實我們前端會驗證,數據庫也會驗證,那麼我們為什麼還要在後臺代碼中驗證呢?個人認為這是一個嚴謹的問題,首先前端是可以驗證,但是如果前端安全驗證做的不好,那麼你的數據接口會被人分析抓取,當然如果你用的是velocity/jsp/freemaker等一些模板引擎的話是沒法抓取接口的,這時候你的接口被抓我就可通過模擬你的接口參數隨便提交數據了。這時候有些參數可能不是在接口裡攜帶,這個參數就可以從session中獲取,這樣可以避免直接訪問數據接口被竊取。數據庫的話比如建表時如果設置了主外鍵不為空最大長度類型等,寫入數據時數據表也會報錯。那麼這個算起來的話也算有兩次驗證了,我們為什麼還要在代碼裡進行驗證呢,個人認為第一,還是那句話嚴謹,要不然這就是bug,哈哈,第二,雖然前端和數據庫算是兩次驗證,但是這樣的驗證不安全,比如有人寫一段注入攻擊的js代碼提交,第三,這裡的驗證可以減少數據庫的交互壓力……
那麼問題來了,我們為什麼要“手動通過java通過反射和自定義註解實現後臺參數值的驗證”?,個人原因,第一,為了少寫代碼,第二,為了能夠學習一些知識,第三,就像裝會兒逼,當然這也不是多厲害的技術。那麼進入正題,以前我們是怎麼驗證的呢?
1、struts2的valid可以通過配置xml,xml中描述規則和返回的信息,這種方式比較麻煩、開發效率低,不推薦
2、validation bean 是基於JSR-303標準開發出來的,使用註解方式實現,及其方便,但是這只是一個接口,沒有具體實現.Hibernate Validator是一個hibernate獨立的包,可以直接引用,他實現了validation bean同時有做了擴展,比較強大 ,實現圖如下:
點此查看中文官方手冊
3、oval 是一個可擴展的Java對象數據驗證框架,驗證的規則可以通過配置文件、Annotation、POJOs 進行設定。可以使用純 Java 語言、JavaScript 、Groovy 、BeanShell 等進行規則的編寫,本次不過多講解
4、 Springboot validator實際集成了Hibernatevalidator。主要是校驗用戶提交的數據的合理性的,比如是否為空了,密碼長度是否大於6位,是否是純數字的,等等。方便後臺的數據合法性的校驗。
代碼基本都長這樣
那麼一下咱們自己實現一下這個東東
1.第一,創建自定義註解,如下圖,咱們先做一個email驗證的,其他的基本步驟都一樣,舉一反三啦
2.第二,編寫驗證的反射類
/**
* 註解驗證方法
*
* @param bean 驗證的實體
* @return
*/
@SuppressWarnings("unchecked")
public static Map
Map
result.put("message", "驗證通過");
result.put("result", true);
Class> cls = bean.getClass();
// 檢測field是否存在
try {
// 獲取實體字段集合
Field[] fields = cls.getDeclaredFields();
for (Field f : fields) {
// 通過反射獲取該屬性對應的值
f.setAccessible(true);
// 獲取字段值
Object value = f.get(bean);
// 獲取字段上的註解集合
Annotation[] arrayAno = f.getAnnotations();
for (Annotation annotation : arrayAno) {
// 獲取註解類型(註解類的Class)
Class> clazz = annotation.annotationType();
// 獲取註解類中的方法集合
Method[] methodArray = clazz.getDeclaredMethods();
for (Method method : methodArray) {
// 獲取方法名
String methodName = method.getName();
// 過濾錯誤提示方法的調用
if(methodName.equals("message")) {
continue;
}
// 初始化註解驗證的方法處理類 (我的處理方法卸載本類中)
Object obj = ValidateUtil.class.newInstance();
// 獲取方法
try {
// 根據方法名獲取該方法
Method m = obj.getClass().getDeclaredMethod(methodName, Object.class, Field.class);
// 調用該方法
result = (Map
/* 驗證結果 有一處失敗則退出 */
if(result.get("result").equals(false)) {
result.put(f.getName(), value);
return result;
}
} catch (Exception e) {
e.printStackTrace();
log.info("找不到該方法:"+methodName);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
log.info("驗證出錯");
}
return result;
}
3.第三我們編寫驗證方法,這裡我用一個正則來實現
4.編寫一個實體類,用於驗證,這裡是測試我們隨便寫
5.我們直接在main函數中進行測試。
6.輸出結果,我傳的是手機號,所以驗證失敗了
那麼這個流程就算完了,那麼現在這個是最簡單的一個驗證,完了之後我們還可以擴展很多出來,比如我們要封裝一個mvc框架,我們可以在controller層實現參數的接收封裝,參數驗證如下圖
這樣就可以實現參數自動接受封裝和驗證,當然通過註解和反射也可以做其他事情如,路由映射,權限驗證,xss攻擊過濾,數據處理,實現aop,數據表結構實體映射等等,大家自己動手試試吧
閱讀更多 在我的瞳孔裡照見你 的文章