驗證
Spring WebFlux 為 @RequestMapping
方法內建了 驗證 功能,包括 Java Bean 驗證。驗證可以應用在以下兩個層面之一
-
@ModelAttribute、@RequestBody 和 @RequestPart 引數解析器會單獨驗證方法引數,如果方法引數被 Jakarta
@Valid
或 Spring 的@Validated
註解,並且緊隨其後沒有Errors
或BindingResult
引數,並且不需要方法驗證(將在後面討論)。在這種情況下丟擲的異常是WebExchangeBindException
。 -
當
@Constraint
註解(例如@Min
、@NotBlank
等)直接宣告在方法引數上或方法上(針對返回值)時,必須應用方法驗證,這會覆蓋方法引數級別的驗證,因為方法驗證同時涵蓋了方法引數約束和透過@Valid
的巢狀約束。在這種情況下丟擲的異常是HandlerMethodValidationException
。
應用必須處理 WebExchangeBindException
和 HandlerMethodValidationException
,因為根據控制器方法簽名,兩者都可能被丟擲。然而,這兩個異常設計得非常相似,並且可以使用幾乎相同的程式碼進行處理。主要區別在於前者針對單個物件,而後者針對方法引數列表。
@Valid 不是一個約束註解,而是用於物件內的巢狀約束。因此,單獨使用 @Valid 不會導致方法驗證。另一方面,@NotNull 是一個約束,將其新增到帶有 @Valid 的引數上會導致方法驗證。特別對於可空性,您也可以使用 @RequestBody 或 @ModelAttribute 的 required 標誌。 |
方法驗證可以與 Errors
或 BindingResult
方法引數結合使用。但是,只有當所有驗證錯誤都發生在緊隨其後帶有 Errors
的方法引數上時,才會呼叫控制器方法。如果任何其他方法引數上存在驗證錯誤,則會丟擲 HandlerMethodValidationException
。
您可以透過 WebFlux 配置 全域性配置 Validator
,或者透過 @Controller
或 @ControllerAdvice
中的 @InitBinder 方法進行本地配置。您還可以使用多個驗證器。
如果控制器類上帶有 @Validated 註解,則透過 AOP 代理應用方法驗證。為了利用 Spring Framework 6.1 中新增的 Spring MVC 內建方法驗證支援,您需要從控制器中移除類級別的 @Validated 註解。 |
錯誤響應 部分提供了關於如何處理 WebExchangeBindException
和 HandlerMethodValidationException
的更多詳細資訊,以及如何透過 MessageSource
和特定於區域設定和語言的資源包定製其渲染。
為了進一步自定義處理方法驗證錯誤,您可以擴充套件 ResponseEntityExceptionHandler
或在控制器或 @ControllerAdvice
中使用 @ExceptionHandler
方法,並直接處理 HandlerMethodValidationException
。該異常包含一個 ParameterValidationResult
列表,這些列表按方法引數對驗證錯誤進行分組。您可以遍歷這些結果,或者提供一個訪問者,該訪問者根據控制器方法引數型別提供回撥方法
-
Java
-
Kotlin
HandlerMethodValidationException ex = ... ;
ex.visitResults(new HandlerMethodValidationException.Visitor() {
@Override
public void requestHeader(RequestHeader requestHeader, ParameterValidationResult result) {
// ...
}
@Override
public void requestParam(@Nullable RequestParam requestParam, ParameterValidationResult result) {
// ...
}
@Override
public void modelAttribute(@Nullable ModelAttribute modelAttribute, ParameterErrors errors) {
// ...
@Override
public void other(ParameterValidationResult result) {
// ...
}
});
// HandlerMethodValidationException
val ex
ex.visitResults(object : HandlerMethodValidationException.Visitor {
override fun requestHeader(requestHeader: RequestHeader, result: ParameterValidationResult) {
// ...
}
override fun requestParam(requestParam: RequestParam?, result: ParameterValidationResult) {
// ...
}
override fun modelAttribute(modelAttribute: ModelAttribute?, errors: ParameterErrors) {
// ...
}
// ...
override fun other(result: ParameterValidationResult) {
// ...
}
})