Я использую Spring Boot + Spring Data JPA с примером результатов привязки. У меня почти 100 контроллеров и для каждого запроса на создание/обновление мы делаем ниже.
@PostMapping
public ResponseEntity<HttpStatus> saveStudent(@Valid @RequestBody StudentDto dto, BindingResult br){
if (br.hasErrors()) {
throw new InvalidRequestException("Wrong resource", br);
}
divisionService.saveStudent(dto);
return new ResponseEntity<>(HttpStatus.CREATED);
}
Есть ли способ, если мы можем централизовать эту логику в одном месте? Можем ли мы разработать слушателей для того же самого?
if (br.hasErrors()) {
throw new InvalidRequestException("Wrong resource", br);
}
Вам не нужна ссылка на BindingResult
в вашем контроллере.
Вам понадобится только ссылка на BindingResult
в контроллере, если вы хотите основывать некоторую пользовательскую логику на том, есть ли у нее ошибки, например. перенаправить на другое представление в сценарии Rest API.
Исключения проверки будут генерироваться либо инфраструктурой проверки Java-бина (через
вы @Valid
аннотацию) или любыми реализациями Spring Validator
, применимыми к запросу.
В последнем случае фреймворк вызовет исключение MethodArgumentNotValidException, поэтому вы можете просто создать реализацию ControllerAdvice (https://spring.io/blog/2013/11/01/обработка-исключений-в-весне-mvc), которая обрабатывает исключения этого типа, и из этого можно получить BindingResult
.
@ControllerAdvice
public class ValidationErrorHandlingAdvice {
/**
* Handler for {@link MethodArgumentNotValidException}s. These are triggered by
* Spring {@link Validator} implementations being invoked by the Spring MVC
* controllers and returning validation errors.
*
*
* @param ex The {@link MethodArgumentNotValidException} to be handled.
*
* @return {@link Map} keyed by field to which the error is bound and with the
* value of the field as a value.
*/
@ResponseStatus(code = HttpStatus.BAD_REQUEST)
@ExceptionHandler(MethodArgumentNotValidException.class)
public @ResponseBody ValidationErrors handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
Map<String, List<String>> errorMap = new TreeMap<>();
BindingResult result = ex.getBindingResult();
for (FieldError error : result.getFieldErrors()) {
if (!errorMap.containsKey(error.getField())) {
errorMap.put(error.getField(), new ArrayList<String>());
}
errorMap.get(error.getField()).add(error.getDefaultMessage());
}
return new ValidationErrors(errorMap);
}
private static class ValidationErrors {
private Map<String, List<String>> errors;
public ValidationErrors(Map<String, List<String>> errors) {
this.errors = errors;
}
@SuppressWarnings("unused")
public Map<String, List<String>> getErrors() {
return errors;
}
}
}