Spring Boot 整合 AbstractRoutingDataSource 切换数据源无效
问题相关代码
@Aspect
@Component
public class DataSourceAspect {
@Before(value = "@annotation(com.kiku.config.SwitchSource)")
public void beforeOpt(JoinPoint joinPoint) {
/*因为是对注解进行切面,所以这边无需做过多判定,直接获取注解的值,进行环绕,将数据源设置成远方,然后结束后,清楚当前线程数据源*/
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
SwitchSource switchSource = method.getAnnotation(SwitchSource.class);
DataSourceHolder.setDataSource(switchSource.value());
}
@After(value = "@annotation(com.kiku.config.SwitchSource)")
public void afterOpt() {
DataSourceHolder.clearDataSource();
}
}
@Target(ElementType.METHOD)
@Retention(value = RetentionPolicy.RUNTIME)
@Documented
public @interface SwitchSource {
String DEFAULT_NAME = "testDataSource";
String value() default DEFAULT_NAME;
}
public class DataSourceHolder {
private static final ThreadLocal<String> dataSources = new InheritableThreadLocal<>();
/**
* 设置数据源
*/
public static void setDataSource(String datasource) {
dataSources.set(datasource);
}
/**
* 获取数据源
*/
public static String getDataSource() {
return dataSources.get();
}
/**
* 清除数据源
*/
public static void clearDataSource() {
dataSources.remove();
}
}
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceHolder.getDataSource();
}
public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
super.setDefaultTargetDataSource(defaultTargetDataSource);
super.setTargetDataSources(targetDataSources);
super.afterPropertiesSet();
}
}
@ConfigurationProperties(prefix = "spring.datasource")
public class MybatisConfig {
private String url;
private String username;
private String password;
private String driverClassName;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getDriverClassName() {
return driverClassName;
}
public void setDriverClassName(String driverClassName) {
this.driverClassName = driverClassName;
}
}
@Configuration
@EnableConfigurationProperties(MybatisConfig.class)
public class MyBatisMapperScannerConfig {
@Autowired
private MybatisConfig mybatisConfig;
private static String MAPPER_LOCATOIN = "classpath*:/mapper/*.xml";
@Bean(name = "dataSource")
public DataSource dataSource() {
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setUrl(mybatisConfig.getUrl());
druidDataSource.setUsername(mybatisConfig.getUsername());
druidDataSource.setDriverClassName(mybatisConfig.getDriverClassName());
druidDataSource.setPassword(mybatisConfig.getPassword());
return druidDataSource;
}
@Bean("sqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MAPPER_LOCATOIN));
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
// 自动将数据库中的下划线转换为驼峰格式
configuration.setMapUnderscoreToCamelCase(true);
configuration.setDefaultFetchSize(100);
configuration.setDefaultStatementTimeout(30);
sqlSessionFactoryBean.setConfiguration(configuration);
return sqlSessionFactoryBean.getObject();
}
}
@Configuration
public class TestMybatisConfig {
private static String MAPPER_LOCATOIN = "classpath*:/mapper/*.xml";
@Bean(name = "testDataSource")
@ConfigurationProperties(prefix = "spring.datasource.test")
public DataSource hisDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "dynamicDataSource")
public DynamicDataSource dynamicDataSource(@Qualifier("dataSource") DataSource dataSource, @Qualifier("testDataSource") DataSource hisDataSource) {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put("testDataSource", hisDataSource);
return new DynamicDataSource(dataSource, targetDataSources);
}
@Bean("sqlSessionFactory2")
@Primary
public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MAPPER_LOCATOIN));
org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
// 自动将数据库中的下划线转换为驼峰格式
configuration.setMapUnderscoreToCamelCase(true);
configuration.setDefaultFetchSize(100);
configuration.setDefaultStatementTimeout(30);
sqlSessionFactoryBean.setConfiguration(configuration);
return sqlSessionFactoryBean.getObject();
}
}
RestController
public class TestController {
@Autowired
private TestDao dao;
@RequestMapping("test01")
public String test01() {
String name = dao.selectTest();
return name;
}
@RequestMapping("test02")
@SwitchSource
public String test02() {
String name = dao.selectTest();
return name;
}
}
<select id="selectTest" resultType="java.lang.String">
select name from kiku
</select>
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/test?useUnicode\=true&characterEncoding\=UTF-8&zeroDateTimeBehavior\=convertToNull&useSSL\=false&allowMultiQueries\=true&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.test.jdbc-url=jdbc:mysql://127.0.0.1:3306/testversionup?useUnicode\=true&characterEncoding\=UTF-8&zeroDateTimeBehavior\=convertToNull&useSSL\=false&allowMultiQueries\=true&serverTimezone=Asia/Shanghai
spring.datasource.test.username=root
spring.datasource.test.password=root
spring.datasource.test.driver-class-name=com.mysql.jdbc.Driver