踩坑筆記【1】關於spring requestbody校驗使用@Valid無法校驗list等collections

鄧gf發表於2021-09-27

問題闡述:
當前關於controller層的request的引數校驗,經常會使用到javax.validation包下的@Valid註解,在對應的javabean中使用各種javax.validation.constraints下的各種註解完成校驗。
但是當傳輸引數為list或者其他非object的collection時,會發現校驗並不生效。
原因是這種方式是透過
org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor呼叫的org.hibernate.validator.internal.engine.ValidatorImpl中的validate方法進行校驗,但僅僅只會校驗object的各個屬性,並不會校驗list中的各個elements。

解決方案:配合@Validated使用@Valid
將@Validated放置在controller類上,同時繼續使用@Valid和@requestBody在請求引數前,此時這種方式會透過
org.springframework.validation.beanvalidation.MethodValidationInterceptor呼叫org.hibernate.validator.internal.engine.ValidatorImpl中的validateParameters方法,該方法會校驗list中的各個element。

區別:
傳統的第一種方式會直接丟擲400。第二種方式是經由controller類丟擲ConstraintViolationException,第二種方式是更加普適的可以用於所有的類中方法的引數校驗,並不專用於controller層,如果想獲得類似第一種方式的exception,需要在@RestControllerAdvice的globalhandler做一下異常處理。

其他方案:
1⃣️可以嘗試將傳輸的引數變為object,繼而將list作為object的一個field,但是這種方式會要求呼叫方做相應的改動。
2⃣️將list變為一個javabean,實現類似如下:
@Data
public class ValidList<E> implements List<E> {

@Valid
@Delegate
private List<E> list = new ArrayList<>();

}

相關文章