Mybatis-plus動態數據庫之主、副數據庫配置從數據庫(主數據庫或其它數據庫都可以)讀取

我卑微Java開發攻城獅一名,最近在做一個項目,Mysql、Oracle、Sql server、PostgreSql都有用到,所以需要用到動態數據庫。本人採用Mybatis-plus的動態數據源,但是我這數據庫有點多,放到yml不好管理、也不太安全,於是我就想到從一個數據庫(主數據庫)讀取所有數據庫信息,但是Mybatis-plus的動態數據配置是自動加載yml或properties配置文件的,所以我加了一個處理器來更改Spring中的bean,從而更改動態數據源加載配置的方法,通過讀取主數據庫一個表(dbs),把所有的數據庫信息加載到mybatis-plus動態數據源配置信息中去,這樣既方便又安全,還便於管理。話不多碩,幹就完了,奧利給!

1.這是Java相關代碼,當然你可以改代碼,可以把副(從)數據庫配置放到其他數據庫,MySQL或Redis都可以

package com.qy.processor;

import com.baomidou.dynamic.datasource.DynamicDataSourceCreator;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.provider.YmlDynamicDataSourceProvider;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.druid.DruidConfig;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Because of you on 2019/12/29.
 */
@Component
@PropertySource({"classpath:db.properties"})//加載resource下的db.properties
public class DbProcessor implements BeanPostProcessor {
    @Value("${db.driver}")
    private String driver;
    @Value("${db.url}")
    private String url;
    @Value("${db.username}")
    private String username;
    @Value("${db.password}")
    private String password;
    @Value("${db.sql}")
    private String sql;
    @Autowired
    private DefaultListableBeanFactory defaultListableBeanFactory;
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        //設置數據庫配置
        if(StringUtils.endsWithIgnoreCase(beanName,"dynamicDataSourceProvider")) {
            boolean containsBean = defaultListableBeanFactory.containsBean("dynamicDataSourceProvider");
            if(containsBean) {
                defaultListableBeanFactory.removeBeanDefinition("dynamicDataSourceProvider");
            }
            defaultListableBeanFactory.registerBeanDefinition("dynamicDataSourceProvider", BeanDefinitionBuilder.genericBeanDefinition(DynamicDataSourceProperties.class).getBeanDefinition());
            bean = null;
            DynamicDataSourceCreator dynamicDataSourceCreator = (DynamicDataSourceCreator) defaultListableBeanFactory.getBean("dynamicDataSourceCreator");
            YmlDynamicDataSourceProvider ymlDynamicDataSourceProvider = new YmlDynamicDataSourceProvider(this.createDynamicDataSourceProperties(),dynamicDataSourceCreator);
            return ymlDynamicDataSourceProvider;
        }
        //設置主數據庫
        if(StringUtils.endsWithIgnoreCase(beanName,"dataSource")) {
            DynamicRoutingDataSource dynamicRoutingDataSource = (DynamicRoutingDataSource)bean;
            dynamicRoutingDataSource.setPrimary("oracle");
            return  dynamicRoutingDataSource;
        }
        return bean;
    }
    public DynamicDataSourceProperties createDynamicDataSourceProperties() {
        Map<String,DataSourceProperty> map = new HashMap<String,DataSourceProperty>();
        DataSourceProperty mainDbProperty = new DataSourceProperty();
        //把主數據設置進去
        mainDbProperty.setDriverClassName(driver);
        mainDbProperty.setUrl(url);
        mainDbProperty.setUsername(username);
        mainDbProperty.setPassword(password);
        map.put("oracle",mainDbProperty);
        List<Map<String,String>> list = this.listDbs();
        DataSourceProperty otherDbProperty =  null;
        //設置副數據庫
        for (Map<String,String> tmpMap : list) {
            otherDbProperty = new DataSourceProperty();
            String nickname = tmpMap.get("nickname");
            otherDbProperty.setDriverClassName(tmpMap.get("driver"));
            otherDbProperty.setUrl(tmpMap.get("url"));
            otherDbProperty.setUsername(tmpMap.get("username"));
            otherDbProperty.setPassword(tmpMap.get("password"));
            map.put(nickname,otherDbProperty);
        }
        DruidConfig druidConfig = this.createDruidConfig();
        DynamicDataSourceProperties dynamicDataSourceProperties = new DynamicDataSourceProperties();
        dynamicDataSourceProperties.setDruid(druidConfig);
        dynamicDataSourceProperties.setDatasource(map);
        return dynamicDataSourceProperties;
    }

    /**
     * 獲取數據庫連接
     * @return
     */
    public Connection getConnection() throws ClassNotFoundException, SQLException {
        Class.forName(driver);
        return DriverManager.getConnection(url,username,password);
    }

    /**
     * 查詢所有數據庫配置
     * @return
     */
    public List<Map<String,String>> listDbs() {
        List<Map<String,String>> resultList = null;
        Connection connection = null;
        PreparedStatement ps = null;
        ResultSet rs =  null;
        try {
            connection =  this.getConnection();
            ps = connection.prepareStatement(sql);
            rs = ps.executeQuery();
            resultList = new ArrayList<Map<String,String>>();
            Map<String,String> resultMap = null;
            while (rs.next()) {
                String nickname = rs.getString("NICKNAME");
                String dbdriver = rs.getString("DRIVER");
                String dburl = rs.getString("URL");
                String dbusername = rs.getString("USERNAME");
                String dbpassword = rs.getString("PASSWORD");
                resultMap = new HashMap<String,String>();
                resultMap.put("nickname",nickname);
                resultMap.put("driver",dbdriver);
                resultMap.put("url",dburl);
                resultMap.put("username",dbusername);
                resultMap.put("password",dbpassword);
                resultList.add(resultMap);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            if(rs!=null) {
                try {
                    rs.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(ps!=null) {
                try {
                    ps.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            if(connection!=null) {
                try {
                    connection.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
            return  resultList;
        }
    }

    /**
     * 配置druid連接池配置
     * @return
     */
    public DruidConfig createDruidConfig() {
        DruidConfig druidConfig = new DruidConfig();
        druidConfig.setInitialSize(10);
        druidConfig.setMaxActive(100);
        druidConfig.setMinIdle(10);
        druidConfig.setMaxWait(60000L);
        druidConfig.setPoolPreparedStatements(true);
        druidConfig.setMaxPoolPreparedStatementPerConnectionSize(20);
        druidConfig.setTimeBetweenEvictionRunsMillis(60000L);
        druidConfig.setMinEvictableIdleTimeMillis(300000L);
        //validation-query: SELECT 1 FROM DUAL
        druidConfig.setTestWhileIdle(true);
        druidConfig.setTestOnBorrow(false);
        druidConfig.setTestOnReturn(false);
        druidConfig.setFilters("stat,wall");
        return druidConfig;
    }
}

2.我用的主數據是oracle,這是db.properties,放到Springboot resource目錄下,當然你的主數據連接信息也可以加密,相關業務代碼你可以自己添加

db.driver=oracle.jdbc.driver.OracleDriver
db.url=jdbc:oracle:thin:@127.0.0.1:1521:myorcl
db.username=數據庫名
db.password=密碼
db.sql=select nickname,driver,url,username,password from DBS

3.創建副(從)數據庫配置表

create table dbs(
     id number(4) primary key,
     nickname varchar2(8) not null,
     driver varchar2(32) not null,
     url  varchar2(64) not null,
     username varchar2(32) not null,
     password varchar2(32) not null,
     create_time date,
     remark varchar2(128)
)

老鐵!別走,如果我的代碼可以幫到你,請給我一顆小心心。奧利給!

                                                         非學無以廣才,非志無以成學。

 

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