我想从使用Spring Beans的java应用程序加载属性,通过数据库,但是我需要从文件加载到数据库的连接属性。
所以我想要的是以下内容:
最后,可以从两个来源访问已加载的属性。
我尝试了以下方式。
应用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
如果我选择初始化bean&#34; dataSourceOracleRead&#34;在application-context.xml中,访问数据库工作正常,而不是通过文件。
<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>
我想当我设置第二个&#34; PropertyPlaceholderConfigurer&#34;我通过第一个(属性文件)自动丢失已经收费的属性。
如果我有两个&#34; PropertyPlaceholderConfigurer&#34;其中一个加载其中一个文件,第二个加载第二个文件,我不会通过第一个&#34; PropertyPlaceholderConfigurer&#34;来丢失收费属性。
Ps:我使用的是弹簧版本3.1.2
答案 0 :(得分:0)
如果您使用的是Spring 3.1,请考虑使用PropertySourcePlaceholderConfigurer,它与ConfigurableEnvironment结合使用,可以动态添加PropertySources
。
这样,您只能定义一个placeholderConfigurer
,从属性文件初始化,然后从数据库加载其他属性。
另外,请检查其他question,它看起来与您想要的非常相似但使用不同的方法。