spring 动态添加切换数据。

        网上关于动态切换数据的例子很多很多看了下也有用,在spring配置文件中配置多个数据源,然后再切换。

        我目前在做一个数据库监控系统。核心点就是多个数据库信息存在数据库中然后在在后台查出数据库信息,然后动态切换数据源在各数据源中运行各个系统sql(sqlserver数据库有很多系统sql可以统计数据库信息,如死锁数量,最近执行sql语句执行时间)。

        通过业务分解,我需要解决的点就是多个数据库信息存在数据库中,然后前端显示,通过选择各个不同的然后页面显示不同数据库执行情况。无法套上前人例子-直接将数据源信息写入spirng配置文件中。也不想使用jdbc,用了jdbc就都没这么麻烦了。但是为了成长,只好去网上搜呀搜还真搜到了,但是在系统用却又很多问题,然后自己再研究研究,改了些东西,总于解决了,对spring的理解有深了几分。下面贴代码

package com.rokin.dynamicdatasource;
import com.alibaba.druid.pool.DruidDataSource;
import com.rokin.constand.CommonConstant;
import com.rokin.pojo.JdbcPojo;
import com.rokin.service.IChanageDbService;
import org.omg.CORBA.SystemException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * @author cjj
 * @version 1.00
 * @time 2018/3/29 13:36
 */
public class DynamicDataSource extends AbstractRoutingDataSource {
    @Autowired
    private IChanageDbService chanageDbService;
    // 默认数据源,也就是主库
    private DataSource masterDataSource;
    private DataSource masterDataSource2;

    public DataSource getMasterDataSource2() {
        return masterDataSource2;
    }

    public void setMasterDataSource2(DataSource masterDataSource2) {
        System.out.println("==============masterDataSource2masterDataSource2=================");
        this.masterDataSource2 = masterDataSource2;
    }

    // 保存动态创建的数据源
    private static final Map targetDataSource = new HashMap<String, Object>();
    @Override
    protected DataSource determineTargetDataSource() {
        // 根据数据库选择方案,拿到要访问的数据库
        String dataSourceName = determineCurrentLookupKey();
        if ("dataSource".equals(dataSourceName)) {
            // 访问默认主库
            return masterDataSource;
        }
        // 根据数据库名字,从已创建的数据库中获取要访问的数据库
        DataSource dataSource = (DataSource) targetDataSource.get(dataSourceName);
        if (null == dataSource) {
            // 从已创建的数据库中获取要访问的数据库,如果没有则创建一个
            dataSource = this.selectDataSource(dataSourceName);
        }
        System.out.println("===============最终返回的数据源头为================== ");
        return dataSource;
    }
    @Override
    protected String determineCurrentLookupKey() {
        // TODO Auto-generated method stub
        String dataSourceName = Dbs.getDbType();
        if (dataSourceName == null ||  "dataSource".equals(dataSourceName)) {
            // 默认的数据源名字
            dataSourceName = "dataSource";
        }
        System.out.println("use datasource : ");
        return dataSourceName;
    }
    public void setTargetDataSource(Map targetDataSource) {
        targetDataSource = targetDataSource;
        super.setTargetDataSources(targetDataSource);
    }
    public Map getTargetDataSource() {
        return targetDataSource;
    }
    public void addTargetDataSource(String key, DruidDataSource dataSource) {
        targetDataSource.put(key, dataSource);
        setTargetDataSources(targetDataSource);
    }
    private synchronized DataSource selectDataSource(String dbType) throws SystemException {
        DataSource obj = (DataSource) targetDataSource.get(dbType);
        if (null != obj) {
            return obj;
        }
        // 为空则创建数据库
        DruidDataSource dataSource = this.getDataSource(dbType);
        if (null != dataSource) {
            // 将新创建的数据库保存到map中
            this.setDataSource(dbType, dataSource);
            return dataSource;
        } else {
            System.out.println("创建数据源失败!根据key:"+dbType+"找不到对应的的数据源");
        }
        return dataSource;
    }
    /**
     * 查询对应数据库的信息
     * @param dbtype
     * @return
     */
    private DruidDataSource getDataSource(String dbtype) {
        String oriType = Dbs.getDbType();
        // 先切换回主库
        Dbs.setDbType("dataSource");
        String url=null;
        String username=null;
        String password=null;
        DruidDataSource dataSource=null;
        if(CommonConstant.defaultDataSource.equals(dbtype)){
            url=CommonConstant.defaultUrl;
            username=CommonConstant.defaultUserName;
            password=CommonConstant.defaultPassword;
        }else{
            Map<String ,List<JdbcPojo>> datebase = chanageDbService.getDbInformation();
            List<JdbcPojo> thisList=null;
            thisList =datebase.get(oriType);
            if(datebase!=null){
                System.out.println("数据库中存储的数据库信息条数为:"+datebase.size());
                System.out.println("切换的数据源头为oriType:"+oriType);
                if(thisList!=null){
                    url = thisList.get(0).getUrl();
                    username = thisList.get(0).getUsername();
                    password = thisList.get(0).getPassword();
                }else{
                    return null;
                }
            }else{
                return null;
            }
        }
        Dbs.setDbType(oriType);
        dataSource = createDataSource(
                url,username,password);
        return dataSource;
    }
    //创建SQLServer数据源
    private DruidDataSource createDataSource(String url,String userName,String password) {
        return createDataSource("com.microsoft.sqlserver.jdbc.SQLServerDriver", url, userName, password);
    }
    //创建数据源
    private DruidDataSource createDataSource(String driverClassName, String url,String username, String password) {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName(driverClassName);
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        dataSource.setTestWhileIdle(true);
        return dataSource;
    }
    public void setDataSource(String type, DruidDataSource dataSource) {
        this.addTargetDataSource(type, dataSource);
        Dbs.setDbType(type);
    }
    @Override
    public void setTargetDataSources(Map targetDataSources) {
        // TODO Auto-generated method stub
        super.setTargetDataSources(targetDataSources);
        // 重点:通知container容器数据源发生了变化
        afterPropertiesSet();
    }
    @Override
    public void afterPropertiesSet() {
    }
    public DataSource getMasterDataSource() {
        return masterDataSource;
    }
    public void setMasterDataSource(DataSource masterDataSource) {
        this.masterDataSource = masterDataSource;
    }
}

IChanageDbService里面就是数据库信息而已 存储多个数据库信息 调用的话 Dbs.setDbType("defaultDataSource");用完需要 Dbs.clear();
Dbs里面和spring配置文件内容都网上都有都一样的,最重要的就是上面这个了



猜你喜欢

转载自blog.csdn.net/qq_34735535/article/details/80063318