使用带有UTF-8的Hibernate验证器进行Vaadin Bean验证

时间:2016-01-18 21:42:44

标签: spring utf-8 vaadin7 hibernate-validator

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

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

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

2 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

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

编辑:关于如何覆盖子类化的评论中的问题后我意识到,从版本7.5.9开始,这部分Vaadin API的当前状态,我无法做到典雅。既然我们不能优雅地做到这一点,我们可以通过反射将快速和肮脏的方式做到这一点,将这个hack实现为弹簧组件:

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

}