多数据源动态切换⾃定义注解⽅式
1、通过切⾯的⽅式进⾏数据源的切换;切的是 注解@DataSoure;
@Pointcut("@annotation(com.managemon.annotation.DataSource)"
+ "|| @within(com.managemon.annotation.DataSource)")
2、然后切⾯获取当前的⽅法的注解中所要切换的数据库
3、设置数据源的变量ThreadLocal<String> CONTEXT_HOLDER.set(dsType); (
什么是ThreadLocal 
ThreadLocal是java中的线程本地变量,⽤于每个线程保存⾃⼰的变量,使线程间的变量互不⼲扰。
使⽤ThreadLocal维护变量,ThreadLocal为每个使⽤该变量的线程提供独⽴的变量副本,
所以每⼀个线程都可以独⽴地改变⾃⼰的副本,⽽不会影响其它线程所对应的副本。
4、使⽤ AbstractRoutingDataSource实现动态数据源切换
1.定义DynamicDataSource类继承抽象类AbstractRoutingDataSource,并实现了determineCurrentLookupKey()⽅法。
2.把配置的多个数据源会放在AbstractRoutingDataSource的 targetDataSources和defaultTargetDataSource中,然后通过afterPropertiesSet()⽅法将数据源分别进⾏复制到resolvedDataSources和resolvedDefaultDataSource中。
3.调⽤AbstractRoutingDataSource的getConnection()的⽅法的时候,先调⽤determineTargetDataSource()⽅法返回
DataSource在进⾏getConnection()。
数据源配置 这⾥⽤的是postgresql
# 数据源配置
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: org.postgresql.Driver
druid:
# 主库数据源
system:
url: jdbc:postgresql://207:12004/db_system?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverT        username: postgres
password: DB$zs#%THI%q4^PYS
# 从库数据源
template:
# 从数据源开关/默认关闭/captchaImage
enabled: true
url: jdbc:postgresql://207:12004/db_work_template?autoReconnect=true&&useSSL=true
username: postgres
password: DB$zs#%THI%q4^PYS
# 从库数据源
log:
# 从数据源开关/默认关闭/captchaImage
enabled: true
url: jdbc:postgresql://207:12004/db_work_log?autoReconnect=true&&useSSL=true
username: postgres
js 正则替换
password: DB$zs#%THI%q4^PYS
# 从库数据源
event:
# 从数据源开关/默认关闭/captchaImage
enabled: true
url: jdbc:postgresql://207:12004/db_work_event?autoReconnect=true&&useSSL=true
username: postgres
password: DB$zs#%THI%q4^PYS
# 从库数据源
statis:
# 从数据源开关/默认关闭/captchaImage
enabled: true
url: jdbc:postgresql://207:12004/db_work_statis?autoReconnect=true&&useSSL=true        username: postgres
password: DB$zs#%THI%q4^PYS
# 从库数据源
allelism:
# 从数据源开关/默认关闭/captchaImage
enabled: true
url: jdbc:postgresql://207:12004/db_allelism?autoReconnect=true&&useSSL=true
username: postgres
password: DB$zs#%THI%q4^PYS
# 从库数据源
activiti:
# 从数据源开关/默认关闭/captchaImage
enabled: true
url: jdbc:postgresql://207:12004/db_activiti?autoReconnect=true&&useSSL=true
username: postgres
password: DB$zs#%THI%q4^PYS
# 初始连接数
initialSize: 5
# 最⼩连接池数量
minIdle: 10
# 最⼤连接池数量
maxActive: 20
# 配置获取连接等待超时的时间
maxWait: 60000
# 配置间隔多久才进⾏⼀次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 配置⼀个连接在池中最⼩⽣存的时间,单位是毫秒
minEvictableIdleTimeMillis: 300000
# 配置⼀个连接在池中最⼤⽣存的时间,单位是毫秒
maxEvictableIdleTimeMillis: 900000
# 配置检测连接是否有效
validationQuery: SELECT 1
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
webStatFilter:
enabled: true
statViewServlet:
enabled: true
# 设置⽩名单,不填则允许所有访问
allow:
url-pattern: /druid/*
# 控制台管理⽤户名和密码
login-username:
login-password:
filter:
stat:
enabled: true
# 慢SQL记录
log-slow-sql: true
slow-sql-millis: 1000
merge-sql: true
wall:
config:
multi-statement-allow: true
配置多数据源
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
import com.alibaba.druid.util.Utils;
import ums.DataSourceType;
import com.fig.properties.DruidProperties;
import com.managemon.datasource.DynamicDataSource;
import com.manage.util.spring.SpringUtils;
import org.activiti.spring.SpringAsyncExecutor;
import org.activiti.spring.SpringProcessEngineConfiguration;
import org.activiti.spring.boot.AbstractProcessEngineAutoConfiguration;
import org.springframework.dition.ConditionalOnProperty;
import org.t.properties.ConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import t.annotation.Bean;
import t.annotation.Configuration;
import t.annotation.Primary;
import ansaction.PlatformTransactionManager;
import javax.servlet.*;
import javax.sql.DataSource;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* druid 配置多数据源
*
* @author xxx
*/
@Configuration
public class DruidConfig  extends AbstractProcessEngineAutoConfiguration {
@Bean
@ConfigurationProperties("spring.datasource.druid.system")
public DataSource systemDataSource(DruidProperties druidProperties) {
DruidDataSource dataSource = ate().build();
return druidProperties.dataSource(dataSource);
}
@Bean
@ConfigurationProperties("spring.datasource.druid.activiti")
@ConditionalOnProperty(prefix = "spring.datasource.druid.activiti", name = "enabled", havingValue = "true")    public DataSource activitiDataSource(DruidProperties druidProperties) {
DruidDataSource dataSource = ate().build();
return druidProperties.dataSource(dataSource);
}
@Bean
@ConfigurationProperties("spring.datasource.druid.allelism")
@ConditionalOnProperty(prefix = "spring.datasource.druid.allelism", name = "enabled", havingValue = "true")    public DataSource allelismDataSource(DruidProperties druidProperties) {
DruidDataSource dataSource = ate().build();
return druidProperties.dataSource(dataSource);
}
@Bean
@ConfigurationProperties("spring.plate")
@ConditionalOnProperty(prefix = "spring.plate", name = "enabled", havingValue = "true")    public DataSource templateDataSource(DruidProperties druidProperties) {
DruidDataSource dataSource = ate().build();
return druidProperties.dataSource(dataSource);
}
@Bean
@ConfigurationProperties("spring.datasource.druid.log")
@ConditionalOnProperty(prefix = "spring.datasource.druid.log", name = "enabled", havingValue = "true")
public DataSource logDataSource(DruidProperties druidProperties) {
DruidDataSource dataSource = ate().build();
return druidProperties.dataSource(dataSource);
}
@Bean
@ConfigurationProperties("spring.datasource.druid.event")
@ConditionalOnProperty(prefix = "spring.datasource.druid.event", name = "enabled", havingValue = "true")    public DataSource eventDataSource(DruidProperties druidProperties) {
DruidDataSource dataSource = ate().build();
return druidProperties.dataSource(dataSource);
}
@Bean
@ConfigurationProperties("spring.datasource.druid.statis")
@ConditionalOnProperty(prefix = "spring.datasource.druid.statis", name = "enabled", havingValue = "true")    public DataSource statisDataSource(DruidProperties druidProperties) {
DruidDataSource dataSource = ate().build();
return druidProperties.dataSource(dataSource);
}
@Bean(name = "dynamicDataSource")
@Primary
public DynamicDataSource dataSource(DataSource systemDataSource) {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DataSourceType.SYSTEM.name(), systemDataSource);
setDataSource(targetDataSources, DataSourceType.ACTIVITI.name(), "activitiDataSource");
setDataSource(targetDataSources, DataSourceType.ALLELISM.name(), "allelismDataSource");
setDataSource(targetDataSources, DataSourceType.TEMPLATE.name(), "templateDataSource");
setDataSource(targetDataSources, DataSourceType.LOG.name(), "logDataSource");
setDataSource(targetDataSources, DataSourceType.EVENT.name(), "eventDataSource");
setDataSource(targetDataSources, DataSourceType.STATIS.name(), "statisDataSource");
return new DynamicDataSource(systemDataSource, targetDataSources);
}
/**
* 设置数据源
*
* @param targetDataSources 备选数据源集合
* @param sourceName        数据源名称
* @param beanName          bean名称
*/
public void setDataSource(Map<Object, Object> targetDataSources, String sourceName, String beanName) {        try {
DataSource dataSource = Bean(beanName);
targetDataSources.put(sourceName, dataSource);
} catch (Exception e) {
}
}
@Bean
public SpringProcessEngineConfiguration springProcessEngineConfiguration(
PlatformTransactionManager transactionManager,
SpringAsyncExecutor springAsyncExecutor) throws IOException {
return baseSpringProcessEngineConfiguration(
transactionManager,
springAsyncExecutor);
}
}
/**
* 去除监控页⾯底部的⼴告
*/
@SuppressWarnings({"rawtypes", "unchecked"})
@Bean
@ConditionalOnProperty(name = "spring.datasource.abled", havingValue = "true")    public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties) {
// 获取web监控页⾯的参数
DruidStatProperties.StatViewServlet config = StatViewServlet();
// 提取common.js的配置路径
String pattern = UrlPattern() != null ? UrlPattern() : "/druid/*";
String commonJsPattern = placeAll("\\*", "js/common.js");
final String filePath = "support/http/resources/js/common.js";
// 创建filter进⾏过滤
Filter filter = new Filter() {
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
chain.doFilter(request, response);
// 重置缓冲区,响应头不会被重置
// 获取common.js
String text = adFromResource(filePath);
// 正则替换banner, 除去底部的⼴告信息
text = placeAll("<a.*?banner\"></a><br/>", "");
text = placeAll("powered.*?shrek.wang</a>", "");
}
@Override
public void destroy() {
}
};
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(filter);
registrationBean.addUrlPatterns(commonJsPattern);
return registrationBean;
}
}
⾃定义注解