Spring Boot 初级入门教程(十九) —— 配置多数据源(附源码)
2020年03月20日 00:16:00 SpringBoot ⁄ 共 16100字 暂无评论 ⁄ 被围观 3,372次

距上篇文章《Spring Boot 初级入门教程(十八) —— 集成 MyBatis 另外一种开发方式》已跨了两个年头,时间确实有些久了!!!这么久没更新这个系列,一则由于自己确实忙了些,项目一个接一个的加班整;再者,由于项目需要,写了些其它方面的文章,比如关于 kafka、redis、IDEA 等。

另外,自己又买了个共享虚机,开通了尘封已久的博客,由于 .com 域名被别人抢注了,所以换成了 menglanglang.cn,如果有兴趣,也可以踩踩。

在开始这篇之前,首先要做的一件事,就是把原来的 demo 源码包中,包名换一下。因为原来一直是 com.menglanglang.xxx,现在换成 cn.menglanglang.xxx。如下:

另外,把代码中的原博客地址 http://blog.csdn.net/tzhuwb 换成 http://www.menglanglang.cn,纯属个人强迫症,理解。

言归正传,在项目开发中,我们常常会碰到一个服务配置多个数据源的情况,有些项目同时配置四五个 oracle,还配置着 mysql,gbase 等等。所以这篇主要说说如何简单的配置多数据源。

这里就简单以前面配置过的 oracle 和 mysql,同时配置到项目中,业务上同时操作不同的库来举例说明配置多数据源的步骤。

第一步,添加依赖包

在 pom 文件中,添加支持数据库连接池的 druid 依赖包,代码如下:

	<!-- 添加数据库连接池插件,支持多数据源 -->
	<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.17</version>
        </dependency>

 添加 Oracle 和 MySQL 依赖包,代码如下:

		<!-- mysql jdbc 插件 -->
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.46</version>
		</dependency>
		
		<!-- oracle jdbc 插件 -->
		<dependency>
			<groupId>com.oracle</groupId>
			<artifactId>ojdbc14</artifactId>
			<version>10.2.0.1.0</version>
		</dependency>

第二步,修改配置文件

在 application.properties 中,同时添加 oracle 数据库配置和 MySQL 数据库配置,分别用 first 和 second 来标识第一个和第二个数据源,代码如下所示:

  1. #################################  
  2. ## Oracle 数据库配置  
  3. #################################  
  4. # Oracle数据库连接  
  5. spring.datasource.first.url=jdbc:oracle:thin:@192.168.220.240:1521:orcl  
  6. # Oracle数据库用户名  
  7. spring.datasource.first.username=scott  
  8. # Oracle数据库密码  
  9. spring.datasource.first.password=123456  
  10. # Oracle数据库驱动(该配置可以不用配置,因为Spring Boot可以从url中为大多数数据库推断出它)  
  11. spring.datasource.first.driver-class-name=oracle.jdbc.OracleDriver  
  12.   
  13. #################################  
  14. ## MySQL 数据库配置  
  15. #################################  
  16. # MySQL数据库连接  
  17. spring.datasource.second.url=jdbc:mysql://192.168.220.240:3306/test_springboot?characterEncoding=UTF-8  
  18. # MySQL数据库用户名  
  19. spring.datasource.second.username=root  
  20. # MySQL数据库密码  
  21. spring.datasource.second.password=123456  
  22. # MySQL数据库驱动(该配置可以不用配置,因为Spring Boot可以从url中为大多数数据库推断出它)  
  23. spring.datasource.second.driver-class-name=com.mysql.jdbc.Driver  
  24.   
  25. #################################  
  26. ## 数据库共通配置  
  27. #################################  
  28. spring.datasource.max-active=10  
  29. spring.datasource.max-wait=10000  
  30. spring.datasource.min-idle=5  
  31. spring.datasource.initial-size=5  
  32. #spring.datasource.validation-query=SELECT 1 FROM DUAL  
  33. #spring.datasource.test-on-borrow=true  
  34. #spring.datasource.test-while-idle=true  
  35. #spring.datasource.time-between-eviction-runs-millis=18800  
  36. #spring.datasource.jdbc-interceptors=ConnectionState;SlowQueryReport(threshold=10000)  

第三步,添加配置类,分别读取数据库配置

创建一个包 config,分别创建 FirstDataSourceConfig 和 SecondDataSourceConfig,结构和代码如下:

FirstDataSourceConfig.java:

  1. package cn.menglanglang.test.springboot.config;  
  2.   
  3. import java.util.Objects;  
  4.   
  5. import javax.sql.DataSource;  
  6.   
  7. import org.apache.ibatis.session.SqlSessionFactory;  
  8. import org.mybatis.spring.SqlSessionFactoryBean;  
  9. import org.mybatis.spring.SqlSessionTemplate;  
  10. import org.springframework.beans.factory.annotation.Autowired;  
  11. import org.springframework.beans.factory.annotation.Qualifier;  
  12. import org.springframework.context.annotation.Bean;  
  13. import org.springframework.context.annotation.Configuration;  
  14. import org.springframework.context.annotation.Primary;  
  15. import org.springframework.core.env.Environment;  
  16. import org.springframework.core.io.support.PathMatchingResourcePatternResolver;  
  17. import org.springframework.jdbc.datasource.DataSourceTransactionManager;  
  18.   
  19. import com.alibaba.druid.pool.DruidDataSource;  
  20.   
  21. @Configuration  
  22. public class FirstDataSourceConfig {  
  23.   
  24.     @Autowired  
  25.     private Environment environment;  
  26.   
  27.     @Bean(name = "firstDataSource")  
  28.     @Primary  
  29.     public DataSource firstDataSource() {  
  30.         DruidDataSource dataSource = new DruidDataSource();  
  31.         String prefix = "spring.datasource";  
  32.         String prefixFirst = "spring.datasource.first";  
  33.         dataSource.setName("firstDataSource");  
  34.         dataSource.setDriverClassName(environment.getProperty(prefixFirst + ".driver-class-name").trim());  
  35.         dataSource.setUrl(environment.getProperty(prefixFirst + ".url").trim());  
  36.         dataSource.setUsername(environment.getProperty(prefixFirst + ".username").trim());  
  37.         dataSource.setPassword(environment.getProperty(prefixFirst + ".password").trim());  
  38.         dataSource.setMaxActive(Integer.parseInt(Objects.requireNonNull(environment.getProperty(prefix + ".max-active")).trim()));  
  39.         dataSource.setMinIdle(Integer.parseInt(Objects.requireNonNull(environment.getProperty(prefix + ".min-idle")).trim()));  
  40.         dataSource.setInitialSize(Integer.parseInt(Objects.requireNonNull(environment.getProperty(prefix + ".initial-size")).trim()));  
  41.         dataSource.setMaxWait(Long.parseUnsignedLong(Objects.requireNonNull(environment.getProperty(prefix + ".max-wait")).trim()));  
  42. //      dataSource.setTimeBetweenEvictionRunsMillis(Long.parseUnsignedLong(Objects.requireNonNull(environment.getProperty(prefix + ".time-between-eviction-runs-millis")).trim()));  
  43. //      dataSource.setMinEvictableIdleTimeMillis(Long.parseUnsignedLong(Objects.requireNonNull(environment.getProperty(prefix + ".min-evictable-idle-time-millis")).trim()));  
  44. //      dataSource.setTestWhileIdle(Boolean.parseBoolean(environment.getProperty(prefix + ".test-while-idle")));  
  45. //      dataSource.setTestOnBorrow(Boolean.parseBoolean(environment.getProperty(prefix + ".test-on-borrow")));  
  46. //      dataSource.setTestOnBorrow(Boolean.parseBoolean(environment.getProperty(prefix + ".test-on-return")));  
  47. //      dataSource.setTestOnBorrow(Boolean.parseBoolean(environment.getProperty(prefix + ".async-close-connection-enable")));  
  48. //      dataSource.setValidationQueryTimeout(Integer.parseInt(Objects.requireNonNull(environment.getProperty(prefix + ".validation-query-timeout")).trim()));  
  49. //      dataSource.setValidationQuery(environment.getProperty(prefix + ".validation-query"));  
  50.         return dataSource;  
  51.     }  
  52.   
  53.     @Bean(name = "firstTransactionManager")  
  54.     @Primary  
  55.     public DataSourceTransactionManager firstTransactionManager() {  
  56.         return new DataSourceTransactionManager(firstDataSource());  
  57.     }  
  58.   
  59.     @Bean(name = "firstSqlSessionFactory")  
  60.     @Primary  
  61.     public SqlSessionFactory firstSqlSessionFactory(@Qualifier("firstDataSource") DataSource dataSource) throws Exception {  
  62.         final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean() {  
  63.             {  
  64.                 setDataSource(dataSource);  
  65.                 setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:/mapper/oracle/**/*.xml"));  
  66.             }  
  67.         };  
  68.         return sessionFactory.getObject();  
  69.     }  
  70.   
  71.     @Bean(name = "firstSqlSessionTemplate")  
  72.     @Primary  
  73.     public SqlSessionTemplate firstSqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {  
  74.         return new SqlSessionTemplate(sqlSessionFactory);  
  75.     }  
  76.   
  77. }  

SecondDataSourceConfig.java:

  1. package cn.menglanglang.test.springboot.config;  
  2.   
  3. import java.util.Objects;  
  4.   
  5. import javax.sql.DataSource;  
  6.   
  7. import org.apache.ibatis.session.SqlSessionFactory;  
  8. import org.mybatis.spring.SqlSessionFactoryBean;  
  9. import org.mybatis.spring.SqlSessionTemplate;  
  10. import org.springframework.beans.factory.annotation.Autowired;  
  11. import org.springframework.beans.factory.annotation.Qualifier;  
  12. import org.springframework.context.annotation.Bean;  
  13. import org.springframework.context.annotation.Configuration;  
  14. import org.springframework.core.env.Environment;  
  15. import org.springframework.core.io.support.PathMatchingResourcePatternResolver;  
  16. import org.springframework.jdbc.datasource.DataSourceTransactionManager;  
  17.   
  18. import com.alibaba.druid.pool.DruidDataSource;  
  19.   
  20. @Configuration  
  21. public class SecondDataSourceConfig {  
  22.   
  23.     @Autowired  
  24.     private Environment environment;  
  25.   
  26.     @Bean(name = "secondDataSource")  
  27.     public DataSource secondDataSource() {  
  28.         DruidDataSource dataSource = new DruidDataSource();  
  29.         String prefix = "spring.datasource";  
  30.         String prefixSecond = "spring.datasource.second";  
  31.         dataSource.setName("secondDataSource");  
  32.         dataSource.setDriverClassName(environment.getProperty(prefixSecond + ".driver-class-name").trim());  
  33.         dataSource.setUrl(environment.getProperty(prefixSecond + ".url").trim());  
  34.         dataSource.setUsername(environment.getProperty(prefixSecond + ".username").trim());  
  35.         dataSource.setPassword(environment.getProperty(prefixSecond + ".password").trim());  
  36.         dataSource.setMaxActive(Integer.parseInt(Objects.requireNonNull(environment.getProperty(prefix + ".max-active")).trim()));  
  37.         dataSource.setMinIdle(Integer.parseInt(Objects.requireNonNull(environment.getProperty(prefix + ".min-idle")).trim()));  
  38.         dataSource.setInitialSize(Integer.parseInt(Objects.requireNonNull(environment.getProperty(prefix + ".initial-size")).trim()));  
  39.         dataSource.setMaxWait(Long.parseUnsignedLong(Objects.requireNonNull(environment.getProperty(prefix + ".max-wait")).trim()));  
  40. //      dataSource.setTimeBetweenEvictionRunsMillis(Long.parseUnsignedLong(Objects.requireNonNull(environment.getProperty(prefix + ".time-between-eviction-runs-millis")).trim()));  
  41. //      dataSource.setMinEvictableIdleTimeMillis(Long.parseUnsignedLong(Objects.requireNonNull(environment.getProperty(prefix + ".min-evictable-idle-time-millis")).trim()));  
  42. //      dataSource.setTestWhileIdle(Boolean.parseBoolean(environment.getProperty(prefix + ".test-while-idle")));  
  43. //      dataSource.setTestOnBorrow(Boolean.parseBoolean(environment.getProperty(prefix + ".test-on-borrow")));  
  44. //      dataSource.setTestOnBorrow(Boolean.parseBoolean(environment.getProperty(prefix + ".test-on-return")));  
  45. //      dataSource.setTestOnBorrow(Boolean.parseBoolean(environment.getProperty(prefix + ".async-close-connection-enable")));  
  46. //      dataSource.setValidationQueryTimeout(Integer.parseInt(Objects.requireNonNull(environment.getProperty(prefix + ".validation-query-timeout")).trim()));  
  47. //      dataSource.setValidationQuery(environment.getProperty(prefix + ".validation-query"));  
  48.         return dataSource;  
  49.     }  
  50.   
  51.     @Bean(name = "secondTransactionManager")  
  52.     public DataSourceTransactionManager secondTransactionManager() {  
  53.         return new DataSourceTransactionManager(secondDataSource());  
  54.     }  
  55.   
  56.     @Bean(name = "secondSqlSessionFactory")  
  57.     public SqlSessionFactory secondSqlSessionFactory(@Qualifier("secondDataSource") DataSource dataSource) throws Exception {  
  58.         final SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean() {  
  59.             {  
  60.                 setDataSource(dataSource);  
  61.                 setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath*:/mapper/mysql/**/*.xml"));  
  62.             }  
  63.         };  
  64.         return sessionFactory.getObject();  
  65.     }  
  66.   
  67.     @Bean(name = "secondSqlSessionTemplate")  
  68.     public SqlSessionTemplate secondSqlSessionTemplate(@Qualifier("secondSqlSessionFactory") SqlSessionFactory sqlSessionFactory) {  
  69.         return new SqlSessionTemplate(sqlSessionFactory);  
  70.     }  
  71.   
  72. }  

第四步,扩展数据库接口查询封装类

接口查询封装类 DaoHelper.java,放在 common 包下,接口如下:

FirstDaoHelper.java:

  1. package cn.menglanglang.test.springboot.common;  
  2.   
  3. import java.util.List;  
  4. import java.util.Map;  
  5.   
  6. import org.apache.ibatis.session.SqlSessionFactory;  
  7. import org.mybatis.spring.SqlSessionTemplate;  
  8. import org.springframework.beans.factory.annotation.Autowired;  
  9. import org.springframework.beans.factory.annotation.Qualifier;  
  10. import org.springframework.stereotype.Component;  
  11.   
  12. /** 
  13.  * @desc 数据库查询封装 
  14.  * 
  15.  * @see 封装了基本的查询方法,包括增删改查分页查等。 使用此类时,使用 @Resource 或 @Autowired 注解注入。 
  16.  * @author 孟郎郎 
  17.  * @blog http://www.menglanglang.cn 
  18.  * @version 1.0 
  19.  * @date 2020年3月19日下午11:02:03 
  20.  */  
  21. @Component  
  22. public class FirstDaoHelper {  
  23.   
  24.     @Autowired  
  25.     @Qualifier("firstSqlSessionTemplate")  
  26.     private SqlSessionTemplate sqlSessionTemplate;  
  27.   
  28.     public FirstDaoHelper(SqlSessionTemplate sqlSessionTemplate) {  
  29.         this.sqlSessionTemplate = sqlSessionTemplate;  
  30.     }  
  31.   
  32.     /** 
  33.      * 获取sqlsession factory 
  34.      */  
  35.     public SqlSessionFactory getSqlSessionFactory() {  
  36.         return this.sqlSessionTemplate.getSqlSessionFactory();  
  37.     }  
  38.   
  39.     // 这部分和前篇文章中的DaoHelper完全一样,在此省略。。。  
  40.   
  41. }  

SecondDaoHelper.java:

  1. package cn.menglanglang.test.springboot.common;  
  2.   
  3. import java.util.List;  
  4. import java.util.Map;  
  5.   
  6. import org.apache.ibatis.session.SqlSessionFactory;  
  7. import org.mybatis.spring.SqlSessionTemplate;  
  8. import org.springframework.beans.factory.annotation.Autowired;  
  9. import org.springframework.beans.factory.annotation.Qualifier;  
  10. import org.springframework.stereotype.Component;  
  11.   
  12. /** 
  13.  * @desc 数据库查询封装 
  14.  * 
  15.  * @see 封装了基本的查询方法,包括增删改查分页查等。 使用此类时,使用 @Resource 或 @Autowired 注解注入。 
  16.  * @author 孟郎郎 
  17.  * @blog http://www.menglanglang.cn 
  18.  * @version 1.0 
  19.  * @date 2020年3月19日下午11:01:34 
  20.  */  
  21. @Component  
  22. public class SecondDaoHelper {  
  23.   
  24.     @Autowired  
  25.     @Qualifier("secondSqlSessionTemplate")  
  26.     private SqlSessionTemplate sqlSessionTemplate;  
  27.   
  28.     public SecondDaoHelper(SqlSessionTemplate sqlSessionTemplate) {  
  29.         this.sqlSessionTemplate = sqlSessionTemplate;  
  30.     }  
  31.   
  32.     /** 
  33.      * 获取sqlsession factory 
  34.      */  
  35.     public SqlSessionFactory getSqlSessionFactory() {  
  36.         return this.sqlSessionTemplate.getSqlSessionFactory();  
  37.     }  
  38.   
  39.     // 这部分和前篇文章中的DaoHelper完全一样,在此省略。。。  
  40.   
  41. }  

第五步,修改测试类、接口类、实现类及 xml 文件

这步骤相当于把《Spring Boot 初级入门教程(十五) —— 集成 MyBatis》和《Spring Boot 初级入门教程(十八) —— 集成 MyBatis 另外一种开发方式》中的代码合并一起,这里就不再详细贴了,可以直接下载打包好的源码查看即可。

分别为:MyBatisController3.java、MyBatisService3.java、MyBatisServiceImpl3.java、mybati-mapper3.xml。

第六步,测试

启动项目,分别访问以下路径,可以看到原来 Oracle 和 MySQL 的接口都可以拿到数据。

可以看到与原来的测试结果完全一致,所以可以同时使用两个数据源配置。

到此,多数据源简单配置步骤结束。^ ^

但一般项目中用到最多,也是最难的部分,是各个数据源参数的配置,以达到访问效率最优,需要结合服务部署机器资源配置,数据库配置,并发访问量等各个指标,来调节数据源参数。这里把常常用到的参数顺便罗列一下,便于服务调优查询。

yml 配置文件格式:

  1. druid:  
  2.       access-to-underlying-connection-allowed: false #允许访问底层连接  
  3.       active-connection-stack-trace:  #活跃连接堆跟踪  
  4.       active-connections: #活跃连接列表  
  5.       aop-patterns: #AOP模式  
  6.       async-close-connection-enable: false #启用异步关闭连接  
  7.       async-init: false #异步初始化  
  8.       break-after-acquire-failure: false #失败后跳过  
  9.       clear-filters-enable: false #启动清除过滤器  
  10.       connect-properties:   #连接配置  
  11.       connection-error-retry-attempts: 1 #连接出错尝试几次重新连接  
  12.       connection-init-sqls:   #连接初始化语句  
  13.       connection-properties:  #连接属性  
  14.       create-scheduler:   #创建程序  
  15.       db-type:  #DB类型  
  16.       default-auto-commit: false #默认自动提交  
  17.       default-catalog:  #默认目录  
  18.       default-read-only: false #默认只读  
  19.       default-transaction-isolation: 1 #默认事务隔离  
  20.       destroy-scheduler:  #销毁程序  
  21.       driver:   #驱动类  
  22.       driver-class-name:  #驱动类名  
  23.       dup-close-log-enable: true #启用DUP关闭日志  
  24.       enable: true #启动连接池  
  25.       exception-sorter:   
  26.       exception-sorter-class-name:   
  27.       fail-fast: true #快速失败?  
  28.       filter-class-names: #过滤器类名称  

properties 配置文件格式:

  1. #连接池属性  
  2.   
  3. spring.datasource.druid.initial-size=15  
  4. spring.datasource.druid.max-active=100  
  5. spring.datasource.druid.min-idle=15  
  6. spring.datasource.druid.max-wait=60000  
  7. spring.datasource.druid.time-between-eviction-runs-millis=60000  
  8. spring.datasource.druid.min-evictable-idle-time-millis=300000  
  9. spring.datasource.druid.test-on-borrow=false  
  10. spring.datasource.druid.test-on-return=false  
  11. spring.datasource.druid.test-while-idle=true  
  12. spring.datasource.druid.validation-query=SELECT 1 FROM DUAL  
  13. spring.datasource.druid.validation-query-timeout=1000  
  14. spring.datasource.druid.keep-alive=true  
  15. spring.datasource.druid.remove-abandoned=true  
  16. spring.datasource.druid.remove-abandoned-timeout=180  
  17. spring.datasource.druid.log-abandoned=true  
  18. spring.datasource.druid.pool-prepared-statements=true  
  19. spring.datasource.druid.max-pool-prepared-statement-per-connection-size=20  
  20. spring.datasource.druid.filters=stat,wall,slf4j  
  21. spring.datasource.druid.use-global-data-source-stat=true  
  22. spring.datasource.druid.preparedStatement=true  
  23. spring.datasource.druid.maxOpenPreparedStatements=100  
  24. spring.datasource.druid.connect-properties.mergeSql=true  
  25. spring.datasource.druid.connect-properties.slowSqlMillis=5000  

属性说明:

源码下载:https://pan.baidu.com/s/1jA_EDzoUeXhgNA-e7wsnYA (提取码:4i84)

​原文链接: https://blog.csdn.net/tzhuwb/article/details/104956070

给我留言

留言无头像?