Получить имя поля, когда javax.validation.ConstraintViolationException выбрано
Когда имя PathVariable не проходит проверку, генерируется исключение javax.validation.ConstraintViolationException. Есть ли способ получить имя параметра в метании javax.validation.ConstraintViolationException?
@RestController
@Validated
public class HelloController {
@RequestMapping("/hi/{name}")
public String sayHi(@Size(max = 10, min = 3, message = "name should have between 3 and 10 characters") @PathVariable("name") String name) {
return "Hi " + name;
}
Ответы
Ответ 1
Следующий обработчик исключений показывает, как он работает:
@ExceptionHandler(ConstraintViolationException.class)
ResponseEntity<Set<String>> handleConstraintViolation(ConstraintViolationException e) {
Set<ConstraintViolation<?>> constraintViolations = e.getConstraintViolations();
Set<String> messages = new HashSet<>(constraintViolations.size());
messages.addAll(constraintViolations.stream()
.map(constraintViolation -> String.format("%s value '%s' %s", constraintViolation.getPropertyPath(),
constraintViolation.getInvalidValue(), constraintViolation.getMessage()))
.collect(Collectors.toList()));
return new ResponseEntity<>(messages, HttpStatus.BAD_REQUEST);
}
Вы можете получить недопустимое значение (имя) с помощью
constraintViolation.getInvalidValue()
Вы можете получить доступ к имени свойства 'name' с помощью
constraintViolation.getPropertyPath()
Ответ 2
используйте этот метод (например, экземпляр ConstraintViolationException):
Set<ConstraintViolation<?>> set = ex.getConstraintViolations();
List<ErrorField> errorFields = new ArrayList<>(set.size());
ErrorField field = null;
for (Iterator<ConstraintViolation<?>> iterator = set.iterator();iterator.hasNext(); ) {
ConstraintViolation<?> next = iterator.next();
System.out.println(((PathImpl)next.getPropertyPath())
.getLeafNode().getName() + " " +next.getMessage());
}
Ответ 3
Если вы проверите возвращаемое значение getPropertyPath()
, то обнаружите его Iterable<Node>
, а последним элементом итератора является имя поля. У меня работает следующий код:
// I only need the first violation
ConstraintViolation<?> violation = ex.getConstraintViolations().iterator().next();
// get the last node of the violation
String field = null;
for (Node node : violation.getPropertyPath()) {
field = node.getName();
}
Ответ 4
У меня была такая же проблема, но также получил "sayHi.arg0" из getPropertyPath. Я решил добавить сообщение в аннотации NotNull, поскольку они были частью нашего публичного API. Как:
@NotNull(message = "timezone param is mandatory")
вы можете получить сообщение, вызвав
ConstraintViolation # GetMessage()