Java 如何定制Bean验证ConstraintViolationException?

Java 如何定制Bean验证ConstraintViolationException?,java,spring,rest,bean-validation,Java,Spring,Rest,Bean Validation,我想验证Spring@RestController中端点的@RequestBody。所以我创建了这样一个方法: @RequestMapping(value = ...) public ResponseEntity<...> myPostMethod(@RequestBody MyBean myBean) throws Exception { 这就是所有验证逻辑发生的地方。当它失败时,isValid返回false,我可以使用该contextparam以我想要的方式构建验证错误消息。此

我想验证Spring
@RestController
中端点的
@RequestBody
。所以我创建了这样一个方法:

@RequestMapping(value = ...)
public ResponseEntity<...> myPostMethod(@RequestBody MyBean myBean) throws Exception {
这就是所有验证逻辑发生的地方。当它失败时,
isValid
返回
false
,我可以使用该
context
param以我想要的方式构建验证错误消息。此外,
myPostMethod
也会自动失败(因为我自己不会抛出它)
MethodArgumentNotValidException
,我将在全局处理程序上捕获该异常,以呈现通用的
响应属性。一切正常问题是:如何不仅自定义验证错误消息,而且自定义整个
ConstraintViolationException
?我想在异常中提供更多数据(来自我的业务域),以便在响应正文json中呈现。

我找到了答案:


让我们假设要传递的附加参数名为
myParam

首先,在约束接口中声明该参数的访问器

public @interface MyConstraint {

    String message();

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};

    String myParam() default "some.value";
}
如果从异常处理程序捕获
ConstraintViolationException
,并希望从异常本身访问参数:

要从
ConstraintViolationException
中检索
ConstraintViolation
,请使用:

constraintViolationException.getConstraintViolations();
然后,要从约束碰撞中检索动态有效载荷,请执行以下操作:

(Map) ((ConstraintViolationImpl) constraintViolation).getDynamicPayload(Map.class))
public class MyValidator implements ConstraintValidator<MyConstraint, String> {

    private String myParam;


    @Override
    public void initialize(OpcoConstraint parameters) {
        code = parameters.myParam();
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {

        HibernateConstraintValidatorContext hibernateContext = context.unwrap(
                HibernateConstraintValidatorContext.class
        );

        // you can pass any object as the payload
        hibernateContext.withDynamicPayload(Map.of("myParam", myParam));
    }
}
constraintViolationException.getConstraintViolations();
(Map) ((ConstraintViolationImpl) constraintViolation).getDynamicPayload(Map.class))