SpringBoot自定義注解使用讀寫(xiě)分離Mysql數(shù)據(jù)庫(kù)的實(shí)例教程
需求場(chǎng)景
為了防止代碼中有的SQL慢查詢(xún),影響我們線上主數(shù)據(jù)庫(kù)的性能。我們需要將sql查詢(xún)操作切換到從庫(kù)中進(jìn)行。為了使用方便,將自定義注解的形式使用。
mysql導(dǎo)入的依賴(lài)
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.16</version> </dependency>
代碼實(shí)現(xiàn)
配置文件
application.yml
spring: datasource: master: username: root password: 123456 jdbc-url: jdbc:mysql://localhost:3306/master?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8 driver-class-name: com.mysql.cj.jdbc.Driver slave: username: root password: 123456 jdbc-url: jdbc:mysql://localhost:3306/slave?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8 driver-class-name: com.mysql.cj.jdbc.Driver
DataSourceType
/** * 數(shù)據(jù)源類(lèi)型枚舉 * @author yangjc01 * @create 2020/11/02 */ public enum DataSourceType { /** * 主庫(kù),主要進(jìn)行寫(xiě)操作 */ MASTER, /** * 從庫(kù),進(jìn)行讀操作 */ SLAVE }
DynamicDataSource
/** * 動(dòng)態(tài)數(shù)據(jù)源 * @author yangjc01 * @create 2020/11/02 */ public class DynamicDataSource extends AbstractRoutingDataSource { public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) { super.setDefaultTargetDataSource(defaultTargetDataSource); super.setTargetDataSources(targetDataSources); super.afterPropertiesSet(); } @Override protected Object determineCurrentLookupKey() { return DynamicDataSourceContextHolder.getDateSourceType(); } }
DynamicDataSourceContextHolder
public class DynamicDataSourceContextHolder { /** * 使用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 setDateSourceType(String dsType) { CONTEXT_HOLDER.set(dsType); } /** * 獲得數(shù)據(jù)源的變量 */ public static String getDateSourceType() { return CONTEXT_HOLDER.get(); } /** * 清空數(shù)據(jù)源變量 */ public static void clearDateSourceType() { CONTEXT_HOLDER.remove(); } }
DataSource 注解
/** * @author yangjc01 * @create 2020/11/01 */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface DataSource { /** * 切換數(shù)據(jù)源 */ DataSourceType value() default DataSourceType.MASTER; }
DataSourceAspect 切面
@Aspect @Order(1) @Component public class DataSourceAspect { @Pointcut("@annotation(com.jgame.mis.annotation.DataSource)") public void dsPointCut() { } @Around("dsPointCut()") public Object around(ProceedingJoinPoint point) throws Throwable { MethodSignature signature = (MethodSignature) point.getSignature(); Method method = signature.getMethod(); DataSource dataSource = method.getAnnotation(DataSource.class); if (null!=dataSource) { DynamicDataSourceContextHolder. setDateSourceType(dataSource.value().name()); } try { return point.proceed(); } finally { // 銷(xiāo)毀數(shù)據(jù)源 在執(zhí)行方法之后 DynamicDataSourceContextHolder.clearDateSourceType(); } } }
DataSourceConfig
@Configuration public class DataSourceConfig { @Bean @ConfigurationProperties("spring.datasource.master") public DataSource masterDataSource() { return DataSourceBuilder.create().build(); } @Bean @ConfigurationProperties("spring.datasource.slave") public DataSource slaveDataSource() { return DataSourceBuilder.create().build(); } @Bean(name = "dynamicDataSource") @Primary public DynamicDataSource dataSource() { Map<Object, Object> targetDataSources = new HashMap<>(); targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource()); targetDataSources.put(DataSourceType.SLAVE.name(), slaveDataSource()); return new DynamicDataSource(masterDataSource(), targetDataSources); } }
啟動(dòng)類(lèi)上添加注解
@Import({DataSourceConfig.class}) @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
需要使用的方法上
@DataSource(value = DataSourceType.SLAVE)
DEMO
@Select("select * from user") @DataSource(value = DataSourceType.SLAVE) List<User> selectUserList();
總結(jié)
到此這篇關(guān)于SpringBoot自定義注解使用讀寫(xiě)分離Mysql數(shù)據(jù)庫(kù)的文章就介紹到這了,更多相關(guān)SpringBoot自定義注解使用讀寫(xiě)分離Mysql內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java實(shí)現(xiàn)微信公眾號(hào)發(fā)送模版消息
大家好,本篇文章主要講的是Java實(shí)現(xiàn)微信公眾號(hào)發(fā)送模版消息,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下2022-01-01Spring MVC中使用Controller如何進(jìn)行重定向
這篇文章主要介紹了Spring MVC中使用Controller如何進(jìn)行重定向操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09Java實(shí)現(xiàn)動(dòng)物換位游戲完整?過(guò)程詳解
大家好,今天嘗試用Java編程設(shè)計(jì)一個(gè)GUI界面的動(dòng)物換位游戲,游戲的結(jié)果是讓左右兩組的動(dòng)物交換位置,以下是具體設(shè)計(jì)過(guò)程,供大家參考2022-07-07Java page cache回寫(xiě)機(jī)制案例詳解
這篇文章主要介紹了Java page cache回寫(xiě)機(jī)制案例詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-09-09Java執(zhí)行cmd命令兩種實(shí)現(xiàn)方法解析
這篇文章主要介紹了Java執(zhí)行cmd命令兩種實(shí)現(xiàn)方法解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07List集合按某個(gè)屬性或者字段進(jìn)行分組的操作
這篇文章主要介紹了List集合按某個(gè)屬性或者字段進(jìn)行分組的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06Java中parallelStream().forEach()的踩坑日記
本文主要介紹了Java中parallelStream().forEach()的踩坑日記,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-06-06