使用 UTF-8 的 Hibernate-validator 验证 Vaadin Bean
Vaadin Bean validation with Hibernate-validator with UTF-8
首先,我是 Vaadin 7 的新手。当我发现 BeanFieldGroup.class 时,我只是在尝试一些 vaadin 演示。如我所见,这 class 将一个字段绑定到一个 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 编码的文件?
默认情况下,读取属性文件时使用 ISO-8859-1 编码。该编码中不可用的字符必须使用 Unicode 转义符(“\u1234”)进行转换,例如使用 native2ascii tool. See this answer 到相关问题以获得更多详细信息。
或者,您可以插入自定义 ResourceBundleLocator
,它使用 UTF-8 编码读取属性。 Hibernate Validator 参考指南 describes how to do this. As a starting point, you could take PlatformResourceBundleLocator 并根据您的要求进行调整。
Vaadin 的 BeanFieldGroup
使用另一个 Vaadin class BeanValidator
进行 JSR-303 验证。如果您在 BeanValidator.getJavaxBeanValidator()
和 getJavaxBeanValidatorFactory()
方法处查看它的源代码,您会发现它正在构建自己的 Validator
和 ValidatorFactory
实例。您需要对其进行 subclass 并使用使用从 Spring 上下文获得的 ValidatorFactory
的方法覆盖 getJavaxBeanValidatorFactory()
方法,该方法已正确设置为使用 Spring 自己的 UTF-8 编码 MessageSource
正如您已经在示例中配置的那样。它还将帮助您进行调试,因为 Spring 的 MessageSource
可以重新加载,这是一个巨大的节省。
编辑: 在关于如何使用 subclassing 覆盖的评论中提出问题后,我意识到 Vaadin 这部分的当前状态 API 从 7.5.9 版本开始,我不能优雅地做到这一点。由于我们不能优雅地做到这一点,我们可以通过反射以 spring 组件实现的这个 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();
}
}
首先,我是 Vaadin 7 的新手。当我发现 BeanFieldGroup.class 时,我只是在尝试一些 vaadin 演示。如我所见,这 class 将一个字段绑定到一个 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 编码的文件?
默认情况下,读取属性文件时使用 ISO-8859-1 编码。该编码中不可用的字符必须使用 Unicode 转义符(“\u1234”)进行转换,例如使用 native2ascii tool. See this answer 到相关问题以获得更多详细信息。
或者,您可以插入自定义 ResourceBundleLocator
,它使用 UTF-8 编码读取属性。 Hibernate Validator 参考指南 describes how to do this. As a starting point, you could take PlatformResourceBundleLocator 并根据您的要求进行调整。
Vaadin 的 BeanFieldGroup
使用另一个 Vaadin class BeanValidator
进行 JSR-303 验证。如果您在 BeanValidator.getJavaxBeanValidator()
和 getJavaxBeanValidatorFactory()
方法处查看它的源代码,您会发现它正在构建自己的 Validator
和 ValidatorFactory
实例。您需要对其进行 subclass 并使用使用从 Spring 上下文获得的 ValidatorFactory
的方法覆盖 getJavaxBeanValidatorFactory()
方法,该方法已正确设置为使用 Spring 自己的 UTF-8 编码 MessageSource
正如您已经在示例中配置的那样。它还将帮助您进行调试,因为 Spring 的 MessageSource
可以重新加载,这是一个巨大的节省。
编辑: 在关于如何使用 subclassing 覆盖的评论中提出问题后,我意识到 Vaadin 这部分的当前状态 API 从 7.5.9 版本开始,我不能优雅地做到这一点。由于我们不能优雅地做到这一点,我们可以通过反射以 spring 组件实现的这个 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();
}
}