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的监听器中便可实现分布式管理项目的数据库,而且不需要重启项目。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐