소스 검색

主从数据源配置读写分离

marxjaw 2 달 전
부모
커밋
9d59af8a59

+ 17 - 0
yt-irun/irun-service/pom.xml

@@ -40,6 +40,23 @@
             <artifactId>risk-feign</artifactId>
             <version>1.0-SNAPSHOT</version>
         </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>2.2.0</version>
+        </dependency>
+        <dependency>
+            <groupId>com.zaxxer</groupId>
+            <artifactId>HikariCP</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-aop</artifactId>
+        </dependency>
     </dependencies>
     <build>
         <finalName>irun-service</finalName>

+ 9 - 1
yt-irun/irun-service/src/main/java/com/ytpm/irun/IRunApplication.java

@@ -1,14 +1,22 @@
 package com.ytpm.irun;
 
+import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
 import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
 import org.springframework.cloud.openfeign.EnableFeignClients;
 import org.springframework.web.bind.annotation.RestController;
 
 
 @RestController
-@SpringBootApplication
+@SpringBootApplication(exclude = {
+        DataSourceAutoConfiguration.class,
+        DataSourceTransactionManagerAutoConfiguration.class,
+        JdbcTemplateAutoConfiguration.class
+})
 @EnableDiscoveryClient
 @EnableFeignClients(basePackages = {"com.ytpm.feign"})
 public class IRunApplication

+ 38 - 0
yt-irun/irun-service/src/main/java/com/ytpm/irun/aop/DataSourceAspect.java

@@ -0,0 +1,38 @@
+package com.ytpm.irun.aop;
+
+import com.ytpm.irun.config.datasource.DynamicDataSourceContextHolder;
+import com.ytpm.irun.enums.DataSourceType;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.After;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.annotation.Pointcut;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+
+@Aspect
+@Component
+@Order(1)
+public class DataSourceAspect {
+
+    @Pointcut("execution(* com.ytpm.irun.service.*.*(..))")
+    public void servicePointcut() {}
+
+    @Before("servicePointcut()")
+    public void beforeService(JoinPoint joinPoint) {
+        String methodName = joinPoint.getSignature().getName();
+        if (methodName.startsWith("get") ||
+            methodName.startsWith("find") ||
+            methodName.startsWith("select") ||
+            methodName.startsWith("query")) {
+            DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.SLAVE);
+        } else {
+            DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER);
+        }
+    }
+
+    @After("servicePointcut()")
+    public void afterService() {
+        DynamicDataSourceContextHolder.clear();
+    }
+}

+ 40 - 1
yt-irun/irun-service/src/main/java/com/ytpm/irun/config/datasource/DataSourceConfig.java

@@ -1,18 +1,29 @@
 package com.ytpm.irun.config.datasource;
 
+import com.ytpm.irun.enums.DataSourceType;
+import com.zaxxer.hikari.HikariDataSource;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.boot.jdbc.DataSourceBuilder;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.DependsOn;
 import org.springframework.context.annotation.Primary;
+import org.springframework.jdbc.datasource.DataSourceTransactionManager;
+import org.springframework.transaction.PlatformTransactionManager;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
 
 import javax.sql.DataSource;
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * 多数据源配置
  * @Marx
  */
-//@Configuration
+@Configuration
+@EnableTransactionManagement
 public class DataSourceConfig {
 
 //    @Primary
@@ -28,5 +39,33 @@ public class DataSourceConfig {
 //        return DataSourceBuilder.create().build();
 //    }
 
+    @Bean(name = "masterDataSource")
+    @ConfigurationProperties(prefix = "spring.datasource.master")
+    public DataSource masterDataSource() {
+        return DataSourceBuilder.create().type(HikariDataSource.class).build();
+    }
 
+    @Bean(name = "slaveDataSource")
+    @ConfigurationProperties(prefix = "spring.datasource.slave")
+    public DataSource slaveDataSource() {
+        return DataSourceBuilder.create().type(HikariDataSource.class).build();
+    }
+    @Primary
+    @Bean(name = "dynamicDataSource")
+    @DependsOn({"masterDataSource", "slaveDataSource"})
+    public DataSource dynamicDataSource() {
+        Map<Object, Object> dataSources = new HashMap<>();
+        dataSources.put(DataSourceType.MASTER, masterDataSource());
+        dataSources.put(DataSourceType.SLAVE, slaveDataSource());
+
+        DynamicDataSource ds = new DynamicDataSource();
+        ds.setDefaultTargetDataSource(masterDataSource());
+        ds.setTargetDataSources(dataSources);
+        return ds;
+    }
+
+    @Bean
+    public PlatformTransactionManager transactionManager(@Qualifier("dynamicDataSource")DataSource dynamicDataSource) {
+        return new DataSourceTransactionManager(dynamicDataSource);
+    }
 }

+ 10 - 0
yt-irun/irun-service/src/main/java/com/ytpm/irun/config/datasource/DynamicDataSource.java

@@ -0,0 +1,10 @@
+package com.ytpm.irun.config.datasource;
+
+import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
+
+public class DynamicDataSource extends AbstractRoutingDataSource {
+    @Override
+    protected Object determineCurrentLookupKey() {
+        return DynamicDataSourceContextHolder.getDataSourceType();
+    }
+}

+ 19 - 0
yt-irun/irun-service/src/main/java/com/ytpm/irun/config/datasource/DynamicDataSourceContextHolder.java

@@ -0,0 +1,19 @@
+package com.ytpm.irun.config.datasource;
+
+import com.ytpm.irun.enums.DataSourceType;
+
+public class DynamicDataSourceContextHolder {
+    private static final ThreadLocal<DataSourceType> CONTEXT = new ThreadLocal<>();
+
+    public static void setDataSourceType(DataSourceType type) {
+        CONTEXT.set(type);
+    }
+
+    public static DataSourceType getDataSourceType() {
+        return CONTEXT.get() == null ? DataSourceType.MASTER : CONTEXT.get();
+    }
+
+    public static void clear() {
+        CONTEXT.remove();
+    }
+}

+ 38 - 0
yt-irun/irun-service/src/main/java/com/ytpm/irun/config/datasource/MyBatisConfig.java

@@ -0,0 +1,38 @@
+package com.ytpm.irun.config.datasource;
+
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.mybatis.spring.SqlSessionFactoryBean;
+import org.mybatis.spring.SqlSessionTemplate;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+
+import javax.sql.DataSource;
+
+@Configuration
+@MapperScan(basePackages = "com.ytpm.irun.dao", sqlSessionFactoryRef = "sqlSessionFactory")
+public class MyBatisConfig {
+
+    @Bean
+    public SqlSessionFactory sqlSessionFactory(@Qualifier("dynamicDataSource") DataSource dataSource) throws Exception {
+        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
+        sessionFactory.setDataSource(dataSource);
+        // 添加XML映射文件位置(如果有)
+        sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver()
+                .getResources("classpath*:mapper/**/*.xml"));
+        // 添加类型别名包
+        sessionFactory.setTypeAliasesPackage("com.ytpm.app.model");
+        // 配置其他MyBatis设置
+        org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
+        configuration.setMapUnderscoreToCamelCase(true);
+        sessionFactory.setConfiguration(configuration);
+        return sessionFactory.getObject();
+    }
+
+    @Bean
+    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory) {
+        return new SqlSessionTemplate(sqlSessionFactory);
+    }
+}

+ 5 - 0
yt-irun/irun-service/src/main/java/com/ytpm/irun/enums/DataSourceType.java

@@ -0,0 +1,5 @@
+package com.ytpm.irun.enums;
+
+public enum DataSourceType {
+    MASTER, SLAVE
+}