基於mycat整合springboot項目實現讀寫分離

主要的原理步驟是,springboot項目整合mycat後,通過aop攔截後切換數據源,然後在通過mycat路由到相應的數據庫中實現讀寫分離,如下是一些核心文件及配置。
項目地址:springboot-mysqlcopy

pom.xml

<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.4.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-aop</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.3.2</version>
		</dependency>

		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.0.23</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

application.yml

server:
  port: 8282

spring:
  datasource:
    ###可讀數據源
    select:
      jdbc-url: jdbc:mysql://192.168.78.231:8066/TESTDB
      driver-class-name: com.mysql.jdbc.Driver
      username: user
      password: user
    ####可寫數據源
    update:
      jdbc-url: jdbc:mysql://192.168.78.231:8066/TESTDB
      driver-class-name: com.mysql.jdbc.Driver
      username: root
      password: root
    type: com.alibaba.druid.pool.DruidDataSource

DataSourceContextHolder

@Component
@Lazy(false)
public class DataSourceContextHolder {
	// 採用ThreadLocal 保存本地多數據源
	private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();

	// 設置數據源類型
	public static void setDbType(String dbType) {
		contextHolder.set(dbType);
	}

	public static String getDbType() {
		return contextHolder.get();
	}

	public static void clearDbType() {
		contextHolder.remove();
	}
}

DataSourceConfig

@Configuration
public class DataSourceConfig {

	// 創建可讀數據源
	@Bean(name = "selectDataSource")
	@ConfigurationProperties(prefix = "spring.datasource.select") // application.properteis中對應屬性的前綴
	public DataSource dataSource1() {
		return DataSourceBuilder.create().build();
	}

	// 創建可寫數據源
	@Bean(name = "updateDataSource")
	@ConfigurationProperties(prefix = "spring.datasource.update") // application.properteis中對應屬性的前綴
	public DataSource dataSource2() {
		return DataSourceBuilder.create().build();
	}

}

DynamicDataSource

//在Spring 2.0.1中引入了AbstractRoutingDataSource, 該類充當了DataSource的路由中介, 能有在運行時, 根據某種key值來動態切換到真正的DataSource上。

@Component
@Primary
public class DynamicDataSource extends AbstractRoutingDataSource {
	@Autowired
	@Qualifier("selectDataSource")
	private DataSource selectDataSource;

	@Autowired
	@Qualifier("updateDataSource")
	private DataSource updateDataSource;

	/**
	 * 這個是主要的方法,返回的是生效的數據源名稱
	 */
	@Override
	protected Object determineCurrentLookupKey() {
		System.out.println("DataSourceContextHolder:::" + DataSourceContextHolder.getDbType());
		return DataSourceContextHolder.getDbType();
	}

	/**
	 * 配置數據源信息
	 */
	@Override
	public void afterPropertiesSet() {
		Map<Object, Object> map = new HashMap<>();
		map.put("selectDataSource", selectDataSource);
		map.put("updateDataSource", updateDataSource);
		setTargetDataSources(map);
		setDefaultTargetDataSource(updateDataSource);
		super.afterPropertiesSet();
	}
}

SwitchDataSourceAOP

@Aspect
@Component
@Lazy(false)
@Order(0) // Order設定AOP執行順序 使之在數據庫事務上先執行
public class SwitchDataSourceAOP {
	// 這裏切到你的方法目錄
	@Before("execution(* com.mayikt.service.*.*(..))")
	public void process(JoinPoint joinPoint) {
		String methodName = joinPoint.getSignature().getName();
		if (methodName.startsWith("get") || methodName.startsWith("count") || methodName.startsWith("find")
				|| methodName.startsWith("list") || methodName.startsWith("select") || methodName.startsWith("check")) {
			DataSourceContextHolder.setDbType("selectDataSource");
		} else {
			// 切換dataSource
			DataSourceContextHolder.setDbType("updateDataSource");
		}
	}
}

以上就是項目整合mycat後實現對數據庫的讀寫分離,自我總結學習並分享給大家!
項目地址:springboot-mysqlcopy
學習參考:螞蟻課堂

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章