Spring:从数据库和本地文件加载属性

Jay*_*eep 7 spring

我正在尝试从数据库加载属性.我成功了.但现在的问题是,对于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>
Run Code Online (Sandbox Code Playgroud)

上面的代码用于从DB加载属性.现在正如您可以看到的dataSource bean,使用了一些占位符.所以我在顶部包含了这一行:

<context:property-placeholder location="classpath:databaseForConfiguration.properties"/>
Run Code Online (Sandbox Code Playgroud)

databaseForConfiguration.properties 包含所有必需的属性,位于类路径中:

driverClassName=org.postgresql.Driver
url=jdbc:postgresql://localhost:5432/mydb
username=user
password=pass
Run Code Online (Sandbox Code Playgroud)

但是当我尝试执行时,我得到以下异常:

 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
Run Code Online (Sandbox Code Playgroud)

{url},{username},{password}类似.

由于它很容易理解,对于要初始化的PropertiesUtil bean,首先需要对dataSource bean进行初始化.对于dataSource bean,必须存在本地属性占位符.在这种情况下,没有得到.

我想要这两件事,从本地文件数据库加载占位符.

有人请帮我解决这个问题.

提前致谢.

Jay*_*eep 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>
Run Code Online (Sandbox Code Playgroud)

我为数据源创建了工厂.现在它看起来像这样:

<bean id="dataSource" class="core.factory.DataSourceFactory" factory-method="createDataSource">
        <constructor-arg type="java.lang.String" value="DBConfig.properties" />
     </bean>
Run Code Online (Sandbox Code Playgroud)

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我也可以从本地文件和数据库中获取属性.

关于我在评论中提出的另一个问题,即从数据库加载i18n资源,我从这个链接得到了解决方案:Spring MVC:Database MessageSource回退到属性文件.

我自己发布了问题,现在我得到了解决方案.希望这对某人有用.


Art*_*lan 6

首先你错过了<context:property-placeholder>.它location是为了file而不是Properties对象.

是的,您databaseForConfiguration.properties包含Properties来自DB 的对象,但它不是.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"/>
Run Code Online (Sandbox Code Playgroud)

从对方并不清楚你将如何从数据库加载性能,如果你尝试使用placeholdersDataSource选项.在这种情况下,您已经应该已经配置了<context:property-placeholder>......

UPDATE

有理由混合来自不同主题的几个答案.我已经在上面展示了MethodInvokingFactoryBean构建Properties对象的东西.

如果你<context:property-placeholder>无法解析占位符(Could not load JDBC driver class [${driverClassName}]),那么它就不会databaseForConfiguration.properties在类路径中看到你.

请确保使用正确的location值,例如location="classpath:WEB-INF/databaseForConfiguration.properties",如果您的文件存在WAR.