spring boot多数据源动态切换代码实例
作者:炫舞风中 发布时间:2022-03-11 00:37:09
标签:spring,boot,数据源,动态,切换
这篇文章主要介绍了spring boot多数据源动态切换代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
当项目中存在多数据源时,就涉及到数据源的动态切换,通过研究,特此记录一下。
1、maven依赖
<!--数据库连接-->
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.4</version>
<scope>runtime</scope>
</dependency>
<!--数据库连接池->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--aop->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
2、多数据源信息配置
#多数据源测试
spring:
datasource:
druid:
master:
driver-class-name: oracle.jdbc.driver.OracleDriver
username: test
password: test
url: jdbc:oracle:thin:@//ip1:1521/orcl
slave:
driver-class-name: oracle.jdbc.driver.OracleDriver
username: test
password: test
url: jdbc:oracle:thin:@//ip2:1521/orcl
3、数据源配置信息转换成实体类
@ConfigurationProperties(prefix = "spring.datasource.druid")
@Data
@Component
public class DataSourceProperties {
private Map<String,String>master;
private Map<String,String>slave;
}
4、动态数据源切换类
public class DynamicDataSource extends AbstractRoutingDataSource {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
super.setDefaultTargetDataSource(defaultTargetDataSource);
super.setTargetDataSources(targetDataSources);
super.afterPropertiesSet();
}
@Override
protected Object determineCurrentLookupKey() {
return getDataSource();
}
public static void setDataSource(String dataSource) {
contextHolder.set(dataSource);
}
public static String getDataSource() {
return contextHolder.get();
}
public static void clearDataSource() {
contextHolder.remove();
}
}
5、多数据源配置类
@Configuration
public class DynamicDataSourceConfig {
@Bean
public DataSource master(@Autowired DataSourceProperties dataSourceProperties){
DruidDataSource druidDataSource = new DruidDataSource();
Map<String, String> master = dataSourceProperties.getMaster();
druidDataSource.setUsername(master.get("username"));
druidDataSource.setPassword(master.get("password"));
druidDataSource.setUrl(master.get("url"));
//其他参数配置 省略
return druidDataSource;
}
@Bean
public DataSource slave(@Autowired DataSourceProperties dataSourceProperties){
DruidDataSource druidDataSource = new DruidDataSource();
Map<String, String> slave = dataSourceProperties.getSlave();
druidDataSource.setUsername(slave.get("username"));
druidDataSource.setPassword(slave.get("password"));
druidDataSource.setUrl(slave.get("url"));
//其他参数配置 省略
return druidDataSource;
}
@Bean
@Primary
public DynamicDataSource dataSource(DataSource master,DataSource slave){
Map<Object,Object>map = new HashMap<>(4);
map.put("master",master);
map.put("slave",slave);
return new DynamicDataSource(master,map);
}
}
6、自定义@DataSource注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSource {
String name() default "master";
}
7、Aop切面类配置
@Component
@Aspect
public class DataSourceAspect {
@Pointcut("@annotation(com.zxgeo.sso.muiltDatasource.anons.DataSource)")
public void dataSourcePointCut(){}
@Around(value = "dataSourcePointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
DataSource dataSource = method.getAnnotation(DataSource.class);
if(dataSource == null){
DynamicDataSource.setDataSource("master");
}else {
DynamicDataSource.setDataSource(dataSource.name());
}
try {
return point.proceed();
} finally {
DynamicDataSource.clearDataSource();
}
}
}
8、启动配置注解信息,重要(不然运行会报错)
@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
9、测试
(1)、service层(此处没有使用mybatis)
@Service
public class TestService {
@Autowired
private javax.sql.DataSource dataSource;
@DataSource
public Map<String,Object> getMasterDataSource() throws SQLException {
Connection connection = dataSource.getConnection();
Map<String,Object> map;
try (PreparedStatement preparedStatement
= connection.prepareStatement("SELECT * FROM AA WHERE A=10001")) {
ResultSet resultSet = preparedStatement.executeQuery();
map = new HashMap<>();
while (resultSet.next()){
map.put("A",resultSet.getString("A"));
map.put("B",resultSet.getString("B"));
map.put("C",resultSet.getString("C"));
}
}
return map;
}
@DataSource(name = "slave")
public Map<String,Object> getSlaveDataSource() throws SQLException {
Connection connection = dataSource.getConnection();
Map<String,Object> map;
try (PreparedStatement preparedStatement
= connection.prepareStatement("SELECT * FROM AA WHERE A=10002")) {
ResultSet resultSet = preparedStatement.executeQuery();
map = new HashMap<>();
while (resultSet.next()){
map.put("A",resultSet.getString("A"));
map.put("B",resultSet.getString("B"));
map.put("C",resultSet.getString("C"));
}
}
return map;
}
}
(2)、单元测试
@SpringBootTest
@RunWith(SpringRunner.class)
class SsoApplicationTests {
@Autowired
private TestService testService;
@Test
public void muliDatasorce() throws SQLException {
Map<String, Object> masterDataSourceUrl = testService.getMasterDataSource();
System.out.println(masterDataSourceUrl);
Map<String, Object> slaveDataSourceUrl = testService.getSlaveDataSource();
System.out.println(slaveDataSourceUrl);
}
}
(3)、结果:
来源:https://www.cnblogs.com/cq-yangzhou/p/12172584.html
0
投稿
猜你喜欢
- BigDecimal类对于不需要任何准确计算精度的数字可以直接使用float或double,但是如果需要精确计算的结果,则必须使用BigDe
- java 避免出现NullPointerException(空指针)的方法总结Java应用中抛出的空指针异常是解决空指针的最好方式,也是写出
- 概况本文主要给大家介绍了通过JDK源码学习InputStream的相关内容,JDK 给我们提供了很多实用的输入流 xxxInputStrea
- 近日工作任务较轻,有空学习学习技术,遂来研究如果实现读写分离。这里用博客记录下过程,一方面可备日后查看,同时也能分享给大家(网上的资料真的大
- 上帝之火本系列讲述的是开源实时监控告警解决方案Prometheus,这个单词很牛逼。每次我都能联想到带来上帝之火的希腊之神,普罗米修斯。而这
- 将网络资源url转化为File文件将互联网上的http开头的url资源,保存到本地。 private File getNetUrlHttp(
- 1.基本概念首先我们需要弄清楚几个概念:面向对象是什么、类是什么、对象又是什么?还是逐个来说1.1面向对象我们常说Java是面向对象的语言,
- 概述还没玩过Spring Boot,现在越来越多的公司在用了,不得不学习了。本篇是Spring Boot的开篇,简单介绍一下如何创建一个Sp
- 为什么需要ThreadLocalRandomjava.util.Random一直都是使用比较广泛的随机数生成工具类,而且java.lang.
- 在开发过程中,碰到生成一个List对象,需要对其里面的每个对象都进行校验。但是,这个Lis
- Arrays 类提供了一个 fill() 方法,可以在指定位置进行数值填充。fill() 方法虽然可以填充数组,但是它的功能有限制,只能使用
- Java常用类库Math类Math包含用于执行基本数字运算的方法,例如基本指数,对数,平方根和三角函数一、Field SummaryModi
- 只能输入数字:"^[0-9]*$"。只能输入n位的数字:"^\d{n}$"。只能输入至少n位的数字:
- 官方文档 8.0Spring为不同缓存做了一层抽象,这里通过阅读文档以及源码会对使用以及原理做一些学习笔记。1.简介
- 图形验证码属于老生常谈了,具体细节这里就不说了。生成图形验证码的办法非常多,今天讲解一种通过Kaptcha组件快速生成图形验证码的方法。Ka
- 顺序语句顺序顾名思义就是程序自上而下执行public class User { public static voi
- Lombok中@Builder用法1、建造者模式简介:Builder 使用创建者模式又叫建造者模式。简单来说,就是一步步创建一个对象,它对用
- 本文实例为大家分享了Java从服务端下载Excel模板文件的具体实现代码,供大家参考,具体内容如下方法一 (2021年01月更新)生成exc
- 我就废话不多说了,大家还是直接看代码吧!public static String mapToTxt(Map<String,String
- 1、使用JPA 的@Enumerated 注解 ,可以直接将Enum映射到数据库中。但是value的值只有两种方式选择,一种是使用枚举的序号