spring boot 多数据源动态切换
来源:互联网 发布:百度云 知乎 编辑:程序博客网 时间:2024/05/31 00:39
总体思路
使用AOP进行数据源切换,继承AbstractRoutingDataSource实现数据源动态的获取,使用注解指定数据源。
//指定aop事务执行顺序,已保证在切换数据源的后面@EnableTransactionManagement(order = 2)//排除数据源自动配置@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class})
一. 多数据源配置
spring: datasource: # 使用druid数据源 druid: default: url: jdbc:mysql:/url/database?useUnicode=true&characterEncoding=utf-8 username: xx password: 123344 driver-class-name: com.mysql.jdbc.Driver filters: stat maxActive: 300 initialSize: 5 maxWait: 60000 minIdle: 5 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQuery: select 'x' testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true maxOpenPreparedStatements: 20 WebStatFilter: enabled: true #是否启用StatFilter默认值true urlPattern: /* exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/ StatViewServlet: enabled: true # 是否启用StatViewServlet默认值true urlPattern: /druid/* other: url: jdbc:mysql://url/database1?useUnicode=true&characterEncoding=utf-8 username: xxx password: 432423 driver-class-name: com.mysql.jdbc.Driver filters: stat maxActive: 300 initialSize: 5 maxWait: 60000 minIdle: 5 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQuery: select 'x' testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true maxOpenPreparedStatements: 20 WebStatFilter: enabled: true #是否启用StatFilter默认值true urlPattern: /* exclusions: '*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid1/ StatViewServlet: enabled: true # 是否启用StatViewServlet默认值true urlPattern: /druid1/* aop: proxy-target-class: true
读取配置
package com.***.dataSource;import com.alibaba.druid.pool.DruidDataSource;import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;import org.apache.ibatis.session.SqlSessionFactory;import org.mybatis.spring.SqlSessionFactoryBean;import org.mybatis.spring.SqlSessionTemplate;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.jdbc.datasource.DataSourceTransactionManager;import org.springframework.transaction.PlatformTransactionManager;import javax.sql.DataSource;import java.util.HashMap;import java.util.Map;/** * 动态数据源配置 * @author Lucian */@Configurationpublic class DynamicDataSourceConfiguration { @Bean(name = DataSourceConsts.DEFAULT) @ConfigurationProperties(prefix = "spring.datasource.druid.default") public DataSource dataSourceOne(){ DruidDataSource dataSource = DruidDataSourceBuilder.create().build(); dataSource.setName(DataSourceConsts.DEFAULT); return dataSource; } @Bean(name = DataSourceConsts.TRADE) @ConfigurationProperties(prefix = "spring.datasource.druid.trade") public DataSource dataSourceTwo(){ DruidDataSource dataSource = DruidDataSourceBuilder.create().build(); dataSource.setName(DataSourceConsts.TRADE); return dataSource; } /** * 动态数据源: 通过AOP在不同数据源之间动态切换 * @return */ @Bean(name = "dynamicDataSource") public DataSource dataSource() { DynamicDataSource dynamicDataSource = new DynamicDataSource(); // 默认数据源 dynamicDataSource.setDefaultTargetDataSource(dataSourceOne()); // 配置多数据源 Map<Object, Object> dsMap = new HashMap(2); dsMap.put(DataSourceConsts.DEFAULT, dataSourceOne()); dsMap.put(DataSourceConsts.TRADE, dataSourceTwo()); dynamicDataSource.setTargetDataSources(dsMap); return dynamicDataSource; } @Bean public PlatformTransactionManager txManager(DataSource dynamicDataSource) { return new DataSourceTransactionManager(dynamicDataSource); } @Bean @ConfigurationProperties(prefix = "mybatis") public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dynamicDataSource) throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dynamicDataSource); return sqlSessionFactoryBean; } @Bean public SqlSessionFactory sqlSessionFactory(SqlSessionFactoryBean sqlSessionFactoryBean) throws Exception { return sqlSessionFactoryBean.getObject(); } @Bean public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) throws Exception { SqlSessionTemplate template = new SqlSessionTemplate(sqlSessionFactory); // 使用上面配置的Factory return template; }}
二. 数据源动态切换类
package com.hunter.nocardpay.core.dataSource;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.reflect.MethodSignature;import org.springframework.core.annotation.Order;import org.springframework.stereotype.Component;import java.lang.reflect.Method;/** * 动态数据源AOP切面 */@Aspect@Order(1)@Componentpublic class DynamicDataSourceAspect { @Around("execution(* com.hunter.nocardpay.*.service..*(..))") public Object switchDS(ProceedingJoinPoint point) throws Throwable { Class<?> className = point.getTarget().getClass(); String dataSource = DataSourceConsts.DEFAULT; if (className.isAnnotationPresent(DS.class)) { DS ds = className.getAnnotation(DS.class); dataSource = ds.value(); }else{ // 得到访问的方法对象 String methodName = point.getSignature().getName(); Class[] argClass = ((MethodSignature)point.getSignature()).getParameterTypes(); Method method = className.getMethod(methodName, argClass); // 判断是否存在@DS注解 if (method.isAnnotationPresent(DS.class)) { DS annotation = method.getAnnotation(DS.class); // 取出注解中的数据源名 dataSource = annotation.value(); } } // 切换数据源 DataSourceContextHolder.setDB(dataSource); try { return point.proceed(); } finally { DataSourceContextHolder.clearDB(); } }}
三. 当前线程数据源
package com.hunter.nocardpay.core.dataSource;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * 当前线程数据源 * @author Lucian */public class DataSourceContextHolder { public static final Logger log = LoggerFactory.getLogger(DataSourceContextHolder.class); private static final ThreadLocal<String> contextHolder = new ThreadLocal<>(); // 设置数据源名 public static void setDB(String dbType) { log.debug("切换到{}数据源", dbType); contextHolder.set(dbType); } // 获取数据源名 public static String getDB() { return (contextHolder.get()); } // 清除数据源名 public static void clearDB() { contextHolder.remove(); }}
四. 动态数据源
package com.hunter.nocardpay.core.dataSource;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;/** * 动态数据源 * @author Lucian */public class DynamicDataSource extends AbstractRoutingDataSource { private static final Logger log = LoggerFactory.getLogger(DynamicDataSource.class); @Override protected Object determineCurrentLookupKey() { log.debug("数据源为:====", DataSourceContextHolder.getDB()); return DataSourceContextHolder.getDB(); }}
数据源注解
package com.hunter.nocardpay.core.dataSource;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/** * 数据源注解 * @author Lucian */@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.TYPE, ElementType.METHOD})public @interface DS { String value() default DataSourceConsts.DEFAULT;}
阅读全文
0 0
- spring boot 多数据源动态切换
- spring boot+mybatis 多数据源切换
- spring boot+mybatis 多数据源切换
- Spring Boot 动态数据源(多数据源自动切换)
- Spring Boot 动态数据源(多数据源自动切换)
- Spring Boot 动态数据源(多数据源自动切换)
- Spring Boot 动态数据源(多数据源自动切换)
- Spring Boot 动态数据源(多数据源自动切换)
- Spring Boot +Mybatis+druid动态多数据源自由切换
- Spring Boot 动态数据源(多数据源自动切换)
- Spring Boot 动态数据源(多数据源自动切换)
- Spring Boot 动态多数据源
- Spring多数据源的动态切换
- Spring动态切换多数据源解决方案
- Spring多数据源的动态切换
- Spring实现多数据源动态切换
- Spring动态切换多数据源解决方案
- Spring > 动态切换多数据源
- spring boot 使用hibernate-validation
- osgViewer应用基础
- NVcaffe源码阅读——Blob的重新构建
- 排序算法
- NOIP2016Day1T1玩具谜题解题报告
- spring boot 多数据源动态切换
- Ubuntu14.04安装最新版Docker
- Hadoop小兵笔记【五】hadoop2.2.0伪分布式环境搭建疑难-第一个用例wordcount失败
- 一个m*n的矩阵,从左到右从上到下都是递增的,给一个数x,判断x是否在矩阵中。要求效率尽可能的高
- 多人聊天室(基于Linux的SOCKET UDP编程)
- Python 标准库 urllib
- spring boot 使用fastjson
- CodeForces 589F:Gourmet and Banquet(二分+贪心)
- lineage13.0 编译 过程 遇到的问题