从零搭建SpringBoot后台框架(十二)——多数据源

240 阅读5分钟

一、本节说明

  1. 本文介绍如何介入多数据源,包含配置、使用
  2. 本文升级了druid版本到1.2.20
  3. 动态数据源在同一个Spring事务中不能切换,需要去掉其中的Spring事务,使用自定义的@DSTransactional

二、引入依赖

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>4.1.3</version>
</dependency>

本节升级druid到1.2.20版本

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.20</version>
</dependency>

三、使用@DS切换数据源

@Service
@DS("system")
public class SystemLogServiceImpl extends ServiceImpl<SystemLogMapper, SystemLog> implements SystemLogService {

}
@Service
@DS("user")
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

}

四、配置数据源

  1. 配置了system和user两个数据源
  2. 指定了默认数据源为system
  3. druid的监控配置web-stat-filterstat-view-servlet保持层级不变
  4. spring.datasource.dynamic.druid连接池配置,配置默认后,所有数据源可以共用,也可以单独配置(本文都是mysql数据源,无需独立配置)
spring:
  datasource:
    druid:
      ###监控配置-开始###
      # WebStatFilter配置,说明请参考Druid Wiki,配置_配置WebStatFilter
      web-stat-filter:
        #是否启用StatFilter,默认值false
        enabled: true
        #需要拦截的url
        url-pattern: /*
        #过滤器忽略的资源类型
        exclusions: "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"
        #是否开启session统计功能,默认值false
        session-stat-enable: true
        #session统计最大值
        session-stat-max-count: 1000
        #session用户信息
        principal-session-name:
        #session用户cookie名称
        principal-cookie-name:
        #监控单个url调用的sql列表
        profile-enable: true
      # StatViewServlet配置,说明请参考Druid Wiki,配置_StatViewServlet配置
      stat-view-servlet:
        #是否启用StatViewServlet(监控页面)默认值为false(考虑到安全问题默认并未启动,如需启用建议设置密码或白名单以保障安全)
        enabled: true
        #监控页面拦截url
        url-pattern: /druid/*
        #是否启用重置功能
        reset-enable: false
        #监控页面登录用户名
        login-username: admin
        #监控页面登录用户密码
        login-password: admin
        #StatViewSerlvet展示出来的监控信息比较敏感,是系统运行的内部情况,如果你需要做访问控制,可以配置allow和deny这两个参数
        #deny优先于allow,如果在deny列表中,就算在allow列表中,也会被拒绝。如果allow没有配置或者为空,则允许所有访问
        #配置的格式
        #<IP>或者<IP>/<SUB_NET_MASK_size>其中128.242.127.1/24,配置多个英文逗号分隔
        #24表示,前面24位是子网掩码,比对的时候,前面24位相同就匹配,不支持IPV6。
        #监控页面白名单
        allow:
        #黑名单
        deny:
        #Spring监控配置,说明请参考Druid Github Wiki,配置_Druid和Spring关联监控配置
        #aop-patterns: com.demo.*.service.* #Spring监控AOP切入点,如x.y.z.service.*,配置多个英文逗号分隔
      ###监控配置-结束###
    dynamic:
      #设置默认的数据源或者数据源组,默认值即为master
      primary: system
      #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
      strict: false
      datasource:
        system:
          url: jdbc:mysql://localhost:3306/demo_system?useSSL=false
          username: root
          password: 123456
          driver-class-name: com.mysql.cj.jdbc.Driver
        user:
          url: jdbc:mysql://localhost:3306/demo?useSSL=false
          username: root
          password: 123456
          driver-class-name: com.mysql.cj.jdbc.Driver
      druid:
        ###连接池配置-开始###
        initial-size: 5
        min-idle: 5
        max-active: 20
        #连接等待超时时间
        max-wait: 60000
        #是否缓存preparedStatement,也就是PSCache。PSCache对支持游标的数据库性能提升巨大,比如说oracle。
        #在mysql5.5以下的版本中没有PSCache功能,建议关闭掉。5.5及以上版本有PSCache,建议开启。
        pool-prepared-statements: true
        #配置PSCache的大小
        max-pool-prepared-statement-per-connection-size: 20
        #用来检测连接是否有效的sql,要求是一个查询语句,常用SELECT 1 FROM DUAL
        validation-query: select 1 from dual
        #检测连接是否有效的超时时间,单位是秒。底层调用jdbc Statement对象的void setQueryTimeout(int seconds)方法
        validation-query-timeout: 3000
        #是否在连接池空闲一段时间后检验连接有效性
        test-while-idle: true
        #申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能
        test-on-borrow: false
        #是否在归还到池中前进行检验
        test-on-return: false
        #间隔多久进行一次检测,检测需要关闭的空闲连接,单位毫秒
        time-between-eviction-runs-millis: 60000
        #一个连接在池中最小生存的时间,单位是毫秒
        min-evictable-idle-time-millis: 300000
        #配置连接池中连接,在时间段内一直空闲,被逐出连接池的时间,单位毫秒。在minEvictableIdleTimeMillis基础上扩展,
        #会在minEvictableIdleTimeMillis基础上判断连接是否空闲(默认逐出时间就是minEvictableIdleTimeMillis)
        max-evictable-idle-time-millis: 600000
        #配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
        filters: stat,wall,log4j
        #是否使用统计
        use-global-data-source-stat: true
        #通过connectProperties属性来打开mergeSql功能;慢SQL记录
        connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
        ###连接池配置-结束###

五、功能验证

  1. 新建demo_system数据库,在其中新建system_log表
  2. 运行项目,调用system和user的增删改查接口,可以发现分表使用的是demo_system.system_log和demo.user表,实现了多个数据源的使用

六、注意事项

  1. @DS是基于AOP实现的,必须通过类+方法的方式调用才会生效;
  2. @DSTransactionalMybatis Plus内置的ServiceImpl在新增,更改,删除等一些批量操作方法上自带事物导致不能切换数据源。可以通过复制出源码,删除其中的事务注解,继承这个新的ServiceImpl即可;也可以创建一个新的方法(推荐),去掉其Spring事务注解,添加@DS即可
  3. 建议仅在同一个连接需要访问多个数据源时,才使用@DSTransactional,确认不存在数据源切换的业务操作,建议使用原生的Spring事务。

七、项目地址

gitee

PS:可以通过tag下载本文对应的代码版本

八、结尾

多数据源已完成,有问题可以联系chenzhenlindx@qq.com

九、参考文章

  1. 从零搭建自己的SpringBoot后台框架(十一)
  2. 多数据源