zookeeper 數據源動態配置

zookeeper具體實現配置在這裏不具體描述,可查看zookeper配置

一、實現的方式

數據源datasource,數據庫的連接或者連接池的具體配置都在其中,因此,我們在修改數據庫的配置的同時修改datasource 就可以不需要重新啓動項目而實現數據庫的切換。

使用org.apache.commons.dbcp.BasicDataSource
說明:這是一種推薦說明的數據源配置方式,它真正使用了連接池技術

<bean id="dataSource"  class="org.apache.commons.dbcp.BasicDataSource"> 
              <property name="driverClassName"> 
                     <value>oracle.jdbc.driver.OracleDriver</value> 
              </property> 
              <property name="url"> 
                     <value>jdbc:oracle:thin:@localhost:1521:orcl</value> 
              </property> 
              <property name="username"> 
                     <value>test</value> 
              </property> 
              <property name="password"> 
                     <value>test</value> 
              </property> 
              <property name="maxActive"> 
                     <value>255</value> 
              </property> 
              <property name="maxIdle"> 
                     <value>2</value> 
              </property> 
              <property name="maxWait"> 
                     <value>120000</value> 
              </property> 
       </bean> 

spring 加載容器的時候初始化了dataSource,爲了方便操作dataSource,我重寫了dataSource,重新了dataSource的創建,以及添加了dataSource的修改。


package app.datasource;

import app.context.RuntimeContext;
import app.utils.JackSonUtil;
import app.utils.PropertiesUtil;
import app.utils.ValueUtil;
import app.zookeeper.ConfigureUtil;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.pool.impl.GenericKeyedObjectPool;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Logger;

/**
 * Created by lili19289 on 2016/8/23.
 */
public class DataSourceConfigure extends BasicDataSource{

    public static final String PREFFIX = "db.";

    public static final String PROP_KEY_DRIVERCLASSNAME =PREFFIX+ "driver";

    public static final String PROP_KEY_URL = PREFFIX+"url";

    public static final String PROP_KEY_USERNAME =PREFFIX+ "username";

    public static final String PROP_KEY_PASSWORD = PREFFIX+"password";

    public static final String PROP_KEY_MAXACTIVE = PREFFIX+"maxActive";

    public static final String PROP_KEY_INITIALSIZE = PREFFIX+"initialSize";

    public static final String PROP_KEY_MAXWAIT =PREFFIX+ "maxWait";

    public static final String PROP_KEY_MAXIDLE = PREFFIX+"maxIdle";

    public static final String PROP_KEY_MINIDLE = PREFFIX+"minIdle";

    public static final String PROP_KEY_TIMEBETWEENEVICTIONRUNSMILLS = PREFFIX+"timeBetweenEvictionRunsMillis";

    public static final String PROP_KEY_MINEVICTABLEIDLETIMEMILLIS = PREFFIX+"minEvictableIdleTimeMillis";





    private static final Log LOG = LogFactory.getLog(DataSourceConfigure.class);

    private static Properties prop;

    public Connection getConnection() throws SQLException {
        return this.getDataSource().getConnection();
    }

    public DataSource getDataSource (){
        initDataSource();
        try {
            this.dataSource= this.createDataSource();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return this.dataSource;
    }

    public void initDataSource(){
        Map<String,Object > configureData = ConfigureUtil.loadConfigData("db");
        System.err.println(configureData.get(PROP_KEY_DRIVERCLASSNAME).toString());
        this.setDriverClassName(configureData.get(PROP_KEY_DRIVERCLASSNAME).toString());
        this.setUrl(configureData.get(PROP_KEY_URL).toString());
        this.setUsername(configureData.get(PROP_KEY_USERNAME).toString());
        this.setPassword(configureData.get(PROP_KEY_PASSWORD).toString());
        int initialSize = ValueUtil.getInt(configureData.get(PROP_KEY_INITIALSIZE), -1);
        if (-1 == initialSize) {
            initialSize = this.initialSize;
        }
        this.setInitialSize(initialSize);

        // maxActive
        int maxActive = ValueUtil.getInt(configureData.get(PROP_KEY_MAXACTIVE), -1);
        if (-1 == maxActive) {
            maxActive = this.maxActive;
        }
        this.setMaxActive(maxActive);

        // maxIdle
        int maxIdle = ValueUtil.getInt(configureData.get(PROP_KEY_MAXIDLE), -1);
        if (-1 == maxIdle) {
            maxIdle = this.maxIdle;
        }
        this.setMaxIdle(maxIdle);

        // minIdle
        int minIdle = ValueUtil.getInt(configureData.get(PROP_KEY_MINIDLE), -1);
        if (-1 == minIdle) {
            minIdle = this.minIdle;
        }
        this.setMinIdle(minIdle);

        // maxWait
        long maxWait = ValueUtil.getLong(configureData.get(PROP_KEY_MAXWAIT), -1);
        if (-1 == maxWait) {
            maxWait = this.maxWait;
        }
        this.setMaxWait(maxWait);

        // timeBetweenEvictionRunsMillis
        long timeBetweenEvictionRunsMillis = ValueUtil.getLong(configureData.get(PROP_KEY_TIMEBETWEENEVICTIONRUNSMILLS),
                -1);
        if (-1 == timeBetweenEvictionRunsMillis) {
            timeBetweenEvictionRunsMillis = this.timeBetweenEvictionRunsMillis;
        }
        this.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);

        // minEvictableIdleTimeMillis
        long minEvictableIdleTimeMillis = ValueUtil.getLong(configureData.get(PROP_KEY_MINEVICTABLEIDLETIMEMILLIS), -1);
        if (-1 == minEvictableIdleTimeMillis) {
            minEvictableIdleTimeMillis = this.minEvictableIdleTimeMillis;
        }
        this.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
    }


    public static void changeDataSource(){
       DataSourceConfigure dataSourceConfigure = (DataSourceConfigure) RuntimeContext.getBean("dataSource");
        try {
            dataSourceConfigure.close();
            dataSourceConfigure.initDataSource();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }



    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return null;
    }

    public <T> T unwrap(Class<T> iface) throws SQLException {
        return null;
    }

    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }
}

修改後,配置文件中的數據源使用重寫過的數據庫實體類,修改爲:

<bean id="dataSource"class="app.datasource.DataSourceConfigure"
        destroy-method="close">
    </bean>

因此,當你修改數據庫的配置時,調用changeDataSource()方法,關閉之前的數據源並初始化新的數據源,即可實現數據庫的動態切換。這個方法放入zookeeper的監聽器中便可實現分佈式管理項目的數據庫,而且不需要重啓項目。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章