Get field name when javax.validation.ConstraintVio

2020-06-08 07:51发布

When the PathVariable 'name' doesn't pass validation a javax.validation.ConstraintViolationException is thrown. Is there a way to retrieve the parameter name in the thrown 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;
}

5条回答
相关推荐>>
2楼-- · 2020-06-08 08:07

use this method(ex is ConstraintViolationException instance):

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楼-- · 2020-06-08 08:08

The following Exception Handler shows how it works :

@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);

}

You can access the invalid value (name) with

 constraintViolation.getInvalidValue()

You can access the property name 'name' with

constraintViolation.getPropertyPath()
查看更多
放我归山
4楼-- · 2020-06-08 08:13

To get only parameter name which is last part of the Path.

violations.stream()
                .map(violation -> String.format("%s value '%s' %s", StreamSupport.stream(violation.getPropertyPath().spliterator(), false).reduce((first, second) -> second).orElse(null),
                        violation.getInvalidValue(), violation.getMessage())).collect(Collectors.toList());
查看更多
家丑人穷心不美
5楼-- · 2020-06-08 08:18

If you inspect the return value of getPropertyPath(), you'll find it'a Iterable<Node> and the last element of the iterator is the field name. The following code works for me:

// 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();
}
查看更多
戒情不戒烟
6楼-- · 2020-06-08 08:19

I had the same problem but also got "sayHi.arg0" from getPropertyPath. I chose to add a message to NotNull annotations since they were part of our public API. Like:

 @NotNull(message = "timezone param is mandatory")

you can obtain the message by calling

ConstraintViolation#getMessage()

查看更多
登录 后发表回答