如何用Hibernate Validator动态解析消息参数? [英] How do I dynamically resolve message parameters with Hibernate Validator?

查看:1320
本文介绍了如何用Hibernate Validator动态解析消息参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Hibernate Validator,并希望在错误消息中解析类别的名称。考虑一下这个简单的场景:

  public class Category {
private String name;
}

public class Product {
@HazardousCategoryConstraint(message ={haz.cat.error})
private Category category;
私人字符串名称;
}

public class InventoryReport {
@Valid
private List< Product>产品;
}


ValidationMessages.properties
haz.cat.error = {name}是危险类别列表中的产品。

假设我有一个HazardousCategoryConstraint的工作实现。验证器根据受限名称列表检查每个类别的名称。当我调用验证(InventoryReport)时,我得到了我期望的错误数,除了它们是相同的字符串。我希望将类别的名称解析为每封邮件。有人可以给我一个如何动态解析参数的例子,或者告诉我如何去解决这个问题?

解决方案

IMO,简单的解决方案是创建 javax.validation.MessageInterpolator 的自定义实现。将主要工作委托给Hibernate Validator的 ResourceBundleMessageInterpolator ,并在 CustomMessageInterpolator 中完成所需的替换工作。

  public class CustomMessageInterpolator extends org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator {

private static final Pattern MESSAGE_PARAMETER_PATTERN = Pattern.compile( (\\ {[^ \\}] +?\\}));

@Override
public String interpolate(String message,Context context){
字符串resolvedMessage = super.interpolate(message,context);
resolvedMessage = replacePropertyNameWithPropertyValues(resolvedMessage,context.getValidatedValue());
返回resolvedMessage;
}

private String replacePropertyNameWithPropertyValues(String resolvedMessage,Object validatedValue){
Matcher matcher = MESSAGE_PARAMETER_PATTERN.matcher(resolvedMessage);
StringBuffer sb = new StringBuffer(); (matcher.find()){
String parameter = matcher.group(1);

while(matcher.find

String propertyName = parameter.replace({,);
propertyName = propertyName.replace(},);

PropertyDescriptor desc = null;
尝试{
desc = new PropertyDescriptor(propertyName,validatedValue.getClass());
} catch(IntrospectionException ignore){
matcher.appendReplacement(sb,parameter);
继续;
}

尝试{
Object propertyValue = desc.getReadMethod()。invoke(validatedValue);
matcher.appendReplacement(sb,propertyValue.toString());
} catch(Exception ignore){
matcher.appendReplacement(sb,parameter);
}
}
matcher.appendTail(sb);
return sb.toString();
}

}

@Test < >

  public void validate(){
Configuration<?>配置= Validation.byDefaultProvider()。configure();
ValidatorFactory validatorFactory = configuration.messageInterpolator(new CustomMessageInterpolator())。buildValidatorFactory();
Validator validator = validatorFactory.getValidator();

产品p =新产品();
类别cat = new Category();
cat.setName(s); //假定指定名称无效
p.setCategory(cat);

Set< ConstraintViolation< Product>> violation = validator.validate(p); (ConstraintViolation< Product>违规:违规){
System.out.println(violation.getMessage());
}
}

输出

  s是危险类别列表中的产品。 


I'm using Hibernate Validator and would like to resolve the category's name in an error message. Consider this simple scenario:

public class Category {
    private String name;
}

public class Product {
    @HazardousCategoryConstraint(message = "{haz.cat.error}")
    private Category category;
    private String name;
}

public class InventoryReport {
    @Valid
    private List<Product> products;
}


ValidationMessages.properties
haz.cat.error={name} is a product in the hazardous category list.

Assume that I have a working implementation of HazardousCategoryConstraint. The validator checks each Category's name against a list of restricted names. When I call validate(InventoryReport) I get the number of errors I expect except they are the same string. I'd like to see the Category's name resolved into each message. Can someone point me to an example of how to resolve parameters dynamically, or show me how to?

解决方案

IMO, the simple solution is to create custom implementation of javax.validation.MessageInterpolator. Delegate the main work to Hibernate Validator's ResourceBundleMessageInterpolator and do the required replacement work in CustomMessageInterpolator.

public class CustomMessageInterpolator extends org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator {

    private static final Pattern MESSAGE_PARAMETER_PATTERN = Pattern.compile( "(\\{[^\\}]+?\\})" );

    @Override
    public String interpolate(String message, Context context) {
        String resolvedMessage = super.interpolate(message, context);
        resolvedMessage = replacePropertyNameWithPropertyValues(resolvedMessage, context.getValidatedValue());
        return resolvedMessage;
    }

    private String replacePropertyNameWithPropertyValues(String resolvedMessage, Object validatedValue) {
        Matcher matcher = MESSAGE_PARAMETER_PATTERN.matcher( resolvedMessage );
        StringBuffer sb = new StringBuffer();

        while ( matcher.find() ) {
            String parameter = matcher.group( 1 );

            String propertyName = parameter.replace("{", "");
            propertyName = propertyName.replace("}", "");

            PropertyDescriptor desc = null;
            try {
                desc = new PropertyDescriptor(propertyName, validatedValue.getClass());
            } catch (IntrospectionException ignore) {
                matcher.appendReplacement( sb, parameter );
                continue;
            }

            try {
                Object propertyValue = desc.getReadMethod().invoke(validatedValue);
                matcher.appendReplacement( sb, propertyValue.toString() );
            } catch (Exception ignore) {
                matcher.appendReplacement( sb, parameter );
            }
        }
        matcher.appendTail( sb );
        return sb.toString();
    }

}

@Test

public void validate() {
        Configuration<?> configuration = Validation.byDefaultProvider().configure();
        ValidatorFactory validatorFactory = configuration.messageInterpolator(new CustomMessageInterpolator()).buildValidatorFactory();
        Validator validator = validatorFactory.getValidator();

        Product p = new Product();
        Category cat = new Category();
        cat.setName("s"); //assume specified name is invalid
        p.setCategory(cat);

        Set<ConstraintViolation<Product>> violations = validator.validate(p);
        for(ConstraintViolation<Product> violation : violations) {
            System.out.println(violation.getMessage());
        }
    }

Output

s is a product in the hazardous category list.

这篇关于如何用Hibernate Validator动态解析消息参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆