在ApplicationContextInitializer中获取属性文件时无法解析占位符

时间:2017-01-30 06:01:04

标签: java spring spring-mvc

我试图以编程方式为我的Spring MVC应用程序设置.properties文件。例如,如果个人资料为dev,我想要提供database-dev.properties文件。

所以在我的web.xml里面我调用了我的自定义类

<servlet>
  <servlet-name>spring-web</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
  <init-param>
    <param-name>contextInitializerClasses</param-name>
    <param-value>com.galapagos.context.CustomEnvironmentApplicationContextInitializer</param-value>
  </init-param>
</servlet>

自定义类只查看当前配置文件,并将正确的.properties文件添加到环境的属性源

public class CustomEnvironmentApplicationContextInitializer
        implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    private static final Logger logger = LoggerFactory.getLogger(
        CustomEnvironmentApplicationContextInitializer.class);


    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        // Get the environment
        ConfigurableEnvironment environment = applicationContext.getEnvironment();

        try {

            profile = environment.getActiveProfiles()[0];

            String fileName = String.format(
                "database-%s.properties",
                profile);

            ResourcePropertySource resource = 
                new ResourcePropertySource(new ClassPathResource(fileName));

            environment.getPropertySources().addFirst(resource);
            logger.info("Loaded: " + resource);

        } catch (IOException e) {
            logger.warn("Error loading: " + e);
        }

        // Print the list of property sources
        logger.info("ENVIRONMENT: " + environment.getPropertySources());

        // Refresh the context - is this even needed??
        applicationContext.refresh();
    }


}

我可以说上面是有效的,因为它打印出底部的属性来源

2017-01-29 21:43:25 INFO  CustomEnvironmentApplicationContextInitializer:66 - ENVIRONMENT: [class path resource [database-dev.properties],servletConfigInitParams,servletContextInitParams,jndiProperties,systemProperties,systemEnvironment]

每个配置文件的所有database-%{xxx}.properties个文件都非常简单。只是一些JDBC连接属性

jdbc.driverClassName=org.postgresql.Driver
jdbc.url=jdbc:postgresql://localhost:5432/galapagos
jdbc.username=my_user
jdbc.password=

最后在我的servlet定义中,我加载了资源并创建了一个dataSource

<beans:bean
  class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
</beans:bean>

<!-- Database / JDBC -->

<beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
  <beans:property name="driverClassName" value="${jdbc.driverClassName}" />
  <beans:property name="url" value="${jdbc.url}" />
  <beans:property name="username" value="${jdbc.username}" />
  <beans:property name="password" value="${jdbc.password}" />
</beans:bean>

但是我因为无法解决占位符名称而导致失败

Could not resolve placeholder 'jdbc.driverClassName' in string value "${jdbc.driverClassName}"; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'jdbc.driverClassName' in string value "${jdbc.driverClassName}"

环顾各种例子,他们似乎都使用这种设置(here's one)。占位符没有生效的原因是什么?

谢谢!

1 个答案:

答案 0 :(得分:0)

能够在这里自我诊断问题。

我的想法是PropertyPlaceholderConfigurer类会遍历我的环境源并获取我在那里的每个文件。

显然,自从Spring 3.1开始使用新类PropertySourcesPlaceholderConfigurer进行替换。

From the docs for PropertySourcesPlaceholderConfigurer -

  

此类被设计为Spring 3.1应用程序中PropertyPlaceholderConfigurer的一般替代

所以我将我的servlet XML文件更新为 -

<beans:bean
  class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">