當一個項目中需要調用兩個數據庫時,這個時候就需要配置雙數據源。
先配置配置文件
然后再Application類上加入:
@SpringBootApplication( exclude = { DataSourceAutoConfiguration.class } )這個注解去除掉默認的數據庫配置,然后我們自己去配置database.
DataSourceConfig類:
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.jdbc.DataSourceBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; import javax.sql.DataSource; import java.util.HashMap; import java.util.Map; /** * @Author: ch * @Date: 2018/6/27 11:06 * @Description: */ @Configuration public class DataSourceConfig { @Bean(name = "db") @ConfigurationProperties(prefix = "spring.datasource.db") public DataSource dataSource1() { return DataSourceBuilder.create().build(); } @Bean(name = "db2") @ConfigurationProperties(prefix = "spring.datasource.db2") public DataSource dataSource2() { return DataSourceBuilder.create().build(); } /** * 動態數據源: 通過AOP在不同數據源之間動態切換 * * @return */ @Primary @Bean(name = "dynamicDS1") public DataSource dataSource() { DynamicDataSource dynamicDataSource = new DynamicDataSource(); // 默認數據源 dynamicDataSource.setDefaultTargetDataSource(dataSource1()); // 配置多數據源 Map<Object, Object> dsMap = new HashMap(5); dsMap.put("db", dataSource1()); dsMap.put("db2", dataSource2()); dynamicDataSource.setTargetDataSources(dsMap); return dynamicDataSource; } /** * 配置@Transactional注解事物 * @return */ @Bean public PlatformTransactionManager transactionManager() { return new DataSourceTransactionManager(dataSource()); } }
DynamicDataSource 類
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; /** * @Author: ch * @Date: 2018/6/27 11:40 * @Description: */ public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DataSourceContextHolder.getDB(); } }
DynamicDataSourceAspect 類
import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; import java.lang.reflect.Method; /** * @Author: ch * @Date: 2018/6/27 11:48 * @Description: */ @Aspect @Component public class DynamicDataSourceAspect { @Before("@annotation(DS)") public void beforeSwitchDS(JoinPoint point){ //獲得當前訪問的class Class<?> className = point.getTarget().getClass(); //獲得訪問的方法名 String methodName = point.getSignature().getName(); //得到方法的參數的類型 Class[] argClass = ((MethodSignature)point.getSignature()).getParameterTypes(); String dataSource = DataSourceContextHolder.DEFAULT_DS; try { // 得到訪問的方法對象 Method method = className.getMethod(methodName, argClass); // 判斷是否存在@DS注解 if (method.isAnnotationPresent(DS.class)) { DS annotation = method.getAnnotation(DS.class); // 取出注解中的數據源名 dataSource = annotation.value(); } } catch (Exception e) { e.printStackTrace(); } // 切換數據源 DataSourceContextHolder.setDB(dataSource); } @After("@annotation(DS)") public void afterSwitchDS(JoinPoint point){ DataSourceContextHolder.clearDB(); } }
DataSourceContextHolder 類
public class DataSourceContextHolder { /** * 默認數據源 */ public static final String DEFAULT_DS = "db"; private static final ThreadLocal<String> contextHolder = new ThreadLocal<>(); // 設置數據源名 public static void setDB(String dbType) { contextHolder.set(dbType); } // 獲取數據源名 public static String getDB() { return (contextHolder.get()); } // 清除數據源名 public static void clearDB() { contextHolder.remove(); } }
DS 類
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * @Author: ch * @Date: 2018/6/27 11:47 * @Description: */ @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.METHOD }) public @interface DS { String value() default "db"; }
默認的數據庫在調用的時候不用加任何的東西,按照正常的方式去使用即可,而使用到第二個數據庫的serviceImpl的方法上加上
@DS("db2")即可,這樣這個方法中的mapper文件就會調用不是默認的那個數據庫了。
轉載至https://blog.csdn.net/haha_66666/article/details/81507416