Bean验证 - 如何自定义ConstraintViolationException?

时间:2017-08-03 00:23:32

标签: java spring rest bean-validation

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

@RequestMapping(value = ...)
public ResponseEntity<...> myPostMethod(@RequestBody MyBean myBean) throws Exception {

MyBean使用自定义@Constraint进行修饰,其各自的验证逻辑在我创建的ConstraintValidator类上实现。此验证器的方法如下:

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

所有验证逻辑发生的地方。失败时,isValid返回false,我可以使用context参数以我想要的方式构建验证错误消息。此外,myPostMethod也失败了自动(因为我不自己抛出)MethodArgumentNotValidException我将在全局处理程序上捕获以呈现通用ResponseEntity }。这一切都按预期工作。 问题是:我如何自定义验证错误消息,以及整个ConstraintViolationException?我想在异常中提供更多数据(来自我的业务领域)以在响应主体json中呈现。

任何提示都会受到高度赞赏。

2 个答案:

答案 0 :(得分:1)

我找到了答案:

https://docs.jboss.org/hibernate/validator/5.4/api/org/hibernate/validator/constraintvalidation/HibernateConstraintValidatorContext.html#withDynamicPayload-java.lang.Object-

public boolean isValid(MyBean value, ConstraintValidatorContext constraintValidatorContext) {
    HibernateConstraintValidatorContext context = constraintValidatorContext.unwrap(HibernateConstraintValidatorContext.class);

    // (...)

    context.buildConstraintViolationWithTemplate( "{foo}" )
        .withDynamicPayload(anyAdditionalInfo)
        .addConstraintViolation();

    return false;
}

答案 1 :(得分:0)

假设您要传递的其他参数称为myParam

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

public @interface MyConstraint {

    String message();

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

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

    String myParam() default "some.value";
}

然后在ConstraintValidator中,您可以访问以下参数:

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并想从异常本身访问参数:

要从ConstraintViolation中提取ConstraintViolationException,请使用:

constraintViolationException.getConstraintViolations();

然后从ConstraintViolation中检索动态有效载荷:

(Map) ((ConstraintViolationImpl) constraintViolation).getDynamicPayload(Map.class))