SpringBoot框架DataSource多數(shù)據(jù)源配置方式
新增數(shù)據(jù)源填入xml文件
這里使用的是新搭建的一個(gè)架子,依賴什么的 就自己Maven工廠去下載吧
我是按照若依的架子搭建的,之前弄過一次,失敗了哈哈哈
進(jìn)入正題
1、導(dǎo)入依賴


2、在配置文件中添加數(shù)據(jù)源信息

3、新建 自定義注解 DataSource

4、新建 DynamicDataSource
繼承Spring boot提供的AbstractRoutingDataSource 根據(jù)用戶定義的規(guī)則選擇當(dāng)前的數(shù)據(jù)源
它的抽象方法 determineCurrentLookupKey() 決定使用哪個(gè)數(shù)據(jù)源。

全部代碼
/**
* 動(dòng)態(tài)數(shù)據(jù)源
* @program: LanAn
* @description: DynamicDataSource
* @author: LanAn
* @create: 2022-08-17 15:33
**/
public class DynamicDataSource extends AbstractRoutingDataSource {
public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) {
super.setDefaultTargetDataSource(defaultTargetDataSource);
super.setTargetDataSources(targetDataSources);
super.afterPropertiesSet();
}
/**
* 根據(jù)用戶定義的規(guī)則選擇當(dāng)前的數(shù)據(jù)源]
* @return: java.lang.Object
* @Author: LanAn
* @Date: 2022/8/17 0017
*/
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceContextHolder.getDataSourceType();
}
}
5、新建DynamicDataSourceContextHolder做動(dòng)態(tài)數(shù)據(jù)源切換處理
public class DynamicDataSourceContextHolder {
public static final Logger log = LoggerFactory.getLogger(DynamicDataSourceContextHolder.class);
/**
* 使用ThreadLocal維護(hù)變量,ThreadLocal為每個(gè)使用該變量的線程提供獨(dú)立的變量副本,
* 所以每一個(gè)線程都可以獨(dú)立地改變自己的副本,而不會(huì)影響其它線程所對(duì)應(yīng)的副本。
*/
private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();
/**
* 設(shè)置數(shù)據(jù)源的變量
*/
public static void setDataSourceType(String dsType)
{
log.info("切換到{}數(shù)據(jù)源", dsType);
CONTEXT_HOLDER.set(dsType);
}
/**
* 獲得數(shù)據(jù)源的變量
*/
public static String getDataSourceType()
{
return CONTEXT_HOLDER.get();
}
/**
* 清空數(shù)據(jù)源變量
*/
public static void clearDataSourceType()
{
CONTEXT_HOLDER.remove();
}
}
6、新建DataSourceType添加對(duì)應(yīng)的數(shù)據(jù)庫枚舉
新增數(shù)據(jù)源的話 在下方繼續(xù)添加枚舉

全部代碼
public enum DataSourceType {
/**
* 主庫
*/
MASTER,
/**
* 從庫
*/
SLAVE
}
7、新增DruidConfig配置類配置讀配置源方法
有多個(gè)數(shù)據(jù)源可以在下方照葫蘆畫瓢 哈哈哈


配置類全部代碼
public class DruidConfig {
/**
* 主庫數(shù)據(jù)源
* @Param: [druidProperties]
* @return: javax.sql.DataSource
* @Author: LanAn
* @Date: 2022/8/17 0017
*/
@Bean
@ConfigurationProperties("spring.datasource.druid.master")
public DataSource masterDataSource(DruidProperties druidProperties) {
DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
return druidProperties.dataSource(dataSource);
}
/**
* 從庫數(shù)據(jù)源
* @Param: [druidProperties]
* @return: javax.sql.DataSource
* @Author: LanAn
* @Date: 2022/8/17 0017
*/
@Bean
@ConfigurationProperties("spring.datasource.druid.slave")
@ConditionalOnProperty(prefix = "spring.datasource.druid.slave", name = "enabled", havingValue = "true")
public DataSource slaveDataSource(DruidProperties druidProperties) {
DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
return druidProperties.dataSource(dataSource);
}
@Bean(name = "dynamicDataSource")
@Primary
public DynamicDataSource dataSource(DataSource masterDataSource) {
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource);
setDataSource(targetDataSources, DataSourceType.SLAVE.name(), "slaveDataSource");
return new DynamicDataSource(masterDataSource, targetDataSources);
}
/**
* 設(shè)置數(shù)據(jù)源
*
* @param targetDataSources 備選數(shù)據(jù)源集合
* @param sourceName 數(shù)據(jù)源名稱
* @param beanName bean名稱
*/
public void setDataSource(Map<Object, Object> targetDataSources, String sourceName, String beanName) {
try {
DataSource dataSource = SpringUtils.getBean(beanName);
targetDataSources.put(sourceName, dataSource);
} catch (Exception e) {
}
}
/**
* 去除監(jiān)控頁面底部的廣告
*/
@SuppressWarnings({"rawtypes", "unchecked"})
@Bean
@ConditionalOnProperty(name = "spring.datasource.druid.statViewServlet.enabled", havingValue = "true")
public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties) {
// 獲取web監(jiān)控頁面的參數(shù)
DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
// 提取common.js的配置路徑
String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
final String filePath = "support/http/resources/js/common.js";
// 創(chuàng)建filter進(jìn)行過濾
Filter filter = new Filter() {
@Override
public void init(javax.servlet.FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
chain.doFilter(request, response);
// 重置緩沖區(qū),響應(yīng)頭不會(huì)被重置
response.resetBuffer();
// 獲取common.js
String text = Utils.readFromResource(filePath);
// 正則替換banner, 除去底部的廣告信息
text = text.replaceAll("<a.*?banner\"></a><br/>", "");
text = text.replaceAll("powered.*?shrek.wang</a>", "");
response.getWriter().write(text);
}
@Override
public void destroy() {
}
};
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(filter);
registrationBean.addUrlPatterns(commonJsPattern);
return registrationBean;
}
}
嘶~~~~少了倆配置,補(bǔ)到后邊吧
8、新建 DruidProperties druid配置屬性
@Configuration
public class DruidProperties {
@Value("${spring.datasource.druid.initialSize}")
private int initialSize;
@Value("${spring.datasource.druid.minIdle}")
private int minIdle;
@Value("${spring.datasource.druid.maxActive}")
private int maxActive;
@Value("${spring.datasource.druid.maxWait}")
private int maxWait;
@Value("${spring.datasource.druid.timeBetweenEvictionRunsMillis}")
private int timeBetweenEvictionRunsMillis;
@Value("${spring.datasource.druid.minEvictableIdleTimeMillis}")
private int minEvictableIdleTimeMillis;
@Value("${spring.datasource.druid.maxEvictableIdleTimeMillis}")
private int maxEvictableIdleTimeMillis;
@Value("${spring.datasource.druid.validationQuery}")
private String validationQuery;
@Value("${spring.datasource.druid.testWhileIdle}")
private boolean testWhileIdle;
@Value("${spring.datasource.druid.testOnBorrow}")
private boolean testOnBorrow;
@Value("${spring.datasource.druid.testOnReturn}")
private boolean testOnReturn;
public DruidDataSource dataSource(DruidDataSource datasource) {
/** 配置初始化大小、最小、最大 */
datasource.setInitialSize(initialSize);
datasource.setMaxActive(maxActive);
datasource.setMinIdle(minIdle);
/** 配置獲取連接等待超時(shí)的時(shí)間 */
datasource.setMaxWait(maxWait);
/** 配置間隔多久才進(jìn)行一次檢測(cè),檢測(cè)需要關(guān)閉的空閑連接,單位是毫秒 */
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
/** 配置一個(gè)連接在池中最小、最大生存的時(shí)間,單位是毫秒 */
datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
datasource.setMaxEvictableIdleTimeMillis(maxEvictableIdleTimeMillis);
/**
* 用來檢測(cè)連接是否有效的sql,要求是一個(gè)查詢語句,常用select 'x'。如果validationQuery為null,testOnBorrow、testOnReturn、testWhileIdle都不會(huì)起作用。
*/
datasource.setValidationQuery(validationQuery);
/** 建議配置為true,不影響性能,并且保證安全性。申請(qǐng)連接的時(shí)候檢測(cè),如果空閑時(shí)間大于timeBetweenEvictionRunsMillis,執(zhí)行validationQuery檢測(cè)連接是否有效。 */
datasource.setTestWhileIdle(testWhileIdle);
/** 申請(qǐng)連接時(shí)執(zhí)行validationQuery檢測(cè)連接是否有效,做了這個(gè)配置會(huì)降低性能。 */
datasource.setTestOnBorrow(testOnBorrow);
/** 歸還連接時(shí)執(zhí)行validationQuery檢測(cè)連接是否有效,做了這個(gè)配置會(huì)降低性能。 */
datasource.setTestOnReturn(testOnReturn);
return datasource;
}
}
9、多數(shù)據(jù)源處理
/**
* @program: LanAn
* 多數(shù)據(jù)源處理
* @description: DataSourceAspect
* @author: LanAn
* @create: 2022-08-17 14:21
**/
@Aspect
@Order(1)
@Component
public class DataSourceAspect {
protected Logger logger = LoggerFactory.getLogger(getClass());
@Pointcut("@annotation(com.lanan.common.annotation.DataSource)"
+ "|| @within(com.lanan.common.annotation.DataSource)")
public void dsPointCut() {
}
@Around("dsPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
DataSource dataSource = getDataSource(point);
if (StringUtils.isNotNull(dataSource)) {
DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name());
}
try {
return point.proceed();
} finally {
// 銷毀數(shù)據(jù)源 在執(zhí)行方法之后
DynamicDataSourceContextHolder.clearDataSourceType();
}
}
/**
* 獲取需要切換的數(shù)據(jù)源
*/
public DataSource getDataSource(ProceedingJoinPoint point) {
MethodSignature signature = (MethodSignature) point.getSignature();
DataSource dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class);
if (Objects.nonNull(dataSource)) {
return dataSource;
}
return AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class);
}
}
10、配置完成 使用方法
在實(shí)現(xiàn)類上直接使用@DataSource注解

可以在方法上指定使用某個(gè)數(shù)據(jù)源

完成!?。。。。。?/p>

總結(jié)
ok!到這里就完成了,啟動(dòng)頁沒有報(bào)錯(cuò)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot集成ElasticSearch(ES)實(shí)現(xiàn)全文搜索功能
Elasticsearch是一個(gè)開源的分布式搜索和分析引擎,它被設(shè)計(jì)用于處理大規(guī)模數(shù)據(jù)集,它提供了一個(gè)分布式多用戶能力的全文搜索引擎,本文將給大家介紹SpringBoot集成ElasticSearch(ES)實(shí)現(xiàn)全文搜索功能,需要的朋友可以參考下2024-02-02
Java8中AbstractExecutorService與FutureTask源碼詳解
這篇文章主要給大家介紹了關(guān)于Java8中AbstractExecutorService與FutureTask的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2022-01-01
Spring Boot定時(shí)器創(chuàng)建及使用解析
這篇文章主要介紹了Spring Boot定時(shí)器創(chuàng)建及使用解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07
Mybatis-Plus自動(dòng)生成的數(shù)據(jù)庫id過長(zhǎng)的解決
這篇文章主要介紹了Mybatis-Plus自動(dòng)生成的數(shù)據(jù)庫id過長(zhǎng)的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12

