Почему некоторые параметры метода нужно ставить раньше других?
Собственно столкнулся с проблемой, на решение которой потратил много времени - Нет редиректа после ошибки валидации Spring boot
Поясните почему так и с чем это связано? А то не хочется в следующий раз тратить два дня на решение такой ерунды.
Ответы (1 шт):
Подобный вопрос на основном SO: Why does BindingResult have to follow @Valid?
Такой порядок обусловлен тем, что в обработчике запросов контроллера потенциально может быть несколько объектов, для которых требуется валидация, то есть, помеченных аннотацией @Valid. Соответственно, для каждого такого объекта понадобится свой экземпляр BindingResult, и вполне логично, чтобы эти объекты находились рядом.
Сама валидация выполняется в методе org.springframework.web.method.annotation.ModelAttributeMethodProcessor::resolveArgument:
public final Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
// ....
if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {
throw new BindException(binder.getBindingResult());
}
// ...
}
И соответственно в методе isBindExceptionRequired проверяется, что следующий за данным параметром объект НЕ является экземпляром интерфейса Errors, от которого унаследован интерфейс BindingResult, то есть, НУЖНО выбросить соответствующее исключение:
/**
* Whether to raise a fatal bind exception on validation errors.
* @param parameter the method parameter declaration
* @return {@code true} if the next method parameter is not of type {@link Errors}
* @since 5.0
*/
protected boolean isBindExceptionRequired(MethodParameter parameter) {
int i = parameter.getParameterIndex();
Class<?>[] paramTypes = parameter.getExecutable().getParameterTypes();
boolean hasBindingResult = (paramTypes.length > (i + 1) && Errors.class.isAssignableFrom(paramTypes[i + 1]));
return !hasBindingResult;
}