基于springboot通过注解AOP动态切换druid多数据源--mybatis
控制于接口之上:
开始:demo地址 在lsr-core-base中
自定义注解:
/**
* @Description: 数据源切换注解
* @Package: lsr-microservice
* @author: Hacker_lsr@126.com
**/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DS {
DataSourceType value() default DataSourceType.db1;
}
数据源标识:
/**
* @Description: 数据源标识
* @Package: lsr-microservice
* @author: Hacker_lsr@126.com
**/
public enum DataSourceType {
db1,db2
}
数据源配置setting:
/**
* @Description: 数据源配置
* @Package: lsr-microservice
* @author: Hacker_lsr@126.com
**/
@Configuration
@ConfigurationProperties(prefix = "spring.datasource")
public class DruidSettings {
private String driverClassName;
private String url;
private String username;
private String password;
private String driverClassName2;
private String url2;
private String username2;
private String password2;
private int initialSize;
private int minIdle;
private int maxActive;
private long maxWait;
private long timeBetweenEvictionRunsMillis;
private long minEvictableIdleTimeMillis;
private String validationQuery;
private boolean testWhileIdle;
private boolean testOnBorrow;
private boolean testOnReturn;
private boolean poolPreparedStatements;
private String filters;
private int maxPoolPreparedStatementPerConnectionSize;
private boolean useGlobalDataSourceStat;
private String connectionProperties;
//get set
}
Druid配置类:
package cn.lsr.core.config.druid; import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
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; /**
* = = Druid配置类
*
* @Version: 1.0
* @Author: Hacker_lsr@126.com
*/
@Configuration
public class DruidConfig {
@Autowired
DruidSettings druidSettings;
/**
* 数据源db1
* @return
*/
//@ConfigurationProperties(prefix = "spring.datasource.db1")
@Bean(name = "dataSource01")
public DataSource dataSource01(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName(druidSettings.getDriverClassName());
druidDataSource.setUrl(druidSettings.getUrl());
druidDataSource.setUsername(druidSettings.getUsername());
druidDataSource.setPassword(druidSettings.getPassword());
druidDataSource.setInitialSize(druidSettings.getInitialSize());
druidDataSource.setMinIdle(druidSettings.getMinIdle());
druidDataSource.setMaxActive(druidSettings.getMaxActive());
druidDataSource.setMaxWait(druidSettings.getMaxWait());
druidDataSource.setTimeBetweenEvictionRunsMillis(druidSettings.getTimeBetweenEvictionRunsMillis());
druidDataSource.setMinEvictableIdleTimeMillis(druidSettings.getMinEvictableIdleTimeMillis());
druidDataSource.setValidationQuery(druidSettings.getValidationQuery());
druidDataSource.setTestWhileIdle(druidSettings.isTestWhileIdle());
druidDataSource.setTestOnBorrow(druidSettings.isTestOnBorrow());
druidDataSource.setTestOnReturn(druidSettings.isTestOnReturn());
druidDataSource.setPoolPreparedStatements(druidSettings.isPoolPreparedStatements());
try {
druidDataSource.setFilters(druidSettings.getFilters());
} catch (Exception e) {
e.printStackTrace();
}
druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(druidSettings.getMaxPoolPreparedStatementPerConnectionSize());
druidDataSource.setUseGlobalDataSourceStat(druidSettings.isUseGlobalDataSourceStat());
druidDataSource.setConnectionProperties(druidSettings.getConnectionProperties());
return druidDataSource;
} /**
* 数据源db2
* @return
*/
//@ConfigurationProperties(prefix = "spring.datasource.db2")
@Bean(name = "dataSource02")
public DataSource dataSource02(){
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName(druidSettings.getDriverClassName2());
druidDataSource.setUrl(druidSettings.getUrl2());
druidDataSource.setUsername(druidSettings.getUsername2());
druidDataSource.setPassword(druidSettings.getPassword2());
druidDataSource.setInitialSize(druidSettings.getInitialSize());
druidDataSource.setMinIdle(druidSettings.getMinIdle());
druidDataSource.setMaxActive(druidSettings.getMaxActive());
druidDataSource.setMaxWait(druidSettings.getMaxWait());
druidDataSource.setTimeBetweenEvictionRunsMillis(druidSettings.getTimeBetweenEvictionRunsMillis());
druidDataSource.setMinEvictableIdleTimeMillis(druidSettings.getMinEvictableIdleTimeMillis());
druidDataSource.setValidationQuery(druidSettings.getValidationQuery());
druidDataSource.setTestWhileIdle(druidSettings.isTestWhileIdle());
druidDataSource.setTestOnBorrow(druidSettings.isTestOnBorrow());
druidDataSource.setTestOnReturn(druidSettings.isTestOnReturn());
druidDataSource.setPoolPreparedStatements(druidSettings.isPoolPreparedStatements());
try {
druidDataSource.setFilters(druidSettings.getFilters());
} catch (Exception e) {
e.printStackTrace();
}
druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(druidSettings.getMaxPoolPreparedStatementPerConnectionSize());
druidDataSource.setUseGlobalDataSourceStat(druidSettings.isUseGlobalDataSourceStat());
druidDataSource.setConnectionProperties(druidSettings.getConnectionProperties()); return druidDataSource;
} /**
* 动态数据源管理
* @return
*/
@Primary
@Bean(name = "dynamicDataSource")
public DataSource dynamicDataSource(){
DynamicDataSource dynamicDataSource = new DynamicDataSource();
//设置默认数据源
dynamicDataSource.setDefaultTargetDataSource(dataSource01());
Map<Object,Object> dbMap = new HashMap<>();
dbMap.put(DataSourceType.db1,dataSource01());
dbMap.put(DataSourceType.db2,dataSource02());
// targetDataSources 这里保存我们数据源配置的多个数据源)的数据源保存到resolvedDataSources
dynamicDataSource.setTargetDataSources(dbMap);
return dynamicDataSource;
} /**
* 将动态数据源放入事务管理器
* @return
*/
@Bean
public PlatformTransactionManager transactionManager(){
return new DataSourceTransactionManager(dynamicDataSource());
}
/**
* 配置监控服务器
**/
@Bean
public ServletRegistrationBean statViewServlet(){
ServletRegistrationBean bean = new ServletRegistrationBean(
new StatViewServlet(), "/druid/*");
Map<String,String> initParams = new HashMap<>();
// druid后台管理员用户
initParams.put("loginUsername","admin");
initParams.put("loginPassword","123456");
// 是否能够重置数据
initParams.put("resetEnable", "false"); bean.setInitParameters(initParams);
return bean;
} /**
* 配置web监控的过滤器
**/
@Bean
public FilterRegistrationBean webStatFilter(){
FilterRegistrationBean bean = new FilterRegistrationBean(
new WebStatFilter());
// 添加过滤规则
bean.addUrlPatterns("/*");
Map<String,String> initParams = new HashMap<>();
// 忽略过滤格式
initParams.put("exclusions","*.js,*.css,*.icon,*.png,*.jpg,/druid/*");
bean.setInitParameters(initParams);
return bean;
} }
动态数据源切换:
/**
* @Description: 动态数据源切换
* @Package: lsr-microservice
* @author: Hacker_lsr@126.com
**/
public class DynamicDataSource extends AbstractRoutingDataSource {
private static final Logger log = LoggerFactory.getLogger(DynamicDataSource.class);
// 当前线程数据源
private static final ThreadLocal<DataSourceType> dataSourceContext = new ThreadLocal<>();
@Override
protected Object determineCurrentLookupKey() {
log.info("数据源:{}",getDataSource());
return getDataSource();
} /**
* 获取当前数据源
* @return
*/
public DataSourceType getDataSource(){
return dataSourceContext.get();
} /**
* 设置数据源
* @param dataSourceType
*/
public static void setDataSource(DataSourceType dataSourceType){
dataSourceContext.set(dataSourceType);
} /**
* 删除数据源
*/
public static void clearDataSource(){
dataSourceContext.remove();
}
}
注解动态数据源切换实现:
/**
* @Description: 动态数据源AOP
* @Package: lsr-microservice
* @author: Hacker_lsr@126.com
**/
@Aspect
@Order(1)
@Component
public class DynamicDataSourceAspect {
@Before("@annotation(ds)")
public void beforeSwitchDS(JoinPoint joinPoint,DS ds){
//获取当前访问的class
Class<?> className = joinPoint.getTarget().getClass();
//获取方法名
String methodName = joinPoint.getSignature().getName();
//获取方法的参数类型
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature)signature;
Class[] arrClass = methodSignature.getParameterTypes();
//默认数据源
DataSourceType dataSourceType = DataSourceType.db1;
try {
//得到方法对象
Method method = className.getMethod(methodName, arrClass);
//判断是否有注解存在
if (method.isAnnotationPresent(DS.class)){
//拿到注解方法
DS dsValue = method.getAnnotation(DS.class);
//拿到注解value
dataSourceType = dsValue.value();
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
//切换数据源
DynamicDataSource.setDataSource(dataSourceType);
}
@After("@annotation(ds)")
public void afterSwitchDS(JoinPoint joinPoint,DS ds){
DynamicDataSource.clearDataSource();
}
}
application.properties##################################### 配置数据源 #####################################
##################################### 配置数据源 #####################################
datasource.db1url=192.168.0.104:3306/lsr-microservice
datasource.db2url=192.168.0.104:3306/lsr-microservice
##################################### 数据源1 #######################################
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://${datasource.db1url}?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
spring.datasource.username=root
spring.datasource.password=lishirui
##################################### 数据源2 #######################################
spring.datasource.driver-class-name2=com.mysql.jdbc.Driver
spring.datasource.url2=jdbc:mysql://${datasource.db1url}?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
spring.datasource.username2=root
spring.datasource.password2=lishirui
##################################### druid连接池 ###################################
spring.datasource.initialSize=5
spring.datasource.minIdle=5
spring.datasource.maxActive=20
spring.datasource.maxWait=60000
spring.datasource.timeBetweenEvictionRunsMillis=60000
spring.datasource.minEvictableIdleTimeMillis=300000
spring.datasource.validationQuery=SELECT 1 FROM DUAL
spring.datasource.testWhileIdle=true
spring.datasource.testOnBorrow=false
spring.datasource.testOnReturn=false
spring.datasource.poolPreparedStatements=true
#配置监控统计拦截的filters.去掉后监控界面sql无法统计,'wall'用于防火墙
spring.datasource.filters=stat,wall,slf4j
spring.datasource.maxPoolPreparedStatementPerConnectionSize=20
spring.datasource.useGlobalDataSourceStat=true
spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
使用:@DS(DataSourceType.db1)
public interface UserMapper extends MyMapper<User> { User selectByName(String username); User selectUserByName(String username);
@DS(DataSourceType.db1)
User selecTest(String username); }
基于springboot通过注解AOP动态切换druid多数据源--mybatis的更多相关文章
- AOP获取方法注解实现动态切换数据源
AOP获取方法注解实现动态切换数据源(以下方式尚未经过测试,仅提供思路) ------ 自定义一个用于切换数据源的注解: package com.xxx.annotation; import org. ...
- springboot 双数据源+aop动态切换
# springboot-double-dataspringboot-double-data 应用场景 项目需要同时连接两个不同的数据库A, B,并且它们都为主从架构,一台写库,多台读库. 多数据源 ...
- Spring AOP动态切换数据源
现在稍微复杂一点的项目,一个数据库也可能搞不定,可能还涉及分布式事务什么的,不过由于现在我只是做一个接口集成的项目,所以分布式就先不用了,用Spring AOP来达到切换数据源,查询不同的数据库就可以 ...
- 基于 Spring 和 iBATIS 的动态可更新多数据源持久层
前言 我们时常会遇到一些 web 项目,需要从不同的数据源中抓取数据来进行分析,而这些数据源是有可能变化的,需要用户来进行动态的维护和添加.可是,大多数的 web 程序使用了应用服务器或者容器中间件来 ...
- springboot集成mongodb实现动态切换数据源
主要实现原理,利用spring的aop 在切入点执行db操作之前 将数据库切换: 本例子采用aop在controller进行拦截 拦截到MongoTemplate.class 切换数据源后重新放回去 ...
- springAOP实现基于注解的数据源动态切换
需求 代码实现读写数据库分离 武器 spring3.0以上版本 实现思路 1.继承org.springframework.jdbc.datasource.lookup.AbstractRoutingD ...
- SPRINGAOP实现基于注解的数据源动态切换(转)
需求 代码实现读写数据库分离 武器 spring3.0以上版本 实现思路 1.继承org.springframework.jdbc.datasource.lookup.AbstractRoutingD ...
- Springboot+Mybatis+Pagehelper+Aop动态配置Oracle、Mysql数据源
本文链接:https://blog.csdn.net/wjy511295494/article/details/78825890 Springboot+Mybatis+Pagehelper+Aop ...
- 在使用 Spring Boot 和 MyBatis 动态切换数据源时遇到的问题以及解决方法
相关项目地址:https://github.com/helloworlde/SpringBoot-DynamicDataSource 1. org.apache.ibatis.binding.Bind ...
随机推荐
- 【C语言】数组名作函数参数,完成数据的升序排列
#include<stdio.h> void sort(int x[],int n); int main() { ] = { ,,,,,,,,, },i; sort(arr, ); pri ...
- MinGW dll导入导出类
dll不仅可以导入导出函数,还可以导入导出类.这篇文章就来介绍如何将类导入dll中并导出. 首先我们建立一个名为dll.cpp的文件(又是这种破名字),里面写上: #include <iostr ...
- 让ul li 或者table 进行循环往上滚屏
转载:https://blog.csdn.net/u012138137/article/details/80729789 <div style="display:inline" ...
- Redis04——Redis五大数据类型 key
key keys * 查看当前库的所有键 exists <key> 判断某个键是否存在 type <key> 查看键的类型 del<key> 删除 ...
- 【StarUML】组件图
架构设计中可视化地表达各个组件之间依赖关系以及组件的接口调用情况 1.元素 a.组件 b.接口 b1.组件暴露接口 暴露接口,需要先画一个接口 然后建立组件和接口的联系,这里是暴露接口,那么这个连线就 ...
- echarts制作html和JavaScript的时钟和代码分析与注释
1.效果图 2.说明: 2.1 代码是大神制作的,我进行修改,感谢大神,原创属于他. 2.2 我对代码进行分析.注释.整理,增加代码的可读性. 2.3 通过上述自己的工作,自己也能熟悉相关的JavaS ...
- go基础_切片
切片创建方式 1.通过数组创建 2.通过内置函数make创建 切片允许的操作 1.追加元素 2.通过内置函数make创建 package main import "fmt" fun ...
- 树莓派4B踩坑指南 - (11)免费搭建网站(宝塔,花生壳)
目录 宝塔 安装宝塔面板 登录及初始化设置 安装网站 花生壳 安装花生壳 设置花生壳 测试 问题(未解决但不影响使用) 网站统计 树莓派这么低的功耗,不用来当服务器总感觉有点浪费...完成效果:htt ...
- JS高级---利用原型共享数据
什么样子的数据是需要写在原型中? 需要共享的数据就可以写原型中 原型的作用之一: 数据共享 //属性需要共享, 方法也需要共享 //不需要共享的数据写在构造函数中,需要共享的数据写在原型中 //构造函 ...
- swift中的可选类型
可选类型也是Swift语言新添加的对象.主要是为了解决对象变量或常量为空的情况.在前面定义的变量和常量都不能为空.里面必须要有值. Swift中的可选类型则允许变量(常量)中没有值(被设为nil).要 ...