У меня есть приложение Spring Boot 2, и я хочу иметь возможность проверять аргументы контроллера с помощью валидатора Hibernate, который я успешно использую.У меня все контроллеры помечены как @Validated
, и я использую проверку параметров запроса, например, @PathVariable @AssertUuid final String customerId
- пока все хорошо, все работает.
Но я также хочу иметь возможность проверить@ModelAttribute
из форм.
@Controller
@PreAuthorize("hasRole('ADMIN')")
@RequestMapping(path = "/customers")
@Validated
public class CustomerController
{
private final CustomerFacade customerFacade;
public CustomerController(
final CustomerFacade customerFacade
)
{
this.customerFacade = customerFacade;
}
@GetMapping("/create")
public ModelAndView create(
final AccessToken accessToken
)
{
return new ModelAndView("customer/create")
.addObject("customer", new CreateCustomerRequest());
}
@PostMapping("/create")
public ModelAndView handleCreate(
final AccessToken accessToken,
@Validated @ModelAttribute("customer") final CreateCustomerRequest customerValues,
final BindingResult validation
) throws
UserDoesNotHaveAdminAccessException
{
if (validation.hasErrors()) {
return new ModelAndView("customer/create")
.addObject("customer", customerValues);
}
CustomerResult newCustomer = customerFacade.createCustomer(
accessToken,
customerValues.getName()
);
return new ModelAndView(new RedirectView("..."));
}
public static final class CreateCustomerRequest
{
@NotNull
@NotBlank
private String name;
public CreateCustomerRequest(final String name)
{
this.name = name;
}
public CreateCustomerRequest()
{
}
public String getName()
{
return name;
}
}
}
Но это заставляет MethodValidationInterceptor
выбрасывать ConstraintViolationException
, когда я отправляю неверные данные.Обычно это имеет смысл, и я хочу, чтобы такое поведение было в любом другом случае, но в этом случае, как вы можете видеть, я хочу использовать BindingResult
для обработки ошибок валидации - что необходимо при работе с формами.
Есть ли способ, которым я мог бы сказать Spring, чтобы он не проверял этот конкретный параметр с помощью MethodValidationInterceptor
, потому что он уже проверен связывателем, и я хочу обработать его по-другому?
Я копался ввесенний код, и, похоже, не предназначен для совместной работы.У меня есть несколько идей, как это исправить:
- уберите
@Validated
из аргумента и - вызов
validator.validate()
явно в методе контроллера - уродливо и опасно (вы можетезабудьте об этом) - создайте еще один перехватчик AOP, который найдет «пары» из
@ModelAttribute
и BindingResult
и вызовет там валидатор, вызывая глобальную проверку
Я совершенно не прав?Я что-то пропустил?Есть ли лучший способ?