如何使用我的 .properties 文件中的自定义消息,但使用@Size注释提供的参数



这应该是一个简单的问题,但我找不到直接的解决方案。

我正在使用 Spring 消息资源从 .properties 文件提供系统上的所有文本。对于国际化问题,我需要它,并且无法使用来自 Spring 的默认消息。

问题是这样的:

我的 .properties 文件中有以下行:

validator_invalid_state_name=Invalid name ({min}, {max})

验证代码为:

@Size( min=3, max=5, message="validator_invalid_state_name" )
public String name;

但是,当向字段发送无效值时,消息为:

"无效名称 ({min}, {max})"而不是"无效名称 (3, 5)"。

我尝试了几种解决方案但没有成功,例如:

@Size( min=3, max=5, message="{validator_invalid_state_name}" )
@Size( min=3, max=5, message="${validator_invalid_state_name}" )
@Size( min=3, max=5, message="Size.name" ) // with "Size.name=Invalid name ({min}, {max})" in my .properties file
@Size( min=3, max=5, message="{Size.name}" ) //idem

但是如果我只使用

@Size( min=3, max=5 )

然后,我收到来自 Spring 的默认消息(我不想使用)。我需要的非常简单:使用我自己的自定义 .properties 文件中的消息,但使用 @Size 注释提供的参数。

有什么建议吗?

提前谢谢你。

访问密钥的正确语法是

@Size( min=3, max=5, message="{validator_invalid_state_name}" )

然而,问题是,在默认设置中,密钥查找不会针对您的 custom.properties 完成,而是针对 Spring 的 ValidationMessages.properties。因此,启动和运行的最快方法是创建一个 ValidationMessages.properties(以及 18n 等效项)并添加您的密钥,例如

validator_invalid_state_name=Invalid name ({min}, {max})

这是最简单的解决方案,没有配置难题。

现在,由于您希望从属性文件中提供此功能,因此它是可行的,但是您必须找到适当的配置。对于Spring 4.x,这将是正确的xml和java配置。

Java Config

@Bean(name = "messageSource")
public MessageSource messageSource()
{
    ReloadableResourceBundleMessageSource bean = new ReloadableResourceBundleMessageSource();
    bean.setBasename("classpath:text");
    bean.setDefaultEncoding("UTF-8");
    return bean;
}
@Bean(name = "validator")
public LocalValidatorFactoryBean validator()
{
    LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
    bean.setValidationMessageSource(messageSource());
    return bean;
}
@Override
public Validator getValidator()
{
    return validator();
}

XML 配置

    <annotation-driven validator="validator">
    <!--i18n filtering-->
    <beans:bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <beans:property name="basenames">
            <beans:list>
                <beans:value>classpath:custom</beans:value>
            </beans:list>
        </beans:property>
        <beans:property name="defaultEncoding" value="UTF-8"/>
    </beans:bean>
  <beans:bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
        <beans:property name="validationMessageSource" ref="messageSource"/>
    </beans:bean>

对于Spring mvc 3.x,你不会在LocalValidatorFactoryBean上找到validationMessageSource属性,为此你必须创建消息插值器,并设置它。您在此线程 http://forum.spring.io/forum/spring-projects/web/78675-jsr-303-validation-spring-mvc-and-messages-properties 中有一个示例。希望对你有帮助

如果您使用的是具有 JPA 持久性支持的 Spring 引导,则此解决方案不起作用。系统抛出;

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name '(inner bean)#427e977': Cannot resolve reference to bean 'entityManagerFactory' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory': Post-processing of FactoryBean's singleton object failed; nested exception is java.lang.IllegalStateException: ApplicationEventMulticaster not initialized - call 'refresh' before multicasting events via the context: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@4f430ea5: startup date [Fri Sep 18 09:33:54 EEST 2015]; root of context hierarchy
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:359)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:108)
at org.springframework.beans.factory.support.ConstructorResolver.resolveConstructorArguments(ConstructorResolver.java:634)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:444)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1119)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1014)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:476)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveInnerBean(BeanDefinitionValueResolver.java:299)
... 96 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory': Post-processing of FactoryBean's singleton object failed; nested exception is java.lang.IllegalStateException: ApplicationEventMulticaster not initialized - call 'refresh' before multicasting events via the context: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@4f430ea5: startup date [Fri Sep 18 09:33:54 EEST 2015]; root of context hierarchy
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:116)
at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1523)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:314)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:351)
... 104 more
Caused by: java.lang.IllegalStateException: ApplicationEventMulticaster not initialized - call 'refresh' before multicasting events via the context: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@4f430ea5: startup date [Fri Sep 18 09:33:54 EEST 2015]; root of context hierarchy
at org.springframework.context.support.AbstractApplicationContext.getApplicationEventMulticaster(AbstractApplicationContext.java:344)
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:331)
at org.springframework.boot.autoconfigure.orm.jpa.DataSourceInitializedPublisher.postProcessAfterInitialization(DataSourceInitializedPublisher.java:69)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:422)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.postProcessObjectFromFactoryBean(AbstractAutowireCapableBeanFactory.java:1719)
at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:113)
... 108 more

(我认为正在发生的事情是,我们不知何故忽略了spring.datasource语句所在的application.properties,但我不知道为什么!我设法让它与以下 java 配置一起工作,删除上面主从给出的 messageSource 的用户定义,并注入 SpringBoot 提供的 messageSource。这现在从消息.属性而不是验证消息.属性填充我的验证消息

@SpringBootApplication
public class MyApplication extends WebMvcConfigurerAdapter {
@Autowired
MessageSource messageSource;
public static void main(String[] args) {
    SpringApplication.run(MyApplication.class, args);
}
    @Bean(name = "validator")
public LocalValidatorFactoryBean validator()
{
    LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
    bean.setValidationMessageSource(messageSource);
    return bean;
}
@Override
public Validator getValidator()
{
    return validator();
}
}

最新更新