使用springboot + druid + mybatisplus完成多資料來源配置
阿新 • • 發佈:2021-11-09
最近專案中需要使用多個數據源完成業務,經過多方尋找資料和親自測試,現在整理一下資料。本文參考:https://www.cnblogs.com/hsbt2333/p/9347249.html
1.在yml中配置多個數據源訪問連線
server: port: 8099 #配置資料來源的屬性 spring: datasource: druid: db1: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/standarddb?useUnicode=true&characterEncoding=utf8&nullCatalogMeansCurrent=true&useSSL=false&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghaiusername: root password: ******** db2: url: jdbc:mysql://IP:3306/rebiaoserver?useUnicode=true&characterEncoding=UTF-8&useSSL=false&allowMultiQueries=true&rewriteBatchedStatements=true username: root password: ******** driver-class-name: com.mysql.cj.jdbc.Driver #監控配置 stat-view-servlet: enabled: true login-username: root login-password: roo #thymeleaf的配置 thymeleaf: cache: false enabled: true #設定開發環境 profiles: active: dev #時區轉換 jackson: date-format: yyyy-MM-dd HH:mm:ss time-zone: GMT+8 #redis redis: database:0 host: 127.0.0.1 #password: 123 port: 6379 timeout: 3000 # 連線超時時間 單位 ms(毫秒) # cluster: # nodes: 10.3.1.4:7000,10.3.1.4:7001,...,10.3.1.4:7008 #配置mybatisplus mybatis-plus: mapper-locations: - classpath:mapper/*/*Mapper.xml global-config: db-config: id-type: auto logic-delete-value: 1 logic-not-delete-value: 0 banner: true configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 分頁外掛 pagehelper: helperDialect: mysql reasonable: true supportMethodsArguments: true params: count=countSql
2. 建立資料來源列舉類DataSourceEnum
package com.ckfuture.pro.DBSource; /** * @description: 多資料來源列舉 * @author: CKFuture * @since: 2021-11-09 13:33 * @version: v1.0 * @LastEditTime: * @LastEditors: * @copyright: hrbckfuture.com */ public enum DataSourceEnum { DB1("db1"),DB2("db2"); private String value; DataSourceEnum(String value){this.value=value;} public String getValue() { return value; } }
3. 建立DataSourceContextHolder類
package com.ckfuture.pro.DBSource; public class DataSourceContextHolder { private static final ThreadLocal<String> contextHolder = new InheritableThreadLocal<>(); /** * 設定資料來源 * @param db */ public static void setDataSource(String db){ contextHolder.set(db); } /** * 取得當前資料來源 * @return */ public static String getDataSource(){ return contextHolder.get(); } /** * 清除上下文資料 */ public static void clear(){ contextHolder.remove(); } }
4. 建立MultipleDataSource類
package com.ckfuture.pro.DBSource; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; public class MultipleDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDataSource(); } }
5.建立DataSource註解
package com.ckfuture.pro.annotation; import com.ckfuture.pro.DBSource.DataSourceEnum; import java.lang.annotation.*; /** * @description: DataSource註解 * @author: CKFuture * @since: 2021-11-09 13:35 * @version: v1.0 * @LastEditTime: * @LastEditors: * @copyright: hrbckfuture.com */ @Target({ElementType.METHOD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface DataSource { DataSourceEnum value() default DataSourceEnum.DB1; }
6.建立DataSourceAspect類
package com.ckfuture.pro.DBSource; import com.ckfuture.pro.annotation.DataSource; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @Component @Slf4j @Aspect @Order(-1) public class DataSourceAspect { @Pointcut("@within(com.ckfuture.pro.annotation.DataSource) || @annotation(com.ckfuture.pro.annotation.DataSource)") public void pointCut(){ } @Before("pointCut() && @annotation(dataSource)") public void doBefore(DataSource dataSource){ log.info("選擇資料來源---"+dataSource.value().getValue()); DataSourceContextHolder.setDataSource(dataSource.value().getValue()); } @After("pointCut()") public void doAfter(){ DataSourceContextHolder.clear(); } }
7.建立配置類MyBatiesPlusConfiguration
package com.ckfuture.pro.config; import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder; /*import com.baomidou.mybatisplus.MybatisConfiguration; import com.baomidou.mybatisplus.entity.GlobalConfiguration; import com.baomidou.mybatisplus.mapper.LogicSqlInjector; import com.baomidou.mybatisplus.plugins.PaginationInterceptor; import com.baomidou.mybatisplus.plugins.PerformanceInterceptor; import com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean;*/ import com.baomidou.mybatisplus.core.MybatisConfiguration; import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean; import com.ckfuture.pro.DBSource.DataSourceEnum; import com.ckfuture.pro.DBSource.MultipleDataSource; import org.apache.ibatis.plugin.Interceptor; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.ibatis.type.JdbcType; import org.mybatis.spring.annotation.MapperScan; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Profile; import javax.sql.DataSource; import java.util.HashMap; import java.util.Map; @Configuration @MapperScan("com.ckfuture.pro.*.*.dao") public class MyBatiesPlusConfiguration { @Bean(name = "db1") @ConfigurationProperties(prefix = "spring.datasource.druid.db1" ) public DataSource db1() { return DruidDataSourceBuilder.create().build(); } @Bean(name = "db2") @ConfigurationProperties(prefix = "spring.datasource.druid.db2" ) public DataSource db2() { return DruidDataSourceBuilder.create().build(); } /** * 動態資料來源配置 * @return */ @Bean @Primary public DataSource multipleDataSource(@Qualifier("db1") DataSource db1, @Qualifier("db2") DataSource db2) { MultipleDataSource multipleDataSource = new MultipleDataSource(); Map< Object, Object > targetDataSources = new HashMap<>(); targetDataSources.put(DataSourceEnum.DB1.getValue(), db1); targetDataSources.put(DataSourceEnum.DB2.getValue(), db2); //新增資料來源 multipleDataSource.setTargetDataSources(targetDataSources); //設定預設資料來源 multipleDataSource.setDefaultTargetDataSource(db1); return multipleDataSource; } }
8.使用資料來源1
只需要在服務實現類的方法上添加註解@DataSource(DataSourceEnum.DB1)即可。
9.使用資料來源2
只需要在服務實現類的方法上添加註解@DataSource(DataSourceEnum.DB2)即可。
這裡本人拋磚引玉,個人建議還是儘量不要在springboot中使用多資料來源,第一是比較麻煩,第二是不安全,還是建議使用springcloud。