SpringBoot + Druid + Dynamic Datasource 多数据源配置

06-01 1063阅读

SpringBoot + Druid + Dynamic Datasource 多数据源配置

  • 1、依赖
  • 2、application.yml
  • 3、多数据源 Duid 自动装配详解
    • 3.1、自动装配 spring.datasource.dynamic
    • 3.2、自动装配多数据源 datasource
    • 3.3、自动装配每个数据源下的 duid 配置
    • 3.4、自动装配 StatViewServlet
    • 3.5、自动装配 WebStatFilter
    • 3.6、自动装配 AopPatterns
    • 3.7、Filter 配置类
    • 4、Druid 监控页面
      • 4.1、首页
      • 4.2、数据源列表
      • 4.2、SQL 监控
      • 4.3、SQL 防火墙
      • 4.4、Web 应用
      • 4.5、URI 监控
      • 4.6、Web Session 监控
      • 4.7、Spring 监控
      • 4.8、JSON API
      • 5、动态切换数据源
        • 5.1、数据源枚举
        • 5.2、Controller 层
        • 5.3、AOP 根据入参自动切换数据源
        • 6、日志输出效果

          1、依赖

               com.baomidou
               dynamic-datasource-spring-boot-starter
               4.3.1
               
                   
                       com.alibaba
                       druid-spring-boot-starter
                   
               
           
           
               com.alibaba
               druid-spring-boot-starter
               1.2.24
              MASTER("master"),
              SLAVE("slave");
              private String value;
              DataSourceEnum(String value) {
                  this.value = value;
              }
              public String getValue() {
                  return value;
              }
          }
          
                  @ApiImplicitParam(name = "envCode", value = "数据源标识", required = true, paramType = "query", example = "MASTER", dataTypeClass = DataSourceEnum.class),
                  @ApiImplicitParam(name = "query", value = "查询字符串", required = true, paramType = "query", example = "select * from chinapostoffice limit 100", dataTypeClass = String.class),
          })
          @GetMapping("/getChinaPostOffice ")
          public Response
              logger.info(">> query: {}", query);
              List list = customMapper.selectList(query);
              logger.info(">>> 总共 {} 条数据", list.size());
              logger.info(">>> 数据: {}", JSONArray.from(list, JSONWriter.Feature.WriteMapNullValue).toJSONString(JSONWriter.Feature.WriteMapNullValue));
              return new Response().success(JSONArray.from(list, JSONWriter.Feature.WriteMapNullValue));
          }
          

          5.3、AOP 根据入参自动切换数据源

          DynamicDataSourceContextHolder 实现原理,可参考源码,解析得很详细了

          SpringBoot + Druid + Dynamic Datasource 多数据源配置

          @Aspect
          @Component
          // 确保在事务切面之前执行
          @Order(Ordered.HIGHEST_PRECEDENCE)
          public class AutoSwitchDataSourceAop {
              private static final Logger logger = LoggerFactory.getLogger(AutoSwitchDataSourceAop.class);
              /**
               * 当前指定的默认数据源
               */
              @Value("${spring.datasource.dynamic.primary}")
              private String dynamicPrimaryDataSource;
              /**
               * 定义匹配需要切换数据源的方法的切点
               * 匹配com.github.wxhnyfy.dynamicdatasource.controller包、com.github.wxhnyfy.dynamicdatasource.impl.service包下所有包含DataSourceEnum参数的方法
               * 支持DataSourceEnum参数在任意参数位置(不限于第一个参数)
               *
               * @param joinPoint 切点
               * @return 目标执行方法
               * @throws Throwable 异常
               */
              @Around("execution(* com.github.wxhnyfy.dynamicdatasource.controller.*.*(com.github.wxhnyfy.dynamicdatasource.enums.DataSourceEnum, ..)) " +
                   "|| execution(* com.github.wxhnyfy.dynamicdatasource.impl.service.*.*(com.github.wxhnyfy.dynamicdatasource.enums.DataSourceEnum, ..))")
              public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
                  MethodSignature signature = (MethodSignature) joinPoint.getSignature();
                  String methodName = signature.getMethod().getName();
                  logger.info("进入 SwitchDataSourceAspect 的方法名: {}", methodName);
                  logger.debug("当前指定的默认数据源:{}", dynamicPrimaryDataSource);
                  DataSourceEnum envCode = null;
                  try {
                      // 获取方法参数中的EnvCode值
                      envCode = extractEnvCode(joinPoint);
                      // 切换数据源
                      if (envCode != null) {
                          logger.info("数据库环境标识:{}", envCode);
                          String previousDs = DynamicDataSourceContextHolder.peek();
                          logger.info("方法 [{}] 切换数据源: {} -> {}", methodName, previousDs, envCode.getValue());
                          DynamicDataSourceContextHolder.push(envCode.getValue());
                      }
                      // 执行目标方法
                      return joinPoint.proceed();
                  } finally {
                      // 清理数据源(恢复到默认数据源)
                      if (envCode != null) {
                          DynamicDataSourceContextHolder.clear();
                      }
                  }
              }
              /**
               * 通过反射获取方法参数
               * 自动识别DataSourceEnum类型的参数
               * 支持任意位置的DataSourceEnum参数
               *
               * @param joinPoint 切点
               * @return DataSourceEnum参数
               */
              private DataSourceEnum extractEnvCode(ProceedingJoinPoint joinPoint) {
                  MethodSignature signature = (MethodSignature) joinPoint.getSignature();
                  Parameter[] parameters = signature.getMethod().getParameters();
                  // 遍历参数查找EnvCode类型的参数
                  for (int i = 0; i  
          

          6、日志输出效果

          Mybatis-Plus 我们使用 org.apache.ibatis.logging.slf4j.Slf4jImpl 日志实现,配置对应的日志级别

          mybatis-plus:
            mapper-locations: classpath:mapper/*.xml
            configuration:
              log-impl: org.apache.ibatis.logging.slf4j.Slf4jImpl
          logging:
            level:
              root: info
              # 注意,logback不支持**匹配
              com.github.wxhnyfy.**.mapper: debug
              druid.sql.Statement: debug
          

          日志输出效果如下图

          SpringBoot + Druid + Dynamic Datasource 多数据源配置

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码