【问题标题】:MessageSource and PropertyPlaceholderConfigurer cannot load messages but with classpath*MessageSource 和 PropertyPlaceholderConfigurer 无法加载消息,但使用类路径*
【发布时间】:2011-09-27 19:34:48
【问题描述】:

我的 applicationContext.xml 在路径中:

src/main/resources/META-INF/spring

属性文件在路径中:

src/main/resources/messages

我在 web.xml 中加载 spring 上下文如下:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:META-INF/spring/applicationContext.xml</param-value>
</context-param>

当我如下配置 MessageSource 和 PropertyPlaceholderConfigurer 时:

<bean id="propertyPlaceholderConfigurer"
      class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
        <list>
            <value>classpath:messages/apps.properties</value>        
        </list>
    </property>
</bean>

<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basenames">
        <list>
            <value>classpath:messages/ValidationMessages</value>
            <value>classpath:messages/app</value>
        </list>
    </property>
    <property name="defaultEncoding" value="UTF-8"/>
</bean>

它们都不起作用,只有当我将 classpath 更改为 classpath* 时才起作用 任何想法为什么?

【问题讨论】:

  • 你的意思是它不起作用,当你启动你的服务器时是否有某种错误信息?
  • 你们是同一个jar的属性吗?你试过classpath:/messages/apps.properties。注意messages之前的正斜杠
  • @Jsword:在 ClassPathResource.class 中设置断点(在构造函数中)并以调试模式启动 servlet 容器。然后,当 Spring 为这些找不到的文件创建 Resource 对象时,检查正在使用哪个 ClassLoader,哪个 Path 和哪个 Class 用于解析。 @tolitius:当使用classpath: 方案时,Spring 无论如何都会剥离前导斜线。请参见 ClassPathResource(String, ClassLoader) 构造函数。

标签: spring jakarta-ee classpath


【解决方案1】:

来自Spring documentation

4.7.2.2 类路径*:前缀

[...] 位置字符串可以使用特殊的classpath*: 前缀:[...]

这个特殊前缀指定所有匹配给定名称的类路径资源必须被获取[...],然后合并以形成最终的应用程序上下文定义。

您确定您的 CLASSPATH 上没有其他 messages/apps.properties 文件巧合地优先并覆盖您的文件吗?此描述表明,当使用 * 时,您可能会合并多个相同命名的文件。

你可以通过调用来检查这个:

SomeClass.class.getClassLoader().getResources("/messages/apps.properties");

?

【讨论】:

  • 感谢反馈,但 url 必须以不带斜线开头,结果枚举只包含 target/classes/messages 中的一个文件,你怎么看?
  • 对不起,这是我唯一的猜测,因此没有回应。
【解决方案2】:

看看这个出色的article for classpath v classpth* 在 spring 资源加载方面的差异,我在测试中对您的问题进行了一些测试,无论我使用的是 classpath 还是 classpath*

我在这里列出了关于我所做的测试的代码

  • 我创建了一个这样的目录结构(src/main/resource下的META-INF/spring)放置context.xml
  • 我在这里列出完整的 context.xml

       <?xml version="1.0" encoding="UTF-8"?>
         <beans xmlns="http://www.springframework.org/schema/beans"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
            xsi:schemaLocation="http://www.springframework.org/schema/beans                http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
    http://www.springframework.org/schema/context   http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    
       <bean id="propertyPlaceholderConfigurer"
                 class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="locations">
            <list>
                <value>classpath:messages/apps.properties</value>
            </list>
        </property>
      </bean>
    
        <bean class="prasanna.service.TestBean">
           <property name="appName" value="${appname}"></property>
         </bean>
    
    <bean id="messageSource"  class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basenames">
         <list>
           <value>classpath:messages/ValidationMessages</value>
               <value>classpath:messages/apps</value>
           </list>
       </property>
        <property name="defaultEncoding" value="UTF-8"/>
    </bean>
        </beans>
    
  • apps.properties 列表

     appname=spring mvc app
    
  • ValidationMessages.properties 的列表

      error.name=Invalid name
    
  • TestBean 比较简单

        public class TestBean 
        {
            private String appName;
    
            public String getAppName() {
                return appName;
            }
    
            public void setAppName(String appName) {
                this.appName = appName;
            }
    
        }
    
  • 我正在使用一个简单的 java 类来加载属性文件并读取它们

    public class LoadContext 
    {
        public static void main(String[] args) 
        {
            ApplicationContext ctx = new ClassPathXmlApplicationContext(new String[]{"classpath:META-INF/spring/context.xml"});
            ReloadableResourceBundleMessageSource msgs = ctx.getBean(ReloadableResourceBundleMessageSource.class);
    
                  TestBean testBean = ctx.getBean(TestBean.class);
        Assert.assertTrue(testBean.getAppName().equals("spring mvc app"));
    
            String msg = msgs.getMessage("appname", new Object[]{new DefaultMessageSourceResolvable("appname")}, null);
            System.out.println(" "+ msg);
    
            String msg2 = msgs.getMessage("error.name", new Object[]{new DefaultMessageSourceResolvable("error.name")}, null);
            System.out.println(" "+ msg2);
        }
    
    }
    

【讨论】:

    猜你喜欢
    • 2021-04-21
    • 1970-01-01
    • 2015-06-25
    • 1970-01-01
    • 1970-01-01
    • 2016-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多