4

我用来在一个公共库中收集我所有的验证约束。在 jar 的根目录中,我放置了一个ValidationMessages_it.properties文件。一切正常,如果我将此库放入 jsf 2 war 项目中,所有验证消息都会正确显示。ValidationMessages_it.properties但是,如果我也将另一个放在战争神器中,则会出现问题。在这种情况下,{library.message_key}会显示一个字符串。

我认为 Bean Validation 在战争中找到了正确的属性文件,并没有考虑到库中的那个。我该如何解决?

例子

我有一个包含自定义约束的库 commons.jar。为了为这些约束设置消息,我ValidationMessages_it.properties在这个库的根目录中添加了一个

commons.jar
    |
    + library
    |   |
    |   + CustomConstraint.class
    |
    + ValidationMessages_it.properties

ValidationMessages_it.properties

library.custom=Questo è l'errore di cui parlavo

自定义约束.java

@Pattern( regexp = "[a-z]", message = "{library.custom}" )
@Constraint( validatedBy = {} )
@Documented
@Target( { ElementType.METHOD, ElementType.FIELD } )
@Retention( RetentionPolicy.RUNTIME )
public @interface CustomConstraint {
    String message() default "C'è un errore";

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

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

PS: 请注意,消息键位于@Pattern 注释而不是 message() 上,这似乎是一个错误,但否则它永远不会起作用!

之后我想commons.jar在我的网络应用程序项目(jsf/mojarra 2.1)中使用它。一切正常。显示的错误消息是“Questo è l'errore di cui parlavo”。

但是现在假设我在我的 webapp 中定义了新的验证约束,所以我想通过添加一个ValidationMessages_it.propertiesinWEB-INF/classes文件夹来为这些约束提供翻译。在这种情况下,显示的错误消息是“{library.custom}”

所以我认为BV(或jsf?)在战争中找到了捆绑并且没有考虑到commons.jar中的那个。它在文件夹中找不到密钥library.custom,因此按字面意思返回。ValidationMessages_it.propertiesWEB-INF/classes{library.custom}

示例 2

基于共享库中的 Bean Validation 约束,我的包结构似乎是正确的。我上传了一个简单的网络应用程序来显示问题:

我在 Glassfish 3.1.2、JBoss AS 7.1.1、Geronimo 3.0.0 中测试了 webapp

Glassfish 和 JBoss 具有相同的行为。在 Geronimo 中它工作得更好一些。

4

2 回答 2

4

默认情况下,如果有多个 JAR/WAR/etc。文件包含一个具有完全相同名称的资源包文件,其中只有一个将用于验证器消息。这是这里的问题:commons.jar应用程序 WAR 都包含一个具有 name 的资源ValidationMessages_it.properties

2015 年 7 月发布的 Hibernate Validator 5.2 增加了对聚合来自不同 JAR 文件的所有同名资源包的支持。默认情况下禁用此功能,并且可以在org.hibernate.validator.resourceloading.PlatformResourceBundleLocator中进行配置。

例子:

PlatformResourceBundleLocator resourceBundleLocator =
    new PlatformResourceBundleLocator(ResourceBundleMessageInterpolator.USER_VALIDATION_MESSAGES, null, true);

Validator validator = Validation.byProvider(HibernateValidator)
    .configure()
    .messageInterpolator(new ResourceBundleMessageInterpolator(resourceBundleLocator))
    .buildValidatorFactory()
    .getValidator();

使用 Java 配置的 Spring 项目的等效代码:

@Bean
public LocalValidatorFactoryBean validator() {
    PlatformResourceBundleLocator resourceBundleLocator =
            new PlatformResourceBundleLocator(ResourceBundleMessageInterpolator.USER_VALIDATION_MESSAGES, null, true);

    LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
    factoryBean.setMessageInterpolator(new ResourceBundleMessageInterpolator(resourceBundleLocator));
    return factoryBean;
}
于 2015-10-30T18:31:55.497 回答
3

我认为您的解决方案是提到的AggregateResourceBundleLocator。但是,属性文件不能使用相同的名称。在内部调用ResourceBundle#getBundle,它确实返回一个ResourceBundle。没有组合/合并具有相同名称的属性文件的概念。

编辑 1

关于这样做的标准方式 - 不幸的是没有。Bean Validation 1.1 ( BVAL-252 ) 存在一个未解决的问题,以解决提供约束库的能力,但尚未做出任何决定,消息插值也需要解决。也许你对它应该如何工作有一个想法。如果是这样,请将您的建议提供给专家组。检查 beanvalidation.org

于 2012-07-26T14:22:51.910 回答