pom.xml
<dependencies>
<!-- springboot核心包-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- springboot-aop包,AOP切面注解,Aspectd等相关注解 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>2.3.10.RELEASE</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- jdbcTemple -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.23</version>
</dependency>
<!-- 开发测试环境修改文件实时生效包,生产默认不使用 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<!-- mysql数据库连接包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
</dependencies>
application.yml
spring:
datasource:
primary:
driver-class-name: com.mysql.cj.jdbc.Driver
jdbcUrl: jdbc:mysql://192.168.20.33:3306/adm_user?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
username: root
password: adm123
second:
jdbcUrl: jdbc:mysql://192.168.20.33:3306/adm_order?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
username: root
password: adm123
hikari:
minimum-idle: 10
maximum-pool-size: 100
messages:
basename: messages-common,messages-user
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;
@Configuration
public class DataSourceConfig {
/**
* 数据源1
* spring.datasource.db1 :application.properteis中对应属性的前缀
* @return
*/
@Bean(name = "datasource1")
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource dataSource1() {
return DataSourceBuilder.create().build();
}
/**
* 数据源1
* spring.datasource.db2 :application.properteis中对应属性的前缀
* @return
*/
@Bean(name = "datasource2")
@ConfigurationProperties(prefix = "spring.datasource.second")
public DataSource dataSource2() {
return DataSourceBuilder.create().build();
}
/**
* 动态数据源: 通过AOP在不同数据源之间动态切换
* @return
*/
@Primary
@Bean(name = "dynamicDataSource")
public DataSource dynamicDataSource() {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
// 默认数据源
dynamicDataSource.setDefaultTargetDataSource(dataSource1());
// 配置多数据源
Map<Object, Object> dsMap = new HashMap();
dsMap.put("datasource1", dataSource1());
dsMap.put("datasource2", dataSource2());
dynamicDataSource.setTargetDataSources(dsMap);
return dynamicDataSource;
}
/**
* 配置@Transactional注解
* @return
*/
@Bean
public PlatformTransactionManager transactionManager() {
return new DataSourceTransactionManager(dynamicDataSource());
}
}
DataSourceSwitch
import java.lang.annotation.*;
/**
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({
ElementType.METHOD})
@Documented
public @interface DataSourceSwitch {
String value() default "datasource1";
}
DynamicDataSource
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
System.out.println("数据源为"+DataSourceContextHolder.getDB());
return DataSourceContextHolder.getDB();
}
}
DataSourceContextHolder
public class DataSourceContextHolder {
/**
* 默认数据源
*/
public static final String DEFAULT_DS = "datasource1";
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
/**
* 设置数据源名
* @param dbType
*/
public static void setDB(String dbType) {
System.out.println("切换到{"+dbType+"}数据源");
contextHolder.set(dbType);
}
/**
* 获取数据源名
* @return
*/
public static String getDB() {
return (contextHolder.get());
}
/**
* 清除数据源名
*/
public static void clearDB() {
contextHolder.remove();
}
}
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;
@Aspect
@Component
public class DynamicDataSourceAspect {
@Before("@annotation(com.admalltech.server.config.DataSourceSwitch)")
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);
// 判断是否存在@DataSourceSwitch注解
if (method.isAnnotationPresent(DataSourceSwitch.class)) {
DataSourceSwitch annotation = method.getAnnotation(DataSourceSwitch.class);
// 取出注解中的数据源名
dataSource = annotation.value();
}
} catch (Exception e) {
e.printStackTrace();
}
// 切换数据源
DataSourceContextHolder.setDB(dataSource);
}
@After("@annotation(com.admalltech.server.config.DataSourceSwitch)")
public void afterSwitchDS(JoinPoint point){
DataSourceContextHolder.clearDB();
}
}
service 注解使用
@Slf4j
@RequiredArgsConstructor
@Service
public class OrderService {
@Autowired
OrderMapper orderMapper;
@DataSourceSwitch("datasource2")
public List<Order> getList() {
List<Order> list = orderMapper.selectList(new QueryWrapper<>());
return list;
}
}
接口不添加@DataSourceSwitch 默认使用datasource1