【问题标题】:Vaadin Bean validation with Hibernate-validator with UTF-8带有 UTF-8 的 Hibernate-validator 的 Vaadin Bean 验证
【发布时间】:2016-01-18 21:42:43
【问题描述】:

首先,我是 Vaadin 7 的新手。当我发现 BeanFieldGroup.class 时,我只是在尝试一些 vaadin 演示。正如我所看到的,这个类将一个字段绑定到一个 bean 属性。在 bean 中,属性使用验证约束注释 (JSR 303) 进行注释。在这种情况下,我的 pom.xml 包含休眠验证器依赖项:

<dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>5.1.0.CR1</version>
</dependency>

我制作了 ValidationMessage.properties 文件并放了一些消息,(带有匈牙利字符)并且它已保存为 UTF-8 格式,例如:

validation.NotBlank=Árvíztűrő tükörfúrgép

这里是带注释的 bean 属性:

@NotNull(message = "{validation.NotBlank}")
private String name = null;

我可以看到,当我将字段值更改为 null 时,Vaadin 会显示我之前的约束错误消息,但字符编码错误

另一方面 - 没有 Vaadin,但 Spring,我可以使用下一个简单的公式,其中字符编码适合我(如您所见,我使用 Spring ReloadableResourceBundleMessageSource):

private MessageSource MessageSource(){
    ReloadableResourceBundleMessageSource reloadableResourceBundleMessageSource = new ReloadableResourceBundleMessageSource();
    reloadableResourceBundleMessageSource.setCacheSeconds(5000);
    reloadableResourceBundleMessageSource.setFallbackToSystemLocale(false);
    reloadableResourceBundleMessageSource.setDefaultEncoding("UTF-8");
    Properties properties = new Properties();
    properties.setProperty("fileEncodings", "UTF-8");
    reloadableResourceBundleMessageSource.setFileEncodings(properties);
    reloadableResourceBundleMessageSource.setBasename("classpath:/locales/messages");

    return reloadableResourceBundleMessageSource;
}

@Bean
public LocalValidatorFactoryBean validator(){

    LocalValidatorFactoryBean factory = new LocalValidatorFactoryBean();
    factory.setValidationMessageSource(MessageSource());

    return factory;
}

我的问题是:谁能告诉我正确的解决方案如何配置休眠验证器或 Vaadin 以读取 UTF-8 编码的属性文件?

【问题讨论】:

    标签: spring utf-8 vaadin7 hibernate-validator


    【解决方案1】:

    默认情况下,读取属性文件时使用 ISO-8859-1 编码。该编码中不可用的字符必须使用 Unicode 转义符(“\u1234”)进行转换,例如使用native2ascii 工具。有关更多详细信息,请参阅this answer 相关问题。

    或者,您可以插入一个自定义 ResourceBundleLocator,它使用 UTF-8 编码读取属性。 Hibernate Validator 参考指南describes 如何做到这一点。作为起点,您可以采用 PlatformResourceBundleLocator 并根据您的要求对其进行调整。

    【讨论】:

      【解决方案2】:

      Vaadin 的 BeanFieldGroup 使用另一个 Vaadin 类 BeanValidator 进行 JSR-303 验证。如果您在BeanValidator.getJavaxBeanValidator()getJavaxBeanValidatorFactory() 方法中查看它的源代码,您会发现它正在构建自己的ValidatorValidatorFactory 实例。您需要对其进行子类化并使用使用从 Spring 上下文中获得的 ValidatorFactory 的方法覆盖 getJavaxBeanValidatorFactory() 方法,该方法已正确设置为使用 Spring 自己的 UTF-8 编码 MessageSource,因为您已经在其中配置了它你的例子。它还可以帮助您进行调试,因为 Spring 的 MessageSource 可以重新加载,这是一个巨大的节省。

      编辑:在 cmets 中关于如何用子类化覆盖的问题之后,我意识到在 7.5.9 版的 Vaadin API 的这一部分的当前状态下,我做不到优雅地。由于我们不能优雅地做到这一点,我们可以通过反射来快速而肮脏地做到这一点,并将这个 hack 实现为 spring 组件:

      @Component
      public class VaadinValidationHack implements InitializingBean {
      
          @Autowired
          private ValidatorFactory validatorFactory;
      
          protected void hack() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
              Field field = BeanValidator.class.getDeclaredField("factory");
              if (!field.isAccessible()) {
                  field.setAccessible(true);
              }
              field.set(null, validatorFactory);
          }
      
          @Override
          public void afterPropertiesSet() throws Exception {
              hack();
          }
      
      }
      

      【讨论】:

      • 嗨!谢谢你的回答。我明白了,但我现在不完全明白,如何获取我的 BeanFieldGroup 的 ValidatorFactory 实例。你能举一个简短的例子吗?
      • 我宁愿通过 Bean Validation 的 validation.xml 描述符进行配置,而不是反射黑客。这配置了默认的验证器工厂,它也应该是 Vaadin 选择的。
      • 我评估了您的建议。在validation.xml 中配置自定义ValidationProvider 可能是一种方法,委托给HibernateValidator 直到它由Spring 设置,并从Spring 配置的点委托给Spring 配置的东西。但它仍然不是一个干净的解决方案,因为它在某些时候肯定会违反ValidationProvider 合同,至少当它使用来自 Spring 的配置覆盖基于 API 的配置时。而且这种违反合同的行为会影响所有的应用程序,而反射 hack 只会影响 Vaadin。
      • 您好!我刚刚尝试了您的解决方案。它工作正常!但还有另一个有趣的想法。我尝试使用这个本地: new Local("hu") 和 xxx_hu.properties 文件,但是这对不起作用,另一方面,如果我使用 new Local("hu","HU") 和 xxx_hu_HU.properties 文件,这对工作正常。谢谢你的帮助!!!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-16
      • 2014-02-08
      相关资源
      最近更新 更多