我正在尝试从数据库加载属性。我成功了。 但现在的问题是,对于dataSource bean,我想使用占位符。 请参阅applicationProperties.xml文件,然后就可以了解:
<!-- Data Source Bean -->
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${driverClassName}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</bean>
<!-- My Own class for managing properites came from Database -->
<bean class="PropFromDB.PropFromDB.PropertiesUtil" >
<property name="propertiesArray">
<list>
<ref bean="propertiesFromDB" />
</list>
</property>
</bean>
<!-- PropertiesFactoryBean bean -->
<bean id="propertiesFromDB"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="properties" ref="commonsConfigurationFactoryBean" />
</bean>
<!-- CommonsConfigurationFactoryBean bean -->
<bean id="commonsConfigurationFactoryBean"
class="org.springmodules.commons.configuration.CommonsConfigurationFactoryBean">
<constructor-arg ref="databaseConfiguration"></constructor-arg>
</bean>
<!-- DatabaseConfiguration bean -->
<bean name="databaseConfiguration"
class="org.apache.commons.configuration.DatabaseConfiguration">
<constructor-arg index="0" ref="dataSource" />
<constructor-arg index="1" value="properties" />
<constructor-arg index="2" value="key" />
<constructor-arg index="3" value="value" />
</bean>
以上代码用于从DB加载属性。现在正如您可以看到的dataSource bean,使用了一些占位符。所以我把这行包括在最上面:
<context:property-placeholder location="classpath:databaseForConfiguration.properties"/>
databaseForConfiguration.properties 包含所有必需的属性,在类路径中:
driverClassName=org.postgresql.Driver
url=jdbc:postgresql://localhost:5432/mydb
username=user
password=pass
但是当我尝试执行时,我得到以下异常:
Caused by: org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'driverClassName' threw exception; nested exception is java.lang.IllegalStateException: Could not load JDBC driver class [${driverClassName}]
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:108)
at org.springframework.beans.AbstractPropertyAccessor.setPropertyValues(AbstractPropertyAccessor.java:62)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1489)
... 60 more
类似 {url} , {username} , {password} 。
由于它易于理解,对于要初始化的PropertiesUtil bean,首先需要初始化dataSource bean。对于dataSource bean,必须存在本地属性占位符。 在这种情况下,没有得到。
我希望这两件事,从本地文件加载占位符,也从数据库加载。
任何人都可以帮我解决这个问题。
提前感谢。
答案 0 :(得分:8)
对于
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${driverClassName}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</bean>
我为数据源创建了工厂。现在它看起来像这样:
<bean id="dataSource" class="core.factory.DataSourceFactory" factory-method="createDataSource">
<constructor-arg type="java.lang.String" value="DBConfig.properties" />
</bean>
DataSourceFactory类如下所示:
public class DataSourceFactory
{
private static final String DRIVER_CLASS_NAME = "db.driver";
private static final String URL = "db.url";
private static final String URL_LOGDB = "logdb.url";
private static final String USER_NAME = "db.username";
private static final String PASSWORD = "db.password";
public static DataSource createDataSource(String propertyFilename) throws IOException
{
Properties properties = getProperties(propertyFilename);
return getDataSource(URL, properties);
}
public static DataSource createDataSourceForLogDb(String propertyFilename) throws Exception
{
Properties properties = getProperties(propertyFilename);
return getDataSource(URL_LOGDB, properties);
}
private static Properties getProperties(final String fileName) throws IOException
{
Properties properties = new Properties();
InputStream in = DataSourceFactory.class.getClassLoader().getResourceAsStream(fileName);
properties.load(in);
in.close();
return properties;
}
private static DataSource getDataSource(final String url, final Properties properties)
{
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(properties.getProperty(DRIVER_CLASS_NAME));
dataSource.setUrl(properties.getProperty(url));
dataSource.setUsername(properties.getProperty(USER_NAME));
dataSource.setPassword(properties.getProperty(PASSWORD));
return dataSource;
}
}
现在我也可以从本地文件和数据库中获取属性。
关于我在评论中提出的另一个问题,即从数据库加载i18n资源,我从这个链接获得了解决方案:Spring MVC: Database MessageSource fall back to properties file。
我自己发布了问题,现在我得到了解决方案。 希望这对某人有用。
答案 1 :(得分:6)
首先,你错过了<context:property-placeholder>
。其location
适用于file
,而非Properties
对象。
是的,您的databaseForConfiguration.properties
包含来自数据库的Properties
对象,但它不是.properties
文件。
所以,试试这个:
<bean id="myProperties" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"
p:staticMethod="org.apache.commons.configuration.ConfigurationConverter.getProperties"
p:arguments-ref="databaseConfiguration"/>
<context:property-placeholder properties-ref="myProperties"/>
从另一方面来看,如果您尝试将placeholders
用于DataSource
选项,则不清楚如何从数据库加载属性。在这种情况下,您已经应该已经配置了<context:property-placeholder>
...
<强>更新强>
有理由混合来自不同主题的几个答案。我已经在MethodInvokingFactoryBean
上面显示了构建Properties
对象的东西。
如果您的<context:property-placeholder>
无法解析占位符(Could not load JDBC driver class [${driverClassName}]
),则它在类路径中看不到您的databaseForConfiguration.properties
。
请务必使用正确的location
值,例如location="classpath:WEB-INF/databaseForConfiguration.properties"
,如果您的文件带有WAR。