From a6fb38de7cb38391531be8e3c1da2fd42857755c Mon Sep 17 00:00:00 2001 From: xiang Date: Sat, 26 Jul 2025 22:13:57 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E8=87=AA=E5=AE=9A=E4=B9=89=E5=8A=A8?= =?UTF-8?q?=E6=80=81=E6=95=B0=E6=8D=AE=E6=BA=90@DynamicDataSource?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 11 ++++-- xservice-common/pom.xml | 1 + xservice-mysql-starter/pom.xml | 20 ++++++++++ .../mysql/annotation/DynamicDataSource.java | 13 +++++++ .../mysql/aspect/DynamicDataSourceAspect.java | 31 ++++++++++++++++ .../mysql/config/DynamicDataSourceConfig.java | 37 +++++++++++++++++++ .../config/DynamicDataSourceContext.java | 18 +++++++++ .../mysql/entity/DataSourceProperty.java | 16 ++++++++ .../entity/DynamicDataSourceProperties.java | 18 +++++++++ .../service/DynamicRoutingDataSource.java | 11 ++++++ .../main/resources/META-INF/spring.factories | 2 + 11 files changed, 175 insertions(+), 3 deletions(-) create mode 100644 xservice-mysql-starter/pom.xml create mode 100644 xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/annotation/DynamicDataSource.java create mode 100644 xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/aspect/DynamicDataSourceAspect.java create mode 100644 xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/config/DynamicDataSourceConfig.java create mode 100644 xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/config/DynamicDataSourceContext.java create mode 100644 xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/entity/DataSourceProperty.java create mode 100644 xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/entity/DynamicDataSourceProperties.java create mode 100644 xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/service/DynamicRoutingDataSource.java create mode 100644 xservice-mysql-starter/src/main/resources/META-INF/spring.factories diff --git a/pom.xml b/pom.xml index eed4df0..063ba90 100644 --- a/pom.xml +++ b/pom.xml @@ -12,6 +12,7 @@ xservice-common xservice-cache xservice-third-part + xservice-mysql-starter @@ -71,13 +72,17 @@ mybatis-spring-boot-starter ${mybatis-spring-boot.version} - - org.springframework.boot - spring-boot-starter-data-redis + spring-boot-starter-aop + + + + + + org.apache.rocketmq diff --git a/xservice-common/pom.xml b/xservice-common/pom.xml index 10f07ac..2562933 100644 --- a/xservice-common/pom.xml +++ b/xservice-common/pom.xml @@ -8,6 +8,7 @@ xservice-basic 1.0-SNAPSHOT + 1.0.1-SNAPSHOT xservice-common diff --git a/xservice-mysql-starter/pom.xml b/xservice-mysql-starter/pom.xml new file mode 100644 index 0000000..c1ee692 --- /dev/null +++ b/xservice-mysql-starter/pom.xml @@ -0,0 +1,20 @@ + + + 4.0.0 + + com.xiang + xservice-basic + 1.0-SNAPSHOT + + + xservice-mysql-starter + + + 17 + 17 + UTF-8 + + + \ No newline at end of file diff --git a/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/annotation/DynamicDataSource.java b/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/annotation/DynamicDataSource.java new file mode 100644 index 0000000..38bebdf --- /dev/null +++ b/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/annotation/DynamicDataSource.java @@ -0,0 +1,13 @@ +package com.xiang.xservice.mysql.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface DynamicDataSource { + // 数据源标识 + String value(); +} diff --git a/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/aspect/DynamicDataSourceAspect.java b/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/aspect/DynamicDataSourceAspect.java new file mode 100644 index 0000000..8417bb5 --- /dev/null +++ b/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/aspect/DynamicDataSourceAspect.java @@ -0,0 +1,31 @@ +package com.xiang.xservice.mysql.aspect; + +import com.xiang.xservice.mysql.annotation.DynamicDataSource; +import com.xiang.xservice.mysql.config.DynamicDataSourceContext; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.stereotype.Component; + +@Aspect +@Component +public class DynamicDataSourceAspect { + @Pointcut("@annotation(com.xiang.xservice.mysql.annotation.DynamicDataSource)") + public void dataSourcePointCut() {} + + @Around("dataSourcePointCut()") + public Object switchDataSource(ProceedingJoinPoint point) throws Throwable { + MethodSignature signature = (MethodSignature) point.getSignature(); + DynamicDataSource ds = signature.getMethod().getAnnotation(DynamicDataSource.class); + if (ds != null) { + DynamicDataSourceContext.set(ds.value()); + } + try { + return point.proceed(); + } finally { + DynamicDataSourceContext.clear(); + } + } +} diff --git a/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/config/DynamicDataSourceConfig.java b/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/config/DynamicDataSourceConfig.java new file mode 100644 index 0000000..1a99752 --- /dev/null +++ b/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/config/DynamicDataSourceConfig.java @@ -0,0 +1,37 @@ +package com.xiang.xservice.mysql.config; + +import com.google.common.collect.Maps; +import com.xiang.xservice.mysql.entity.DynamicDataSourceProperties; +import com.xiang.xservice.mysql.service.DynamicRoutingDataSource; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +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 javax.sql.DataSource; +import java.util.Map; + +@Configuration +@EnableConfigurationProperties(DynamicDataSourceProperties.class) +public class DynamicDataSourceConfig { + + @Bean + @Primary + public DataSource dataSource(DynamicDataSourceProperties props) { + Map targetDataSources = Maps.newHashMap(); + props.getDatasource().forEach((key, config) -> { + DataSourceBuilder builder = DataSourceBuilder.create() + .url(config.getUrl()) + .username(config.getUsername()) + .password(config.getPassword()) + .driverClassName(config.getDriverClassName()); + targetDataSources.put(key, builder.build()); + }); + + DynamicRoutingDataSource routing = new DynamicRoutingDataSource(); + routing.setDefaultTargetDataSource(targetDataSources.get(props.getPrimary())); + routing.setTargetDataSources(targetDataSources); + return routing; + } +} diff --git a/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/config/DynamicDataSourceContext.java b/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/config/DynamicDataSourceContext.java new file mode 100644 index 0000000..5854712 --- /dev/null +++ b/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/config/DynamicDataSourceContext.java @@ -0,0 +1,18 @@ +package com.xiang.xservice.mysql.config; + + +public class DynamicDataSourceContext { + private static final ThreadLocal CONTEXT = new ThreadLocal<>(); + + public static void set(String datasource) { + CONTEXT.set(datasource); + } + + public static String get() { + return CONTEXT.get(); + } + + public static void clear() { + CONTEXT.remove(); + } +} diff --git a/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/entity/DataSourceProperty.java b/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/entity/DataSourceProperty.java new file mode 100644 index 0000000..1eb20bd --- /dev/null +++ b/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/entity/DataSourceProperty.java @@ -0,0 +1,16 @@ +package com.xiang.xservice.mysql.entity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class DataSourceProperty { + private String url; + private String username; + private String password; + private String driverClassName = "com.mysql.cj.jdbc.Driver"; + +} diff --git a/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/entity/DynamicDataSourceProperties.java b/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/entity/DynamicDataSourceProperties.java new file mode 100644 index 0000000..1ce76c1 --- /dev/null +++ b/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/entity/DynamicDataSourceProperties.java @@ -0,0 +1,18 @@ +package com.xiang.xservice.mysql.entity; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.springframework.boot.context.properties.ConfigurationProperties; + +import java.util.HashMap; +import java.util.Map; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@ConfigurationProperties(prefix = "spring.datasource.dynamic.datasource") +public class DynamicDataSourceProperties { + private String primary; + private Map datasource = new HashMap<>(); +} \ No newline at end of file diff --git a/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/service/DynamicRoutingDataSource.java b/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/service/DynamicRoutingDataSource.java new file mode 100644 index 0000000..f058af8 --- /dev/null +++ b/xservice-mysql-starter/src/main/java/com/xiang/xservice/mysql/service/DynamicRoutingDataSource.java @@ -0,0 +1,11 @@ +package com.xiang.xservice.mysql.service; + +import com.xiang.xservice.mysql.config.DynamicDataSourceContext; +import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; + +public class DynamicRoutingDataSource extends AbstractRoutingDataSource { + @Override + protected Object determineCurrentLookupKey() { + return DynamicDataSourceContext.get(); + } +} diff --git a/xservice-mysql-starter/src/main/resources/META-INF/spring.factories b/xservice-mysql-starter/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..7c4c1c1 --- /dev/null +++ b/xservice-mysql-starter/src/main/resources/META-INF/spring.factories @@ -0,0 +1,2 @@ +org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ +com.xiang.xservice.mysql.config.DynamicDataSourceConfig \ No newline at end of file