Spring MVC @Valid Validation с пользовательским HandlerMethodArgumentResolver
Я хочу зарегистрировать пользовательский HandlerMethodArgumentResolver
, который может обрабатывать следующее определение метода обработчика @Controller
@RequestMapping(method = RequestMethod.POST)
public String createDomain(@Valid Domain domain, BindingResult errors, @RequestParam("countryId") Long countryId) {
Я могу зарегистрировать свой резольвер, который просто создает объект Domain
через параметры запроса, переопределяя addArgumentResolver()
из WebMvcConfigurerAdapter
. Когда Spring пытается разрешить параметр Domain
, он проходит через свой список HandlerMethodArgumentResolver
(их много) и выбирает первый, который supports()
он.
В приведенном выше примере, хотя мой резольвер будет вызван, и мой аргумент Domain
будет инициализирован, аннотация @Valid
не будет обработана и преобразователем для BindingResult
, a ErrorsMethodArgumentResolver
завершится с ошибкой, так как для метода обработчика требуется @ModelAttribute
, @RequestBody
или @RequestPart
аргумент, который у меня отсутствует.
Если я попытаюсь исправить это, добавив @ModelAttribute
@RequestMapping(method = RequestMethod.POST)
public String createDomain(@Valid @ModelAttribute Domain domain, BindingResult errors, @RequestParam("countryId") Long countryId) {
a HandlerMethodArgumentResolver
, ModelAttributeMethodProcessor
, сначала будет проверяться с помощью supports()
и разрешить аргумент (с @ModelAttribute
и @Valid
) перед моим пользовательским преобразователем. BindingResult
не будет работать, но у меня не будет своего пользовательского поведения создания на экземпляре Domain
.
Я мог бы просто скопировать код для проверки и добавить к модели, что в ModelAttributeMethodProcessor
, но я надеялся, что есть более простой способ разрешить мои параметры и выполнить проверку без добавления объекта к модели. Есть ли такой способ?
Ответы
Ответ 1
Хорошее описание проблемы, с которой вы столкнулись.
Я проверил код, который вы наметили, и пришел к тому же выводу, что у вас есть - нет встроенного способа иметь как настраиваемую HandlerMethodArgumentResolver
так и @Valid
связанную проверку, применяемую при этом time, единственный выбор - сделать то, что делает ModelAttributeMethodProcessor
, чтобы проверить, имеет ли параметр аннотацию @Valid
и вызывает код логики проверки достоверности.
Вероятно, вы можете получить HandlerMethodResolverArgumentResolver
от ModelAttributeMethodProcessor
и вызвать super.validateIfApplicable(..)
по крайней мере таким образом, чтобы существующий код был задействован.
Ответ 2
Возможно, слишком поздно, но ваш HandlerMethodArgumentResolver
получает объект WebDataBinderFactory
в качестве последнего аргумента, а затем, чтобы подключить проверку, просто добавьте это в свою реализацию resolver:
Object resolvedObject = // your logic
if(parameter.hasParameterAnnotation(Valid.class){
binderFactory.createBinder(webRequest,resolvedObject,"resolvedObjectLogicalName").validate ();
}