1. 研究javax.validation.constraints.NotNull運行原理
1.1. 源碼跟進
- 為了找到
NotNull
到底是在哪里被處理,我先打印一個錯誤信息,根據錯誤信息的關鍵字,我首先找到的是這個地方,可以看到是webmvc包,可以理解,畢竟是通過接口請求並攔截的,需要經過webmvc
- 接下來要探究這句話是怎么產生的了,追溯body值得來源,發現最終捕獲異常的地方在
DispatcherServlet
類的如下方法,感覺快要找到了,進入handle方法吧
- 繼續往里面找,找到了拋
MethodArgumentNotValidException
異常的地方,可以看到驗證參數的方法就是validateIfApplicable
- 進到這個方法就能看到熟悉的小伙伴了,
@Validated
這個注解,在需要驗證的Controller接口都需要加,之后的核心驗證方法為binder.validate
,之后需要層層遞進分叉非常多了,我就講一條我遇到的實際問題找尋源碼的路徑
1.2. 問題
- 只是在
controller
層,寫個@Validated
注解,之后的@NotNull
判斷等注解判斷只在@Validated
定義的對象生效,現在我想要實現對象中的對象也實現驗證效果,我這里直接說結論了,我寫了如下類,我需要body對象也能夠得到參數驗證,則在類方法上加個@Valid
注解即可實現,接下去看源碼
@Data
public class Request<T> {
/**
* 請求體
*/
@Valid
private T body;
/**
* 請求碼(預留可不填)
*/
private Integer requestCode;
/**
* 額外請求參數,可另做處理
*/
private Map<String,Object> extend;
}
- 由於深入層數過多,我會挑幾個重點截圖,起到拋磚引玉的作用了,想要深入了解一定要自己看源碼
-
通過
SpringValidatorAdapter
驗證類作為核心
-
接下去解析注解,中間調整過多,我會跳過幾層
-
終於找到獲取對象屬性的
@Valid
注解
-
獲得了這個級聯元數據,后續的判斷就會用到這個,設值
valueContext
,我把這個ExampleDeleteVo
對象的id屬性設值了注解@NotNull
- 可以看到它獲取了id為null的值放入了
currentValue
1.3. 總結
一開始我研究@Validated
注解就是為了找是否有辦法驗證對象內對象,如果不行可能就需要自己寫攔截器方法了,不到迫不得已我也不想重復造輪子,畢竟@Validated
自帶的驗證這么多,寫起來也蠻累的,還容易出bug。有耐心看完這篇文章的估計是遇到@Vaildated
的問題了,希望能起到拋磚引玉的作用吧