天天看点

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里面的代码表结构一模一样,代码有些冗余,自己修改优化一下就好了

继续阅读