【问题标题】:Spring Multiple PropertyPlaceholderConfigurer files and databaseSpring Multiple PropertyPlaceholderConfigurer 文件和数据库
【发布时间】:2014-10-18 21:04:39
【问题描述】:

我想通过数据库从我使用 Spring Beans 的 java 应用程序加载属性,但是我需要从文件加载到数据库的连接属性。

所以我想要的是以下内容:

  1. 加载文件 db.Properties
  2. 初始化数据源的bean
  3. 加载剩余的属性 Base

最后,可以从两个来源访问加载的属性。

我尝试了以下方法。

application-context.xml:

<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<!-- ************************************* -->
<!--        1:  Files Properties Load      -->
<!-- ************************************* -->
<bean id="placeholderPropertiesFile" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
        <list>
            <value>file:./properties/dataBase.properties</value>
            <value>file:./properties/webServicesUserPass.properties</value>
        </list>
    </property>
    <property name="placeholderPrefix" value="$file{" />
    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
    <property name="ignoreUnresolvablePlaceholders" value="true" />
    <property name="order" value="0" />
</bean>



<!-- ************************************* -->
<!--        2:  Data Sources Load          -->
<!-- ************************************* -->  

<bean id="dataSourceOracleRead" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="$file{db.driverClassName}" />
    <property name="url" value="$file{dbRead.url}" />
    <property name="username" value="$file{dbRead.username}" />
    <property name="password" value="$file{dbRead.password}" />
    <property name="poolPreparedStatements" value="true" />
</bean>

<bean id="dataSourceOracleWrite" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="$file{db.driverClassName}" />
    <property name="url" value="$file{dbWrite.url}" />
    <property name="username" value="$file{dbWrite.username}" />
    <property name="password" value="$file{dbWrite.password}" />
    <property name="poolPreparedStatements" value="true" />
</bean>


<!-- ************************************* -->
<!--        3:  Database Properties Load   -->
<!-- ************************************* -->
<bean id="placeholderPropertiesDatabase" class="xxx.xxx.DbPropertyPlaceholderConfigurer" >
    <property name="dt" ref="dataSourceOracleRead" />
    <property name="table" value="CONFIG0" />
    <property name="key" value="I_CODIGO" />
    <property name="value" value="C_VALOR" />

    <property name="placeholderPrefix" value="$db{" />
    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
    <property name="ignoreUnresolvablePlaceholders" value="false" />
    <property name="order" value="1" />
</bean>

DbPropertyPlaceholderConfigurer:

public class DbPropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
    private DataSource dt;
private String key;
private String value;
private String table;

@Override
protected void loadProperties(final Properties props) throws IOException {
    if (null == props) {
        throw new IOException("No properties passed by Spring framework - cannot proceed.");
    }

    String sql = String.format("SELECT %s, %s FROM %s", key, value, table);

    try {
        JdbcTemplate t = new JdbcTemplate(dt);
        t.query(sql, new RowCallbackHandler() {
            @Override
            public void processRow(ResultSet rs) throws SQLException {
                String auxKey = rs.getString(key);
                String auxValue = rs.getString(value);

                if (null == auxKey || null == auxValue) {
                    throw new SQLException("Configuration database contains empty data. Name='" + (auxKey == null ? "" : auxKey)
                            + "', Value='" + (auxValue == null ? "" : auxValue) + "'.");
                }

                props.setProperty(auxKey, auxValue);
            }
        });
    } catch (Exception e) {
        logger.fatal("There is an error in either 'application.properties' or the configuration database.");
        throw new IOException(e);
    }

    if (props.size() == 0) {
        logger.fatal("The configuration database could not be reached or does not contain any properties in '" + table
                + "'.");
    } else {
        logger.info("Application config info loaded from configuration database.");
    }
}

public void setDt(DataSource dt) {
    this.dt = dt;
}

public void setKey(String key) {
this.key = key;
}

public void setValue(String value) {
this.value = value;
}

public void setTable(String table) {
this.table = table;
}
}

错误:

Exception in thread "Main Thread" org.springframework.beans.factory.BeanInitializationException: Could not load properties; nested exception is java.io.IOException: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot load JDBC driver class '$file{db.driverClassName}'
    at org.springframework.beans.factory.config.PropertyResourceConfigurer.postProcessBeanFactory(PropertyResourceConfigurer.java:87)
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:686)
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:661)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:451)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:84)
    at xxx.xxx.xxx.BatchMain.main(BatchMain.java:35)
Caused by: java.io.IOException: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is org.apache.commons.dbcp.SQLNestedException: Cannot load JDBC driver class '$file{db.driverClassName}'
    at xxx.xxx.xxx.xxx.propertiesLoader.DbPropertyPlaceholderConfigurer.loadProperties(DbPropertyPlaceholderConfigurer.java:60)
    at org.springframework.core.io.support.PropertiesLoaderSupport.mergeProperties(PropertiesLoaderSupport.java:161)
    at org.springframework.beans.factory.config.PropertyResourceConfigurer.postProcessBeanFactory(PropertyResourceConfigurer.java:78)
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:686)
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:664)
    ... 4 more

如果我选择在 application-context.xml 中初始化 bean“dataSourceOracleRead”而不是通过文件获取,访问数据库工作正常。

<bean id="dataSourceOracleRead" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:@10.10.10.10:1521:bdtest" />
<property name="username" value="test" />
<property name="password" value="qwerty" />
<property name="poolPreparedStatements" value="true" />
</bean>

我认为当我设置第二个“PropertyPlaceholderConfigurer”时,我会自动丢失已经通过第一个(属性文件)收取的属性。

如果我有两个“PropertyPlaceholderConfigurer”,其中一个加载其中一个文件,第二个加载第二个文件,我不会通过第一个“PropertyPlaceholderConfigurer”丢失收费属性。

Ps:我用的是spring 3.1.2版本

【问题讨论】:

    标签: java spring javabeans


    【解决方案1】:

    如果您使用的是 Spring 3.1,请考虑使用 PropertySourcePlaceholderConfigurer,它与 ConfigurableEnvironment 结合使用,可以让您动态添加 PropertySources

    这样您可以只定义一个placeholderConfigurer,从属性文件初始化,然后从数据库中加载其他属性。

    另外,请检查另一个question,它看起来与您想要的非常相似,但使用了不同的方法。

    【讨论】:

      猜你喜欢
      • 2018-07-21
      • 2014-12-10
      • 1970-01-01
      • 2012-02-18
      • 2011-11-24
      • 2012-06-06
      • 2013-08-21
      • 2010-12-08
      • 1970-01-01
      相关资源
      最近更新 更多