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的問題了,希望能起到拋磚引玉的作用吧
