在Spring框架中从数据库中加载配置

来源:互联网 发布:淘宝客现在还好做吗 编辑:程序博客网 时间:2024/05/17 06:19


目录(?)[+]

 

一. 问题

        在实际开发中,通常服务器都很多,每台服务器上的应用都需要配置参数,如果有修改或者变动就会很麻烦,每台服务器都需要改一次。所以有必要把一些参数配置到数据库里,这样方便查看和管理。

     

       来看一个实际例子,我们在Spring中加载配置的代码为:

 

 

[xhtml] view plaincopy
  1. <!-- 应用的全局配置文件 -->  
  2. <context:property-placeholder location="classpath*:config.properties" />  
  3.   
  4. <!-- 定义远程访问 url 的 工具 -->  
  5. <bean id="httpUtils" class="common.web.HttpUtils">           
  6.  <property name="directHost" value="${httpUtils.directHost}" />  
  7.  <property name="host" value="${root}" />  
  8. <!-- 超时设置 10秒 -->  
  9. <property name="timeOut" value="10000" />  
  10. <!-- 使用代理 -->  
  11. <property name="useProxy" value="${useProxy}" />  
  12. <property name="proxyServer" value="${proxyServer}" />  
  13. <property name="proxyPort" value="${proxyPort}" />  
  14. <property name="proxyUser" value="${proxyUser}" />  
  15. <property name="proxyPassword" value="${proxyPassword}" />  
  16. <property name="proxyServerType" value="${proxyType}" />  
  17. <property name="defaultHeaders">  
  18. <map>  
  19.  <entry key="User-Agent" value="Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; WOW64; Trident/4.0; GTB6; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.0.04506; Media Center PC 5.0)" />  
  20.  <entry key="Cookie" value="BX=4ec9sn94jpfsc&b=3&s=u6; cna=/6HDAZV3zUUBAf6fYMrpHz8u; t=858409c6a38498fadf40289e2e828abd; " />  
  21. </map>  
  22. </property>  
  23. </bean>  

       我们把配置都集中放到config.properties里,方便管理。如果是变动了,所有服务器上都需要更改一次。

 

二. Spring 的已有解决办法

  

    http://www.springbyexample.org/twiki/bin/view/Example/SpringModulesWithCommonsConfiguration 

 

    这链接介绍了如何实现,主要通过Spring Module 和 Common Configuration 来实现。

 

 

   

[xhtml] view plaincopy
  1. <!-- Required to donnect to datasource -->  
  2. <bean name="PropertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
  3.   <property name="properties" ref="CommonsConfigurationFactoryBean"/>  
  4. </bean>     
  5.   
  6. <bean name="CommonsConfigurationFactoryBean" class="org.springmodules.commons.configuration.CommonsConfigurationFactoryBean">         
  7.    <constructor-arg ref="DatabaseConfiguration"/>  
  8. </bean>     
  9. <bean name="DatabaseConfiguration" class="org.apache.commons.configuration.DatabaseConfiguration">          
  10.   <constructor-arg type="javax.sql.DataSource" ref="someDataSource"/>          
  11.   <constructor-arg index="1" value="TEST_SCHEMA.APPLICATION_PROPERTIES_TABLE"/>          <constructor-arg index="2" value="KEY"/>        <constructor-arg index="3" value="VALUE"/>  
  12. </bean>  
  13.   
  14. <!-- Included to elaborate functionality -->  
  15. <bean name="PropertiesPrinter" class="example.PropertiesPrinter" init-method="displayAllProperties">      
  16. <property name="fileLocation" value="${file.location}"/>    <property name="petDogsName" value="${pet.dogs.name}"/>      
  17. <property name="keyOne" value="${key.one}"/>  
  18. </bean>  
 

 

 

三. 我们的实现

   以上方法是通过commons-configuration  来实现,这种每次读取和变动都会访问数据库,在我们的实际应用中,应该是启动的时候读取一次就可以了,没有必要占着数据库连接,而且全局配置不允许应用修改的。

 

     借鉴以上方法,我们写了一个类似的类来实现。

 

      配置如下:

[xhtml] view plaincopy
  1. <!-- 采用数据库读取配置 -->  
  2.  <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
  3.  <property name="properties"  ref="dataBaseProperties"/>  
  4.        <!-- 文件会覆盖数据库配置 -->  
  5.  <property name="locations">  
  6.     <list>  
  7.         <value>classpath*:config.properties</value>  
  8.     </list>  
  9.        </property>  
  10. lt;/bean>  
  11.   
  12.    <!-- 第一次读入,如果更改,需要重启  数据库配置,这里不能用${} -->  
  13.    <bean id="dataBaseProperties" class="common.spring.DatabaseProperties" >  
  14.        <constructor-arg type="javax.sql.DataSource" ref="confDataSource"/>  
  15.        <constructor-arg value="select key_s,value_s from app_conf where status>0"/>  
  16.    </bean>  
  17.   
  18.    <bean id="confDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  
  19.        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>  
  20.        <property name="url" value="jdbc:mysql://localhost/test?characterEncoding=gbk"/>  
  21.        <property name="username" value="root"/>  
  22.        <property name="password" value=""/>  
  23.    </bean>  

        文件和数据库混合配置,文件的配置优先。

  

      源码如下:

[java] view plaincopy
  1. /** 
  2.  * 专注互联网,分享创造价值 
  3.  * maoxiang@gmail.com 
  4.  */  
  5. package common.spring;  
  6.   
  7. import common.util.ValidateUtil;  
  8. import java.sql.Connection;  
  9. import java.sql.PreparedStatement;  
  10. import java.sql.ResultSet;  
  11. import java.util.Properties;  
  12. import javax.sql.DataSource;  
  13. import org.apache.commons.logging.Log;  
  14. import org.apache.commons.logging.LogFactory;  
  15. import org.springframework.beans.factory.FactoryBean;  
  16. import org.springframework.beans.factory.InitializingBean;  
  17.   
  18. /** 
  19.  * 从数据库里读取配置 
  20.  *  实现参考http://forum.springsource.org/showthread.php?t=57246 
  21.  */  
  22. public class DatabaseProperties implements InitializingBean, FactoryBean {  
  23.   
  24.     private static final Log log = LogFactory.getLog(DatabaseProperties.class);  
  25.     private Properties props = new Properties();  
  26.     private DataSource datasource;  //数据源  
  27.     private String query;  //读取的sql  
  28.   
  29.     public DatabaseProperties(DataSource datasource, String query) {  
  30.         this.datasource = datasource;  
  31.         this.query = query;  
  32.     }  
  33.   
  34.     @Override  
  35.     public void afterPropertiesSet() throws Exception {  
  36.         initProperties();  
  37.     }  
  38.   
  39.     @Override  
  40.     public Object getObject() throws Exception {  
  41.         return props;  
  42.     }  
  43.   
  44.     @Override  
  45.     public Class getObjectType() {  
  46.         return Properties.class;  
  47.     }  
  48.   
  49.     @Override  
  50.     public boolean isSingleton() {  
  51.         return true;  
  52.     }  
  53.     //----------  
  54.   
  55.     private void initProperties() {  
  56.         Connection connection = null;  
  57.         try {  
  58.             connection = datasource.getConnection();  
  59.             PreparedStatement ps = connection.prepareStatement(query);  
  60.             ResultSet rs = ps.executeQuery();  
  61.             while (rs.next()) {  
  62.                 String key = rs.getString(1);  
  63.                 String value = rs.getString(2);  
  64.                 if (!ValidateUtil.isNull(key) && !ValidateUtil.isNull(value)) {  
  65.                     log.info("load property. Key=" + key + ",Value=" + value);  
  66.                     props.setProperty(key, value);  
  67.                 }  
  68.             }  
  69.             rs.close();  
  70.             ps.close();  
  71.         } catch (Exception e) {  
  72.             log.error(e);  
  73.         } finally {  
  74.             if (connection != null) {  
  75.                 try {  
  76.                     connection.close();  
  77.                 } catch (Exception e) {  
  78.                     log.error(e);  
  79.                 }  
  80.             }  
  81.         }  
  82.     }  

原创粉丝点击