前言:
随着应用用户数量的增加,相应的并发请求的数量也会跟着不断增加,慢慢地,单个数据库已经没有办法满足我们频繁的数据库操作请求了,在某些场景下,我们可能会需要配置多个数据源,使用多个数据源(例如实现数据库的读写分离)来缓解系统的压力等,同样的,Springboot官方提供了相应的实现来帮助开发者们配置多数据源,一般分为两种方式(目前我所了解到的),分包和AOP,而在上一篇文章Springboot +Mybatis实现多数据源配置中,我们实现了静态多数据源的配置,但是这种怎么说呢,在实际的使用中不够灵活,为了解决这个问题呢,我们可以使用上文提到的第二种方法,即使用AOP面向切面编程的方式来实现在不同数据源之间动态切换的目的。
2. 环境准备:
首先新建一个Springboot项目,我这里版本是2.1.7.RELEASE,并在pom文件中引入相关依赖,和上次相比,这次主要额外新增了aop相关的依赖,如下:
<dependency>
3.代码部分
首先呢,在我们Springboot的配置文件中配置我们的datasourse,和以往不一样的是,因为我们有两个数据源,所以要指定相关数据库的名称,其中主数据源为primary,次数据源为secondary如下:
#配置主数据库
spring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/testdatasource1?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false
spring.datasource.primary.username=root
spring.datasource.primary.password=root
spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driver
##配置次数据库
spring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/testdatasource2?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false
spring.datasource.secondary.username=root
spring.datasource.secondary.password=root
spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
spring.http.encoding.force=true
需要我们注意的是,Springboot2.0 在配置数据库连接的时候需要使用jdbc-url,如果只使用url的话会报
jdbcUrl is required with driverClassName.错误。
新建一个配置文件,DynamicDataSourceConfig 用来配置我们相关的bean,代码如下
@Configuration
而在这所有的配置中,最核心的地方就是DynamicDataSource这个类了,DynamicDataSource是我们自定义的动态切换数据源的类,该类继承了AbstractRoutingDataSource 类并重写了它的determineCurrentLookupKey()方法。
AbstractRoutingDataSource 类内部维护了一个名为targetDataSources的Map,并提供的setter方法用于设置数据源关键字与数据源的关系,实现类被要求实现其determineCurrentLookupKey()方法,由此方法的返回值决定具体从哪个数据源中获取连接。同时AbstractRoutingDataSource类提供了程序运行时动态切换数据源的方法,在dao类或方法上标注需要访问数据源的关键字,路由到指定数据源,获取连接。
DynamicDataSource代码如下:
public
DataSourceType类的代码如下:
public
接下来编写我们相关的Mapper和xml文件,代码如下:
@Component
相关接口文件编写好之后,就可以编写我们的aop代码了:
@Aspect
编写我们的测试 UserController: 代码如下:
@RestController
4. 测试:
启动项目,在浏览器中分别输入http://127.0.0.1:8080/primary 和http://127.0.0.1:8080/primary ,结果如下:
[{
5.等等
等等,啧啧啧,我看你这不行啊,还不够灵活,几个菜啊,喝成这样,这就算灵活了?
那肯定不能的,aop也有aop的好处,比如两个包下的代码分别用两个不同的数据源,就可以直接用aop表达式就可以完成了,但是,如果想本例中方法级别的拦截,就显得优点不太灵活了,这个适合就需要我们的注解上场了。
6.配合注解实现
首先自定义我们的注解 @DataSource
/**
通过使用aop拦截,获取注解的属性value的值。如果value的值并没有在我们DataBaseType里面,则使用我们默认的数据源,如果有的话,则切换为相应的数据源。
@Aspect
7 .测试:
修改我们的mapper,添加我们的自定义的@DataSouse注解,并注解掉我们DataSourceAop类里面的内容。如下:
@Component
启动项目,在浏览器中分别输入http://127.0.0.1:8080/primary 和http://127.0.0.1:8080/primary ,结果如下:
[{
到此,就算真正的大功告成啦。
最后的最后,大家好,我是韩数,哼,关注我,有你好果子吃(叉腰)。
记得点个赞再走哦~
等一下:
相关源码欢迎去我的github下载(欢迎star): https:// github.com/hanshuaikang /Spring-Note