当前位置: 首页 > 面试题库 >

如何使用Hibernate Validator动态解析消息参数?

谭坚诚
2023-03-14
问题内容

我正在使用Hibernate Validator,并且想在错误消息中解析类别的名称。考虑以下简单情况:

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.

假设我有一个HazardousCategoryConstraint的有效实现。验证器根据受限名称列表检查每个类别的名称。当我调用validate(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) {
        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();
    }

}

@测试

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());
        }
    }

输出量

s is a product in the hazardous category list.


 类似资料:
  • 问题内容: 这可能很简单,但是我在文档中找不到任何内容,因此使用谷歌搜索没有帮助。我正在尝试定义一个状态,在该状态下,我需要在服务器上单击以提取所需数据的URL取决于状态URL参数。简而言之,类似于: 上面的方法不起作用。我尝试注入以获取所需的参数,但是没有运气。什么是正确的方法? 问题答案: 您关系密切。如果使用ui-router,请改用。该代码对我有用:

  • 问题内容: 我有动态JSON,下面是示例:http : //pastebin.com/QMWRZTrD 如何使用翻新解析? 我没有生成POJO类,因为我有诸如“ 5411”和“ 5412”之类的动态字段。 编辑 : 我通过使用Map来解决它,因为第一个值始终是整数,第二个是对象列表。 问题答案: 如果使用随机键,则可以用来序列化和反序列化。

  • 问题内容: 因此,我使用GSON来从API解析JSON,并被困在如何解析数据中的动态字段上。 这是查询返回的JSON数据的示例: 我当前处理单个静态值的方式是使用一个类: 然后我可以简单地使用GSON来解析它: 我知道这对子数据有效,因为我可以查询并获得单个条目并非常轻松地解析该条目,但是为数组中每个值给出的随机整数值呢?(即30655845和2868874) 有什么帮助吗? 问题答案: 根据GS

  • 我正在尝试从Cisco IOS配置解析以下命令:

  • 我正在使用Spring Boot 2.1.8构建一个项目,我的POM中有spring-boot-starter-web,我可以看到Maven将hibernate-validator 6.0.17拉到类路径上。 我在资源文件夹中有我的消息,它们似乎可以正确地查找,这样当我更改区域设置时,Spring就可以从正确的文件中加载消息。 my@RESTController中的相关方法采用@Valid和@Re

  • 问题内容: 我正在尝试使用Go解析YAML文件。问题在于YAML文件中的密钥可能并不总是相同。这是为了进行API版本控制,以便用户可以定义他们支持的版本。例如V1,V2,V3等。它们不需要按顺序排列,并且可以省略它们不支持的版本,例如V0,V2,V5等。 这是最高层,我还没有从结构内部弄清楚如何做到这一点。 问题答案: 首先,您尝试将根解析为,但其实际类型为。其次,如果要保留该类型结构,则需要一个