天天看點

springboot 配置多druid資料源

由于項目需要進行資料表水準拆分,需要将原來一個表的資料拆分成兩個庫,根據自增ID進行取模,為0的路由在DB0,為1的路由在DB1,所有就需要配置三個資料源。

項目環境:SpringBoot2x,jdk8

pom.xml 引入需要的包

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.2.3</version>
</dependency>
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.3.2</version>
</dependency>
<!-- 阿裡系的Druid依賴包 -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.9</version>
</dependency>
           

一,application.properties配置檔案

#mysql 配置
spring.datasource.olddb.url=jdbc:mysql://192.168.2.200:3306/sunshine_aunt_test?characterEncoding=utf-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&useSSL=false
spring.datasource.olddb.username=root
spring.datasource.olddb.password=123456
#db0
spring.datasource.db0.url=jdbc:mysql://192.168.2.185:3306/springboot_bigdata?characterEncoding=utf-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&useSSL=false
spring.datasource.db0.username=root
spring.datasource.db0.password=123456
#db1
spring.datasource.db1.url=jdbc:mysql://192.168.2.185:3307/springboot_bigdata?characterEncoding=utf-8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&useSSL=false
spring.datasource.db1.username=root
spring.datasource.db1.password=123456

#阿裡druid連接配接池驅動配置資訊
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
#連接配接池的配置資訊
#初始化大小,最小,最大
spring.datasource.initialSize=2
spring.datasource.minIdle=2
spring.datasource.maxActive=3
#配置擷取連接配接等待逾時的時間
spring.datasource.maxWait=6000
#配置間隔多久才進行一次檢測,檢測需要關閉的空閑連接配接,機關是毫秒
spring.datasource.timeBetweenEvictionRunsMillis=60000
#配置一個連接配接在池中最小生存的時間,機關是毫秒
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=SELECT 1 FROM DUAL
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
#打開PSCache,并且指定每個連接配接上PSCache的大小
spring.datasource.poolPreparedStatements=true
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
#配置監控統計攔截的filters,去掉後監控界面sql無法統計,'wall'用于防火牆
spring.datasource.filters=stat,wall,log4j
#通過connectProperties屬性來打開mergeSql功能;慢SQL記錄
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000

#新增資料後自動擷取資料庫自增主鍵, 需要使用 keyProperty 指定主鍵
mybatis.configuration.use-generated-keys=true
#開啟自動駝峰命名轉換
mybatis.configuration.map-underscore-to-camel-case=true
           

裡面配置了三個資料源,olddb,db0 和db1,将olddb庫的資料查詢出來根據自增id進行取模路由到db0庫和db1庫

二,druid 的config配置檔案,三份,一個庫一份

1,OldDBDruidDBConfig

@Configuration
@MapperScan(sqlSessionTemplateRef = OldDBDruidDBConfig.SqlSessionTemplate, basePackages = OldDBDruidDBConfig.BASE_PACKAGES)
@Slf4j
public class OldDBDruidDBConfig {

    private static final String DB_PREFIX = "spring.datasource";

    public static final String BASE_PACKAGES = "springboot.bigdata.demo.mappers.old_db";

    private static final String MAPPER_LOCATIONS = "classpath*:mappers/old_db/*.xml";

    public static final String SqlSessionTemplate = "oldDBSqlSessionTemplate";

    private static final String SqlSessionFactory = "oldDBSqlSessionFactory";

    private static final String PlatformTransactionManager = "oldDBPlatformTransactionManager";

    private static final String DataSource = "oldDBDataSource";
	
    @Bean
    public ServletRegistrationBean druidServlet() {
        log.info("init olddb Druid Servlet Configuration ");
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
        // IP白名單
        servletRegistrationBean.addInitParameter("allow", "");
        // IP黑名單(共同存在時,deny優先于allow)
        servletRegistrationBean.addInitParameter("deny", "");
        //控制台管理使用者
        servletRegistrationBean.addInitParameter("loginUsername", "");
        servletRegistrationBean.addInitParameter("loginPassword", "");
        //是否能夠重置資料 禁用HTML頁面上的“Reset All”功能
        servletRegistrationBean.addInitParameter("resetEnable", "false");
        return servletRegistrationBean;
    }

    @Bean(name = SqlSessionTemplate)
    @Autowired
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier(SqlSessionFactory) SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    @Bean(name = SqlSessionFactory)
    @Autowired
    public SqlSessionFactory sqlSessionFactory(@Qualifier(DataSource) DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MAPPER_LOCATIONS));
        return bean.getObject();
    }

    @Bean(name = PlatformTransactionManager)
    @Autowired
    public PlatformTransactionManager platformTransactionManager(@Qualifier(DataSource) DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter());
        filterRegistrationBean.addUrlPatterns("/*");
        filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
        return filterRegistrationBean;
    }

    @Value("${spring.datasource.olddb.url}")
    private String spring_datasource_url;
    @Value("${spring.datasource.olddb.username}")
    private String spring_datasource_username;
    @Value("${spring.datasource.olddb.password}")
    private String spring_datasource_password;

    // 解決 spring.datasource.filters=stat,wall,log4j 無法正常注冊進去
    @ConfigurationProperties(prefix = DB_PREFIX)
    class IDataSourceProperties {
        private String url = spring_datasource_url;
        private String username = spring_datasource_username;
        private String password = spring_datasource_password;
        private String driverClassName;
        private int initialSize;
        private int minIdle;
        private int maxActive;
        private int maxWait;
        private int timeBetweenEvictionRunsMillis;
        private int minEvictableIdleTimeMillis;
        private String validationQuery;
        private boolean testWhileIdle;
        private boolean testOnBorrow;
        private boolean testOnReturn;
        private boolean poolPreparedStatements;
        private int maxPoolPreparedStatementPerConnectionSize;
        private String filters;
        private String connectionProperties;

        @Bean(name = DataSource)     //聲明其為Bean執行個體
//        @Primary  //在同樣的DataSource中,首先使用被标注的DataSource(分庫後多資料源不需要配置)
        public DataSource dataSource() {
            DruidDataSource datasource = new DruidDataSource();
            datasource.setUrl(url);
            datasource.setUsername(username);
            datasource.setPassword(password);
            datasource.setDriverClassName(driverClassName);

            //configuration
            datasource.setInitialSize(initialSize);
            datasource.setMinIdle(minIdle);
            datasource.setMaxActive(maxActive);
            datasource.setMaxWait(maxWait);
            datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
            datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
            datasource.setValidationQuery(validationQuery);
            datasource.setTestWhileIdle(testWhileIdle);
            datasource.setTestOnBorrow(testOnBorrow);
            datasource.setTestOnReturn(testOnReturn);
            datasource.setPoolPreparedStatements(poolPreparedStatements);
            datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
            try {
                datasource.setFilters(filters);
            } catch (SQLException e) {
                log.error("druid configuration initialization filter: " + e);
            }
            datasource.setConnectionProperties(connectionProperties);
            return datasource;
        }
           

2,DB0DruidDBConfig

@Configuration
@MapperScan(sqlSessionTemplateRef = DB0DruidDBConfig.SqlSessionTemplate, basePackages = DB0DruidDBConfig.BASE_PACKAGES)
@Slf4j
public class DB0DruidDBConfig {

    private static final String DB_PREFIX = "spring.datasource";

    public static final String BASE_PACKAGES = "springboot.bigdata.demo.mappers.db0";

    private static final String MAPPER_LOCATIONS = "classpath*:mappers/db0/*.xml";

    public static final String SqlSessionTemplate = "db0SqlSessionTemplate";

    private static final String SqlSessionFactory = "db0SqlSessionFactory";

    private static final String PlatformTransactionManager = "db0PlatformTransactionManager";

    private static final String DataSource = "db0DataSource";

    @Bean
    public ServletRegistrationBean druidServlet() {
        log.info("init db0 Druid Servlet Configuration ");
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
        // IP白名單
        servletRegistrationBean.addInitParameter("allow", "");
        // IP黑名單(共同存在時,deny優先于allow)
        servletRegistrationBean.addInitParameter("deny", "");
        //控制台管理使用者
        servletRegistrationBean.addInitParameter("loginUsername", "");
        servletRegistrationBean.addInitParameter("loginPassword", "");
        //是否能夠重置資料 禁用HTML頁面上的“Reset All”功能
        servletRegistrationBean.addInitParameter("resetEnable", "false");
        return servletRegistrationBean;
    }

    @Bean(name = SqlSessionTemplate)
    @Autowired
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier(SqlSessionFactory) SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    @Bean(name = SqlSessionFactory)
    @Autowired
    public SqlSessionFactory sqlSessionFactory(@Qualifier(DataSource) DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MAPPER_LOCATIONS));
        return bean.getObject();
    }

    @Bean(name = PlatformTransactionManager)
    @Autowired
    public PlatformTransactionManager platformTransactionManager(@Qualifier(DataSource) DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter());
        filterRegistrationBean.addUrlPatterns("/*");
        filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
        return filterRegistrationBean;
    }

    @Value("${spring.datasource.db0.url}")
    private String spring_datasource_url;
    @Value("${spring.datasource.db0.username}")
    private String spring_datasource_username;
    @Value("${spring.datasource.db0.password}")
    private String spring_datasource_password;

    // 解決 spring.datasource.filters=stat,wall,log4j 無法正常注冊進去
    @ConfigurationProperties(prefix = DB_PREFIX)
    class IDataSourceProperties {
        private String url = spring_datasource_url;
        private String username = spring_datasource_username;
        private String password = spring_datasource_password;
        private String driverClassName;
        private int initialSize;
        private int minIdle;
        private int maxActive;
        private int maxWait;
        private int timeBetweenEvictionRunsMillis;
        private int minEvictableIdleTimeMillis;
        private String validationQuery;
        private boolean testWhileIdle;
        private boolean testOnBorrow;
        private boolean testOnReturn;
        private boolean poolPreparedStatements;
        private int maxPoolPreparedStatementPerConnectionSize;
        private String filters;
        private String connectionProperties;

        @Bean(name = DataSource)     //聲明其為Bean執行個體
//        @Primary  //在同樣的DataSource中,首先使用被标注的DataSource(分庫後多資料源不需要配置)
        public DataSource dataSource() {
            DruidDataSource datasource = new DruidDataSource();
            datasource.setUrl(url);
            datasource.setUsername(username);
            datasource.setPassword(password);
            datasource.setDriverClassName(driverClassName);

            //configuration
            datasource.setInitialSize(initialSize);
            datasource.setMinIdle(minIdle);
            datasource.setMaxActive(maxActive);
            datasource.setMaxWait(maxWait);
            datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
            datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
            datasource.setValidationQuery(validationQuery);
            datasource.setTestWhileIdle(testWhileIdle);
            datasource.setTestOnBorrow(testOnBorrow);
            datasource.setTestOnReturn(testOnReturn);
            datasource.setPoolPreparedStatements(poolPreparedStatements);
            datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
            try {
                datasource.setFilters(filters);
            } catch (SQLException e) {
                log.error("druid configuration initialization filter: " + e);
            }
            datasource.setConnectionProperties(connectionProperties);
            return datasource;
        }
           

3,DB1DruidDBConfig

@Configuration
@MapperScan(sqlSessionTemplateRef = DB1DruidDBConfig.SqlSessionTemplate, basePackages = DB1DruidDBConfig.BASE_PACKAGES)
@Slf4j
public class DB1DruidDBConfig {

    private static final String DB_PREFIX = "spring.datasource";

    public static final String BASE_PACKAGES = "springboot.bigdata.demo.mappers.db1";

    private static final String MAPPER_LOCATIONS = "classpath*:mappers/db1/*.xml";

    public static final String SqlSessionTemplate = "db1SqlSessionTemplate";

    private static final String SqlSessionFactory = "db1SqlSessionFactory";

    private static final String PlatformTransactionManager = "db1PlatformTransactionManager";

    private static final String DataSource = "db1DataSource";

    @Bean
    public ServletRegistrationBean druidServlet() {
        log.info("init db1 Druid Servlet Configuration ");
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
        // IP白名單
        servletRegistrationBean.addInitParameter("allow", "");
        // IP黑名單(共同存在時,deny優先于allow)
        servletRegistrationBean.addInitParameter("deny", "");
        //控制台管理使用者
        servletRegistrationBean.addInitParameter("loginUsername", "");
        servletRegistrationBean.addInitParameter("loginPassword", "");
        //是否能夠重置資料 禁用HTML頁面上的“Reset All”功能
        servletRegistrationBean.addInitParameter("resetEnable", "false");
        return servletRegistrationBean;
    }

    @Bean(name = SqlSessionTemplate)
    @Autowired
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier(SqlSessionFactory) SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }

    @Bean(name = SqlSessionFactory)
    @Autowired
    public SqlSessionFactory sqlSessionFactory(@Qualifier(DataSource) DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MAPPER_LOCATIONS));
        return bean.getObject();
    }

    @Bean(name = PlatformTransactionManager)
    @Autowired
    public PlatformTransactionManager platformTransactionManager(@Qualifier(DataSource) DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean
    public FilterRegistrationBean filterRegistrationBean() {
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new WebStatFilter());
        filterRegistrationBean.addUrlPatterns("/*");
        filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
        return filterRegistrationBean;
    }

    @Value("${spring.datasource.db1.url}")
    private String spring_datasource_url;
    @Value("${spring.datasource.db1.username}")
    private String spring_datasource_username;
    @Value("${spring.datasource.db1.password}")
    private String spring_datasource_password;

    // 解決 spring.datasource.filters=stat,wall,log4j 無法正常注冊進去
    @ConfigurationProperties(prefix = DB_PREFIX)
    class IDataSourceProperties {
        private String url = spring_datasource_url;
        private String username = spring_datasource_username;
        private String password = spring_datasource_password;
        private String driverClassName;
        private int initialSize;
        private int minIdle;
        private int maxActive;
        private int maxWait;
        private int timeBetweenEvictionRunsMillis;
        private int minEvictableIdleTimeMillis;
        private String validationQuery;
        private boolean testWhileIdle;
        private boolean testOnBorrow;
        private boolean testOnReturn;
        private boolean poolPreparedStatements;
        private int maxPoolPreparedStatementPerConnectionSize;
        private String filters;
        private String connectionProperties;

        @Bean(name = DataSource)     //聲明其為Bean執行個體
//        @Primary  //在同樣的DataSource中,首先使用被标注的DataSource(分庫後多資料源不需要配置)
        public DataSource dataSource() {
            DruidDataSource datasource = new DruidDataSource();
            datasource.setUrl(url);
            datasource.setUsername(username);
            datasource.setPassword(password);
            datasource.setDriverClassName(driverClassName);

            //configuration
            datasource.setInitialSize(initialSize);
            datasource.setMinIdle(minIdle);
            datasource.setMaxActive(maxActive);
            datasource.setMaxWait(maxWait);
            datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
            datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
            datasource.setValidationQuery(validationQuery);
            datasource.setTestWhileIdle(testWhileIdle);
            datasource.setTestOnBorrow(testOnBorrow);
            datasource.setTestOnReturn(testOnReturn);
            datasource.setPoolPreparedStatements(poolPreparedStatements);
            datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
            try {
                datasource.setFilters(filters);
            } catch (SQLException e) {
                log.error("druid configuration initialization filter: " + e);
            }
            datasource.setConnectionProperties(connectionProperties);
            return datasource;
        }
           

以上每個類裡面的代碼基本一樣,不同之處在于不同的資料源掃描不同的mapper包與xml檔案路徑,進而通過調用不同包下的mapper時使用不同的連結源,確定在多個資料源下,通過不同的包來自動選擇資料源,需要操作哪個庫下面的資料就用哪個包下面的mapper(都是主庫,不是主從分離)

三,項目基本結構

springboot 配置多druid資料源
springboot 配置多druid資料源

db0和db1裡面的代碼表結構一模一樣,代碼有些備援,自己修改優化一下就好了

繼續閱讀