shuhao 2 years ago
parent
commit
95367fe11d

+ 1 - 1
fast-boot.iml

@@ -6,7 +6,7 @@
         <setting name="validation-enabled" value="true" />
         <setting name="provider-name" value="Hibernate" />
         <datasource-mapping>
-          <factory-entry name="fast-boot" />
+          <factory-entry name="Entities" />
         </datasource-mapping>
         <naming-strategy-map />
       </configuration>

+ 1 - 0
src/main/java/com/xiesx/fastboot/core/jpa/JpaPlusRepository.java

@@ -2,6 +2,7 @@ package com.xiesx.fastboot.core.jpa;
 
 import java.util.List;
 
+import com.xiesx.fastboot.core.jpa.annotation.TargetDataSource;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
 import org.springframework.data.domain.Sort;

+ 15 - 0
src/main/java/com/xiesx/fastboot/core/jpa/annotation/TargetDataSource.java

@@ -0,0 +1,15 @@
+package com.xiesx.fastboot.core.jpa.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * @Remark: 自定义 动态切换数据库的注解
+ * @Author: lsw
+ * @Date : 2022/3/14 18:27
+ */
+@Target({ElementType.METHOD, ElementType.TYPE})
+@Retention(value = RetentionPolicy.RUNTIME)
+@Documented
+public @interface TargetDataSource {
+    String value();
+}

+ 34 - 0
src/main/java/com/xiesx/fastboot/core/jpa/aop/RoutingAopAspect.java

@@ -0,0 +1,34 @@
+package com.xiesx.fastboot.core.jpa.aop;
+
+import com.xiesx.fastboot.core.jpa.annotation.TargetDataSource;
+import com.xiesx.fastboot.core.jpa.cfg.DynamicRoutingDataSource;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+
+/**
+ * @Remark: 切面拦截动态数据源注解
+ * @Author: lsw
+ * @Date : 2022/3/14 18:26
+ */
+@Order(0)
+@Aspect
+@Component
+public class RoutingAopAspect {
+
+    public RoutingAopAspect(){
+        System.out.println("--------------------------RoutingAopAspect");
+    }
+
+    @Around("@annotation(targetDataSource)")
+    public Object routingWithDataSource(ProceedingJoinPoint joinPoint, TargetDataSource targetDataSource) throws Throwable {
+        try {
+            DynamicRoutingDataSource.setRoutingDataSource(targetDataSource.value());
+            return joinPoint.proceed();
+        } finally {
+            DynamicRoutingDataSource.removeRoutingDataSource();
+        }
+    }
+}

+ 13 - 0
src/main/java/com/xiesx/fastboot/core/jpa/cfg/DataSourceEnum.java

@@ -0,0 +1,13 @@
+package com.xiesx.fastboot.core.jpa.cfg;
+
+/**
+ * @Remark: 数据源类型
+ * @Author: lsw
+ * @Date : 2022/3/15 9:47
+ */
+public interface DataSourceEnum {
+
+    String master = "write";
+    String slave = "read";
+
+}

+ 43 - 0
src/main/java/com/xiesx/fastboot/core/jpa/cfg/DynamicRoutingDataSource.java

@@ -0,0 +1,43 @@
+package com.xiesx.fastboot.core.jpa.cfg;
+
+import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
+
+/**
+ * @Remark: 加载数据库配置
+ * @Author: lsw
+ * @Date : 2022/3/14 18:25
+ */
+public class DynamicRoutingDataSource extends AbstractRoutingDataSource {
+    @Override
+    protected Object determineCurrentLookupKey() {
+        Object lookupKey = DynamicRoutingDataSource.getRoutingDataSource();
+        System.err.println(Thread.currentThread().getName() + " determineCurrentLookupKey : " + lookupKey);
+        return lookupKey;
+    }
+
+    private static final ThreadLocal<Object> threadLocalDataSource = new ThreadLocal<>();
+
+
+    public static void setRoutingDataSource(Object dataSource) {
+        if (dataSource == null) {
+            throw new NullPointerException();
+        }
+        threadLocalDataSource.set(dataSource);
+        // System.err.println(Thread.currentThread().getName()+" set RoutingDataSource : " + dataSource);
+    }
+
+    public static Object getRoutingDataSource() {
+        Object dataSourceType = threadLocalDataSource.get();
+        if (dataSourceType == null) {
+            threadLocalDataSource.set(DataSourceEnum.master);
+            return getRoutingDataSource();
+        }
+        // System.err.println(Thread.currentThread().getName()+" get RoutingDataSource : " + dataSourceType);
+        return dataSourceType;
+    }
+
+    public static void removeRoutingDataSource() {
+        threadLocalDataSource.remove();
+        // System.err.println(Thread.currentThread().getName()+" remove RoutingDataSource");
+    }
+}

+ 48 - 0
src/main/java/com/xiesx/fastboot/core/jpa/cfg/JpaPlusCfg.java

@@ -1,13 +1,28 @@
 package com.xiesx.fastboot.core.jpa.cfg;
 
 import javax.persistence.EntityManager;
+import javax.sql.DataSource;
 
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
+import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
+import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
+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.Primary;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
 import com.querydsl.jpa.impl.JPAQueryFactory;
 
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * @title TokenCfg.java
  * @description 令牌认证
@@ -22,4 +37,37 @@ public class JpaPlusCfg{
         return new JPAQueryFactory(entityManager);
     }
 
+    @Bean(name = "masterDataSource")
+    @ConfigurationProperties(prefix = "spring.datasource.write")
+    public DataSource masterDataSource() {
+        return DataSourceBuilder.create().build();
+    }
+
+    @Bean(name = "slaveDataSource")
+    @ConfigurationProperties(prefix = "spring.datasource.read")
+    public DataSource slaveDataSource() {
+        return DataSourceBuilder.create().build();
+    }
+
+    @Primary
+    @Bean
+    public DynamicRoutingDataSource dynamicDataSource(
+            @Qualifier(value = "masterDataSource") DataSource masterDataSource,
+            @Qualifier(value = "slaveDataSource") DataSource slaveDataSource) {
+        Map<Object, Object> targetDataSources = new HashMap<>(2);
+        targetDataSources.put(DataSourceEnum.master, masterDataSource);
+        targetDataSources.put(DataSourceEnum.slave, slaveDataSource);
+        DynamicRoutingDataSource dynamicRoutingDataSource = new DynamicRoutingDataSource();
+        //设置数据源
+        dynamicRoutingDataSource.setTargetDataSources(targetDataSources);
+        //设置默认选择的数据源
+        dynamicRoutingDataSource.setDefaultTargetDataSource(masterDataSource);
+        dynamicRoutingDataSource.afterPropertiesSet();
+        return dynamicRoutingDataSource;
+    }
+
+
+
+
+
 }

+ 1 - 1
src/main/resources/META-INF/spring.factories

@@ -1,2 +1,2 @@
 org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
-com.xiesx.fastboot.SpringContextAware
+com.xiesx.fastboot.core.jpa.aop.RoutingAopAspect,com.xiesx.fastboot.SpringContextAware