配置了一下druid的多数据源配置,尝试了很多方法,Spring boot关于对Mysql和Sqlite多数据源的配置,记录下来:
涉及技术点:
Springboot
+ Druid
+ Mysql
+Sqlite
一、引入Jar包:
<!--Spring Boot依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.1.8.RELEASE</version>
</dependency>
<!--MYSQL连接依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.18</version>
</dependency>
<!--阿里数据源连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<!--sqlite依赖-->
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.28.0</version>
</dependency>
<!--aspects依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
二、配置参数:
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
#druid相关配置
druid:
one:
name: ds_mysql
driver-class-name: com.mysql.cj.jdbc.Driver
#基本属性
url: @jdbc.url@
username: @jdbc.username@
password: @jdbc.password@
test-while-idle: false
two:
name: ds_sqlite
driver-class-name: org.sqlite.JDBC
#基本属性
url: jdbc:sqlite:db/test.db
username: test
password: test
test-while-idle: false
use-global-data-source-stat: true
#监控统计拦截的filters
filters: stat
#配置初始化大小/最小/最大
initial-size: 2
min-idle: 2
max-active: 20
#获取连接等待超时时间
max-wait: 60000
#间隔多久进行一次检测,检测需要关闭的空闲连接
time-between-eviction-runs-millis: 60000
#一个连接在池中最小生存的时间
min-evictable-idle-time-millis: 300000
validation-query: SELECT 'x' FROM DUAL
# mysql需要设置校验
# 指明是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个.注意: 设置为true后如果要生效,validationQuery参数必须设置为非空字符串
test-while-idle: false
# 指明是否在归还到池中前进行检验 注意: 设置为true后如果要生效,validationQuery参数必须设置为非空字符串
test-on-borrow: false
# 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除. 注意: 设置为true后如果要生效,validationQuery参数必须设置为非空字符串
test-on-return: false
#打开PSCache,并指定每个连接上PSCache的大小。oracle设为true,mysql设为false。分库分表较多推荐设置为false
pool-prepared-statements: false
(参数配置,可参考: https://gitee.com/wenshao/druid/tree/master/druid-spring-boot-starter)
三、编写配置文件:
1、定义数据源名称常量 :
package com.meng.scaffold.config.datasource;
/**
* @Description: 数据源名称
* @author: MengW9
* @Date: 2019-11-28
* @Time: 10:26
*/
public interface DataSourceNames {
String ONE = "ONE";
String TWO = "TWO";
}
2、创建动态数据源:
package com.meng.scaffold.config.datasource;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import javax.sql.DataSource;
import java.util.Map;
/**
* @program: scaffold
* @description: 动态数据源
* @author: MengW9
* @create: 2019-11-28 10:26
**/
public class DynamicDataSource extends AbstractRoutingDataSource {
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
/**
* 配置DataSource, defaultTargetDataSource为主数据库
*/
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();
}
}
3、动态数据源配置:
package com.meng.scaffold.config.datasource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
/**
* @program: scaffold
* @description: 多数据源配置
* @author: MengW9
* @create: 2019-11-28 10:16
**/
@Configuration
public class DynamicDataSourceConfig {
/**
* 创建 DataSource Bean
*/
@Bean("oneDataSource")
@ConfigurationProperties("spring.datasource.druid.one")
public DataSource oneDataSource() {
return DruidDataSourceBuilder.create().build();
}
@Bean("twoDataSource")
@ConfigurationProperties("spring.datasource.druid.two")
public DataSource twoDataSource() {
return DruidDataSourceBuilder.create().build();
}
/**
* 如果还有数据源,在这继续添加 DataSource Bean
*/
@Bean
@Primary
public DynamicDataSource dataSource(DataSource oneDataSource, DataSource twoDataSource) {
Map<Object, Object> targetDataSources = new HashMap<>(2);
targetDataSources.put(DataSourceNames.ONE, oneDataSource);
targetDataSources.put(DataSourceNames.TWO, twoDataSource);
// 还有数据源,在targetDataSources中继续添加
System.out.println("DataSources:" + targetDataSources);
return new DynamicDataSource(oneDataSource, targetDataSources);
}
}
4、定义动态数据源注解:
package com.meng.scaffold.config.datasource;
import java.lang.annotation.*;
/**
* @description: 多数据源注解
* @author: MengW9
* @create: 2019-11-28 10:31
**/
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSource {
String value() default DataSourceNames.ONE;
}
5、设置数据源 AOP 代理:
package com.meng.scaffold.config.datasource;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
* @description: 数据源AOP切面处理
* @author: MengW9
* @create: 2019-11-28 10:33
**/
@Aspect
@Component
public class DataSourceAspect implements Ordered {
protected Logger logger = LoggerFactory.getLogger(getClass());
/**
* 切点: 所有配置 DataSource 注解的方法
*/
@Pointcut("@annotation(com.meng.scaffold.config.datasource.DataSource)")
public void dataSourcePointCut() {
}
@Around("dataSourcePointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
DataSource ds = method.getAnnotation(DataSource.class);
// 通过判断 DataSource 中的值来判断当前方法应用哪个数据源
DynamicDataSource.setDataSource(ds.value());
System.out.println("当前数据源: " + ds.value());
logger.debug("set datasource is " + ds.value());
try {
return point.proceed();
} finally {
DynamicDataSource.clearDataSource();
logger.debug("clean datasource");
}
}
@Override
public int getOrder() {
return 1;
}
}
四、修改启动文件:
package com.meng.scaffold;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.Import;
import com.gy.fast.common.config.data.DynamicDataSourceConfig;
**
* 动态数据源配置,需要将自有的配置依赖(DynamicDataSourceConfig),将原有的依赖去除(DataSourceAutoConfiguration)
* exclude = DataSourceAutoConfiguration.class
* @author Meng
*/
@Import({DynamicDataSourceConfig.class})
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
public class DeviceApplication {
public static void main(String[] args) {
SpringApplication.run(DeviceApplication.class, args);
}
}
五、配置完成, 进行测试:
测试接口编写:
package com.meng.scaffold.service;
import com.meng.scaffold.config.datasource.DataSource;
import com.meng.scaffold.config.datasource.DataSourceNames;
import com.meng.scaffold.dao.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @description: 测试多数据源
* @author: MengW9
* @create: 2019-11-28 10:39
**/
@Service
public class DataSourceTestService {
@Autowired
private UserService userService;
public User test1(Long userId) {
return userService.selectById(userId);
}
/**
* @Description: 多数据注解必须放在接口实现类的上面
* @Param: [userId]
* @Author: MengW9
*/
@DataSource(DataSourceNames.TWO)
public User test2(Long userId) {
return userService.selectById(userId);
}
}
编写测试类:
package com.meng.scaffold;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.meng.scaffold.dao.User;
@RunWith(SpringRunner.class)
@SpringBootTest
public class DynamicDataSourceTest {
@Autowired
private DataSourceTestService dataSourceTestService;
@Test
public void test(){
// 数据源ONE
SysUser user1 = dataSourceTestService.test1(1L);
System.out.println(ToStringBuilder.reflectionToString(user1));
// 数据源TWO
SysUser user2 = dataSourceTestService.test2(1L);
System.out.println(ToStringBuilder.reflectionToString(user2));
// 数据源ONE
SysUser user3 = dataSourceTestService.test1(1L);
System.out.println(ToStringBuilder.reflectionToString(user3));
}
}
代码地址:Git仓库
参考:
https://my.oschina.net/u/3681868/blog/1813011
SpringBoot配置多数据源Mysql+Sqlite的更多相关文章
-
springboot配置双数据源 MySQL和SqlServer
1. pom文件的驱动jar包加上去, compile 'com.microsoft.sqlserver:mssql-jdbc:6.2.2.jre8' 2. application.yml sprin ...
-
springboot配置Druid数据源
springboot配置druid数据源 Author:SimpleWu springboot整合篇 前言 对于数据访问层,无论是Sql还是NoSql,SpringBoot默认采用整合SpringDa ...
-
SpringBoot配置多数据源时遇到的问题
SpringBoot配置多数据源 参考代码:Spring Boot 1.5.8.RELEASE同时配置Oracle和MySQL 原作者用的是1.5.8版本的SpringBoot,在升级到2.0.*之后 ...
-
springboot 配置多数据源
1.首先在创建应用对象时引入autoConfig package com; import org.springframework.boot.SpringApplication; import org. ...
-
springboot 配置多数据源 good
1.首先在创建应用对象时引入autoConfig package com; import org.springframework.boot.SpringApplication; import org. ...
-
SpringBoot添加多数据源mysql和oracle
项目结构 多数据源配置文件 MultiDataSourceConfig.java SqlSessionTemplate1.java SqlSessionTemplate2.java package c ...
-
spring boot 配置双数据源mysql、sqlServer
背景:原来一直都是使用mysql数据库,在application.properties 中配置数据库信息 spring.datasource.url=jdbc:mysql://xxxx/test sp ...
-
springboot配置多数据源mybatis配置失效问题
mybatis配置 #开启驼峰映射 mybatis.configuration.map-underscore-to-camel-case=true #开启打印sql mybatis.configura ...
-
Springboot配置多数据源(Mysql和Orcale)--(Idea Maven JDBCTemplate支持下的)
1.配置 orcale jdbc 对于一个Maven项目,使用Mysql时,可直接添加如下依赖: <dependency> <groupId>mysql</groupId ...
随机推荐
-
递推+高精度 UVA 10497 Sweet Child Makes Trouble(可爱的孩子惹麻烦)
题目链接 题意: n个物品全部乱序排列(都不在原来的位置)的方案数. 思路: dp[i]表示i个物品都乱序排序的方案数,所以状态转移方程.考虑i-1个物品乱序,放入第i个物品一定要和i-1个的其中一个 ...
-
基础学习day10--异常、包
一.异常 1.1.异常定义 异常:--不正常,程序在运行时出现不正常情况 异常由来:其实也是现实生活中一个具体的事物,马可以通过JAVA的类的形式表现描述,并封装成类. Java对不正常情况描述后的, ...
-
initWithFrame 和 initWithCoder
当我们所写的程序里没用用Nib文件(XIB)时,用代码控制视图内容,需要调用initWithFrame去初始化 - (id)initWithFrame:(CGRect)frame { if (self ...
-
nvidia安装与卸载方式
第1种方法:.最好的方式不是手动安装官方驱动(手动安装官方驱动无法使用gpu,而且无法启用3d,同时无法生效,所以最好采用此种方法),而是使用bumblebee-nvidia安装,不过要先添加x-sw ...
-
JS实现简单倒计时
/*倒计时*/ lcf.downTime = function (endTime,obj,callback){ /*基本判断*/ if(!endTime || typeof endTime !== & ...
-
rip路由协议 细节分析及实例配置【完整版】
rip路由协议 细节分析及实例配置[完整版] RIP呢,这是一个比较重要的知识点,所以它的知识覆盖面很广泛:但是呢,我将会对碰到的问题进行一些分析解刨(主要是为了帮助自己理清思维):也希望能够从中发现 ...
-
安全之路 —— 借助DLL进行远程线程注入实现穿墙与隐藏进程
简介 大多数后门或病毒要想初步实现隐藏进程,即不被像任务管理器这样典型的RING3级进程管理器找到过于明显的不明进程,其中比较著名的方法就是通过远程线程注入的方法注入将恶意进程的DLL文 ...
-
gdb 调试入门,大牛写的高质量指南
引用自:http://blog.jobbole.com/107759/ gdb 调试 ncurses 全过程: 发现网上的“gdb 示例”只有命令而没有对应的输出,我有点不满意.gdb 是 GNU 调 ...
-
python 全栈开发,Day74(基于双下划线的跨表查询,聚合查询,分组查询,F查询,Q查询)
昨日内容回顾 # 一对多的添加方式1(推荐) # book=Book.objects.create(title="水浒传",price=100,pub_date="164 ...
-
20_集合_第20天(Map、可变参数、Collections)_讲义
今日内容介绍 1.Map接口 2.模拟斗地主洗牌发牌 01Map集合概述 A:Map集合概述: 我们通过查看Map接口描述,发现Map接口下的集合与Collection接口下的集合,它们存储数据的形式 ...