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


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

3、新建 自定義注解 DataSource

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

全部代碼
/**
* 動態(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做動態(tài)數(shù)據(jù)源切換處理
public class DynamicDataSourceContextHolder {
public static final Logger log = LoggerFactory.getLogger(DynamicDataSourceContextHolder.class);
/**
* 使用ThreadLocal維護(hù)變量,ThreadLocal為每個使用該變量的線程提供獨(dú)立的變量副本,
* 所以每一個線程都可以獨(dú)立地改變自己的副本,而不會影響其它線程所對應(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添加對應(yīng)的數(shù)據(jù)庫枚舉
新增數(shù)據(jù)源的話 在下方繼續(xù)添加枚舉

全部代碼
public enum DataSourceType {
/**
* 主庫
*/
MASTER,
/**
* 從庫
*/
SLAVE
}
7、新增DruidConfig配置類配置讀配置源方法
有多個數(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)頭不會被重置
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);
/** 配置獲取連接等待超時的時間 */
datasource.setMaxWait(maxWait);
/** 配置間隔多久才進(jìn)行一次檢測,檢測需要關(guān)閉的空閑連接,單位是毫秒 */
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
/** 配置一個連接在池中最小、最大生存的時間,單位是毫秒 */
datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
datasource.setMaxEvictableIdleTimeMillis(maxEvictableIdleTimeMillis);
/**
* 用來檢測連接是否有效的sql,要求是一個查詢語句,常用select 'x'。如果validationQuery為null,testOnBorrow、testOnReturn、testWhileIdle都不會起作用。
*/
datasource.setValidationQuery(validationQuery);
/** 建議配置為true,不影響性能,并且保證安全性。申請連接的時候檢測,如果空閑時間大于timeBetweenEvictionRunsMillis,執(zhí)行validationQuery檢測連接是否有效。 */
datasource.setTestWhileIdle(testWhileIdle);
/** 申請連接時執(zhí)行validationQuery檢測連接是否有效,做了這個配置會降低性能。 */
datasource.setTestOnBorrow(testOnBorrow);
/** 歸還連接時執(zhí)行validationQuery檢測連接是否有效,做了這個配置會降低性能。 */
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注解

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

完成!?。。。。?!

總結(jié)
ok!到這里就完成了,啟動頁沒有報(bào)錯
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
詳解Java中的File文件類以及FileDescriptor文件描述類
在Java中File類可以用來新建文件和目錄對象,而FileDescriptor類則被用來表示文件或目錄的可操作性,接下來我們就來詳解Java中的File文件類以及FileDescriptor文件描述類2016-06-06
SpingMvc復(fù)雜參數(shù)傳收總結(jié)
這篇文章主要為大家介紹了SpingMvc復(fù)雜參數(shù)傳收總結(jié),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08
為什么wait和notify必須放在synchronized中使用
這篇文章主要介紹了為什么wait和notify必須放在synchronized中使用,文章圍繞主題的相關(guān)問題展開詳細(xì)介紹,具有一定的參考價值,需要的小伙伴可以參考以參考一下2022-05-05
Java利用HttpClient模擬POST表單操作應(yīng)用及注意事項(xiàng)
本文主要介紹JAVA中利用HttpClient模擬POST表單操作,希望對大家有所幫助。2016-04-04
Mybatis?連接mysql數(shù)據(jù)庫底層運(yùn)行的原理分析
這篇文章主要介紹了Mybatis?連接mysql數(shù)據(jù)庫底層運(yùn)行的原理分析,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03
SpringBoot?mybatis-plus使用json字段實(shí)戰(zhàn)指南
在現(xiàn)代應(yīng)用開發(fā)中經(jīng)常會使用JSON格式存儲和傳輸數(shù)據(jù),為了便捷地處理數(shù)據(jù)庫中的JSON字段,MyBatis-Plus提供了強(qiáng)大的JSON處理器,這篇文章主要給大家介紹了關(guān)于SpringBoot?mybatis-plus使用json字段的相關(guān)資料,需要的朋友可以參考下2024-01-01

