需求:当前模块数据由A库获取插入B库,需要连接两个数据源
实现:采用AOP形式实现多数据源切换功能
实现步骤
一:于 application.properties 定义数据源配置
test1 database
spring.datasource.host.url=jdbc:mysql://127.0.0.1:3306/host?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false
spring.datasource.host.username=host
spring.datasource.host.password=host
spring.datasource.host.driver-class-name=com.mysql.jdbc.Driver
test2 database
spring.datasource.second.url=jdbc:mysql://127.0.0.x:3306/second?useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true&useSSL=false
spring.datasource.second.username=second
spring.datasource.second.password=second
spring.datasource.second.driver-class-name=com.mysql.jdbc.Driver
二:启动类配置去除数据库自动装配
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class,HibernateJpaAutoConfiguration.class})
@EnableEurekaClient
@EnableDHRestful
@ComponentScan(basePackages = { "com.dh.common.restful.controller","com.dh.xxx.handle","com.dh.xxx.datasource" })
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application .class, args);
}
}
三:编写数据源切换的AOP实现类
@Aspect
@Component
public class DataSourceAop {
//该注解为指定包中方法前缀为 host的方法运行前进入
@Before("execution(* com.dh.XXX.handle..*.host*(..))")
public void setDataSourceHost() {
DataSourceType.setDataBaseType(DataBaseType.HOST);
}
//该注解为指定包中方法前缀为 second的方法运行前进入
@Before("execution(* com.dh.XXX.handle..*.second*(..))")
public void setDataSourceSecond() {
DataSourceType.setDataBaseType(DataBaseType.SECOND);
}
}
四:编写数据源类型Class
public class DataSourceType {
public enum DataBaseType {
HOST, SECOND
}
// 使用ThreadLocal保证线程安全
private static final ThreadLocal<DataBaseType> TYPE = new ThreadLocal<DataBaseType>();
// 往当前线程里设置数据源类型
public static void setDataBaseType(DataBaseType dataBaseType) {
if (dataBaseType == null) {
throw new NullPointerException();
}
System.err.println("[将当前数据源改为]:" + dataBaseType);
TYPE.set(dataBaseType);
}
// 获取数据源类型
public static DataBaseType getDataBaseType() {
DataBaseType dataBaseType = TYPE.get() == null ? DataBaseType.HOST : TYPE.get();
System.err.println("[获取当前数据源的类型为]:" + dataBaseType);
return dataBaseType;
}
// 清空数据类型
public static void clearDataBaseType() {
TYPE.remove();
}
}
五:编写数据源配置类
@Configuration
// 指定扫描的 dao层
@MapperScan(basePackages = "com.dh.xxx.dao", sqlSessionFactoryRef = "SqlSessionFactory")
public class DataSourceConfig {
@Primary
@Bean(name = "hostDataSource")
// application.properties 中定义的数据源前缀
@ConfigurationProperties(prefix = "spring.datasource.host")
public DataSource getDateSource1() {
return DataSourceBuilder.create().build();
}
@Bean(name = "secondDataSource")
@ConfigurationProperties(prefix = "spring.datasource.second")
public DataSource getDateSource2() {
return DataSourceBuilder.create().build();
}
@Bean(name = "dynamicDataSource")
public DynamicDataSource DataSource(@Qualifier("hostDataSource") DataSource hostDataSource,
@Qualifier("secondDataSource") DataSource secondDataSource) {
Map<Object, Object> targetDataSource = new HashMap<>();
targetDataSource.put(DataSourceType.DataBaseType.HOST, hostDataSource);
targetDataSource.put(DataSourceType.DataBaseType.SECOND, secondDataSource);
DynamicDataSource dataSource = new DynamicDataSource();
dataSource.setTargetDataSources(targetDataSource);
dataSource.setDefaultTargetDataSource(hostDataSource);
return dataSource;
}
@Bean(name = "SqlSessionFactory")
public SqlSessionFactory test1SqlSessionFactory(@Qualifier("dynamicDataSource") DataSource dynamicDataSource)
throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dynamicDataSource);
// 指定映射的 xml路径
bean.setMapperLocations(
new PathMatchingResourcePatternResolver().getResources("classpath*:mybatis/mapper/*.xml"));
return bean.getObject();
}
}
六:添加一个当前数据源监控类
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
DataSourceType.DataBaseType dataBaseType = DataSourceType.getDataBaseType();
return dataBaseType;
}
}
完结