Hibernate Validator、自定义 ResourceBundleLocator 和 Spring

发布于 2024-10-02 12:47:55 字数 289 浏览 5 评论 0原文

我正在尝试覆盖休眠验证 4.1 中的默认 ResourceBundleLocator。到目前为止,它工作得很好,但其使用的唯一示例包括用于实例化 ValidationFactory 的 java 代码。

当使用 Spring 的 Web 应用程序时,会自动配置休眠验证(只有合适的休眠验证 *.jar 文件应该存在,并且会自动使用)。在这种情况下我该如何替代 ResourceBundleLocator?我没有在任何属性或 applicationContext.xml 文件中看到任何指定自定义 ResourceBundleLocator 的方法。

I'm trying to override default ResourceBundleLocator in hibernate validation 4.1. So far it works perfectly, but the only examples of its usage include java code to instantiate ValidationFactory.

When using a web application with spring hibernate validation is automatically configured (only the suitable hibernate validation *.jar file should exist and it is automatically used). How can i substitute ResourceBundleLocator in that scenario? I do not see any way of specyfing my custom ResourceBundleLocator in any properties or applicationContext.xml file.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

秋凉 2024-10-09 12:47:55

完成所需工作的神奇方法是 LocalValidatorFactoryBean#setValidationMessageSource(MessageSource messageSource)

首先,该方法的合同:-

<块引用>

指定自定义 Spring MessageSource 来解析验证
消息,而不是依赖
JSR-303 的默认值
“ValidationMessages.properties”包
在类路径中。这可能指的是
Spring 上下文是共享的
“messageSource”bean,或某些
特殊的 MessageSource 设置
仅用于验证目的。

注意:此功能需要 Hibernate
验证器 4.1 或更高版本
类路径。尽管如此,您仍然可以使用
不同的验证提供者但是
Hibernate 验证器
资源包消息插值器
课程期间必须可以访问
配置。

指定此属性或
“messageInterpolator”,而不是两者。如果
你想建立一个定制的
MessageInterpolator,考虑推导
来自 Hibernate 验证器的
ResourceBundleMessageInterpolator 和
走过一个春天
消息源资源包定位器
构建插值器时。

您可以通过调用此方法来指定自定义 message.properties(或 .xml)...像这样...

my-beans.xml

<bean name="validator"
    class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
    <property name="validationMessageSource">
        <ref bean="resourceBundleLocator"/>
    </property>
</bean>

<bean name="resourceBundleLocator" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basenames">
        <list>
            <value>META-INF/validation_errors</value>
        </list>
    </property>
</bean>

validation_errors.properties

javax.validation.constraints.NotNull.message=MyNotNullMessage

Person.java

    class Person {
    private String firstName;
    private String lastName;

    @NotNull
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}

BeanValidationTest.java

    public class BeanValidationTest {

    private static ApplicationContext applicationContext; 

    @BeforeClass
    public static void initialize() {
        applicationContext = new ClassPathXmlApplicationContext("classpath:META-INF/spring/webmvc-beans.xml");
        Assert.assertNotNull(applicationContext);
    }

    @Test
    public void test() {
        LocalValidatorFactoryBean factory = applicationContext.getBean("validator", LocalValidatorFactoryBean.class);
        Validator validator = factory.getValidator();
        Person person = new Person();
        person.setLastName("dude");
        Set<ConstraintViolation<Person>> violations = validator.validate(person);
        for(ConstraintViolation<Person> violation : violations) {
            System.out.println("Custom Message:- " + violation.getMessage());
        }
    }

}

输出: 自定义消息:- MyNotNullMessage

The magic method that does the required job is LocalValidatorFactoryBean#setValidationMessageSource(MessageSource messageSource).

First of all, contract of the method:-

Specify a custom Spring MessageSource for resolving validation
messages, instead of relying on
JSR-303's default
"ValidationMessages.properties" bundle
in the classpath. This may refer to a
Spring context's shared
"messageSource" bean, or to some
special MessageSource setup for
validation purposes only.

NOTE: This feature requires Hibernate
Validator 4.1 or higher on the
classpath. You may nevertheless use a
different validation provider but
Hibernate Validator's
ResourceBundleMessageInterpolator
class must be accessible during
configuration.

Specify either this property or
"messageInterpolator", not both. If
you would like to build a custom
MessageInterpolator, consider deriving
from Hibernate Validator's
ResourceBundleMessageInterpolator and
passing in a Spring
MessageSourceResourceBundleLocator
when constructing your interpolator.

You can specify your custom message.properties(or .xml) by invoking this method... like this...

my-beans.xml

<bean name="validator"
    class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
    <property name="validationMessageSource">
        <ref bean="resourceBundleLocator"/>
    </property>
</bean>

<bean name="resourceBundleLocator" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basenames">
        <list>
            <value>META-INF/validation_errors</value>
        </list>
    </property>
</bean>

validation_errors.properties

javax.validation.constraints.NotNull.message=MyNotNullMessage

Person.java

    class Person {
    private String firstName;
    private String lastName;

    @NotNull
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}

BeanValidationTest.java

    public class BeanValidationTest {

    private static ApplicationContext applicationContext; 

    @BeforeClass
    public static void initialize() {
        applicationContext = new ClassPathXmlApplicationContext("classpath:META-INF/spring/webmvc-beans.xml");
        Assert.assertNotNull(applicationContext);
    }

    @Test
    public void test() {
        LocalValidatorFactoryBean factory = applicationContext.getBean("validator", LocalValidatorFactoryBean.class);
        Validator validator = factory.getValidator();
        Person person = new Person();
        person.setLastName("dude");
        Set<ConstraintViolation<Person>> violations = validator.validate(person);
        for(ConstraintViolation<Person> violation : violations) {
            System.out.println("Custom Message:- " + violation.getMessage());
        }
    }

}

Outupt: Custom Message:- MyNotNullMessage

深爱不及久伴 2024-10-09 12:47:55

如果您想混合现有的休眠验证消息和自定义验证消息,这里有一个解决方案:(

<mvc:annotation-driven validator="validator" />
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
    <property name="validationMessageSource" ref="messageSource"/>
</bean>
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basenames" value="i18n,iso-i18n,org.hibernate.validator.ValidationMessages" />
    <property name="useCodeAsDefaultMessage" value="true" />
</bean>

请参阅Web MVC 框架验证部分在 Spring 文档中配置 Bean 验证提供程序

Here is a solution if you want to mix the existing hibernate validation messages and custom validation messages :

<mvc:annotation-driven validator="validator" />
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
    <property name="validationMessageSource" ref="messageSource"/>
</bean>
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basenames" value="i18n,iso-i18n,org.hibernate.validator.ValidationMessages" />
    <property name="useCodeAsDefaultMessage" value="true" />
</bean>

(see Web MVC framework Validation section and Configuring a Bean Validation Provider in Spring documentation)

柒夜笙歌凉 2024-10-09 12:47:55

谢谢@Lu55,根据你的回答我解决了我的问题!

我刚刚转换为 Configuration 类,我在这里发布以防万一其他人需要:

导入详细信息:它对我来说适用于 ReloadableResourceBundleMessageSource,但使用 ResourceBundleMessageSource 则不起作用。我不知道为什么。

@Configuration
public class ErrorConfig {

    @Bean
    public Validator validatorFactory (MessageSource messageSource) {
        LocalValidatorFactoryBean validator =  new LocalValidatorFactoryBean();
        validator.setValidationMessageSource(messageSource);
        return validator;
    }

    @Bean
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource bean = new ReloadableResourceBundleMessageSource();
        bean.addBasenames("classpath:org.hibernate.validator.ValidationMessages","classpath:message");
        bean.setDefaultEncoding("UTF-8");
        return bean;
    }
}

在我的资源文件夹中,我有 message.properties 文件。

Thank you @Lu55, based on your answer I solved my problem!!

I just converted to a Configuration class, and I am posting here just in case anyone else need:

Import detail: it worked for me with ReloadableResourceBundleMessageSource, but it did not work using ResourceBundleMessageSource. I am not sure why.

@Configuration
public class ErrorConfig {

    @Bean
    public Validator validatorFactory (MessageSource messageSource) {
        LocalValidatorFactoryBean validator =  new LocalValidatorFactoryBean();
        validator.setValidationMessageSource(messageSource);
        return validator;
    }

    @Bean
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource bean = new ReloadableResourceBundleMessageSource();
        bean.addBasenames("classpath:org.hibernate.validator.ValidationMessages","classpath:message");
        bean.setDefaultEncoding("UTF-8");
        return bean;
    }
}

Inside my resource folder I have message.properties file.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文