当一个项目中需要调用两个数据库时,这个时候就需要配置双数据源。
先配置配置文件
然后再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