From ce4fb28c01ebe1face709f7dbb276f8a7116a5ae Mon Sep 17 00:00:00 2001
From: "Yangkai.Shen" <237497819@qq.com>
Date: Wed, 4 Sep 2019 18:25:18 +0800
Subject: [PATCH] =?UTF-8?q?:sparkles:=20=E5=8A=A8=E6=80=81=E6=B7=BB?=
=?UTF-8?q?=E5=8A=A0=E6=95=B0=E6=8D=AE=E6=BA=90=EF=BC=8C=E5=8A=A8=E6=80=81?=
=?UTF-8?q?=E5=88=87=E6=8D=A2=E6=95=B0=E6=8D=AE=E6=BA=90?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
pom.xml | 1 +
.../.gitignore | 31 +++++++
.../db/init.sql | 16 ++++
.../db/user.sql | 25 +++++
spring-boot-demo-dynamic-datasource/pom.xml | 71 +++++++++++++++
...gBootDemoDynamicDatasourceApplication.java | 39 ++++++++
.../annotation/DefaultDatasource.java | 17 ++++
.../aspect/DatasourceSelectorAspect.java | 70 ++++++++++++++
.../config/DatasourceConfiguration.java | 29 ++++++
.../dynamic/datasource/config/MyMapper.java | 17 ++++
.../config/MybatisConfiguration.java | 37 ++++++++
.../DatasourceConfigController.java | 44 +++++++++
.../datasource/controller/UserController.java | 33 +++++++
.../datasource/DatasourceConfigCache.java | 58 ++++++++++++
.../DatasourceConfigContextHolder.java | 40 ++++++++
.../datasource/DatasourceHolder.java | 91 +++++++++++++++++++
.../datasource/DatasourceManager.java | 57 ++++++++++++
.../datasource/DatasourceScheduler.java | 44 +++++++++
.../datasource/DynamicDataSource.java | 61 +++++++++++++
.../mapper/DatasourceConfigMapper.java | 17 ++++
.../dynamic/datasource/mapper/UserMapper.java | 15 +++
.../datasource/model/DatasourceConfig.java | 69 ++++++++++++++
.../dynamic/datasource/model/User.java | 35 +++++++
.../dynamic/datasource/utils/SpringUtil.java | 86 ++++++++++++++++++
.../src/main/resources/application.yml | 10 ++
...DemoDynamicDatasourceApplicationTests.java | 16 ++++
26 files changed, 1029 insertions(+)
create mode 100644 spring-boot-demo-dynamic-datasource/.gitignore
create mode 100644 spring-boot-demo-dynamic-datasource/db/init.sql
create mode 100644 spring-boot-demo-dynamic-datasource/db/user.sql
create mode 100644 spring-boot-demo-dynamic-datasource/pom.xml
create mode 100644 spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/SpringBootDemoDynamicDatasourceApplication.java
create mode 100644 spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/annotation/DefaultDatasource.java
create mode 100644 spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/aspect/DatasourceSelectorAspect.java
create mode 100644 spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/config/DatasourceConfiguration.java
create mode 100644 spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/config/MyMapper.java
create mode 100644 spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/config/MybatisConfiguration.java
create mode 100644 spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/controller/DatasourceConfigController.java
create mode 100644 spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/controller/UserController.java
create mode 100644 spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/datasource/DatasourceConfigCache.java
create mode 100644 spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/datasource/DatasourceConfigContextHolder.java
create mode 100644 spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/datasource/DatasourceHolder.java
create mode 100644 spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/datasource/DatasourceManager.java
create mode 100644 spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/datasource/DatasourceScheduler.java
create mode 100644 spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/datasource/DynamicDataSource.java
create mode 100644 spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/mapper/DatasourceConfigMapper.java
create mode 100644 spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/mapper/UserMapper.java
create mode 100644 spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/model/DatasourceConfig.java
create mode 100644 spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/model/User.java
create mode 100644 spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/utils/SpringUtil.java
create mode 100644 spring-boot-demo-dynamic-datasource/src/main/resources/application.yml
create mode 100644 spring-boot-demo-dynamic-datasource/src/test/java/com/xkcoding/dynamic/datasource/SpringBootDemoDynamicDatasourceApplicationTests.java
diff --git a/pom.xml b/pom.xml
index 1ee5d37..d20d3fc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -63,6 +63,7 @@
+ * 启动器 + *
+ * + * @author yangkai.shen + * @date Created in 2019/9/4 17:57 + */ +@SpringBootApplication +@RequiredArgsConstructor(onConstructor_ = @Autowired) +public class SpringBootDemoDynamicDatasourceApplication implements CommandLineRunner { + private final DatasourceConfigMapper configMapper; + + public static void main(String[] args) { + SpringApplication.run(SpringBootDemoDynamicDatasourceApplication.class, args); + } + + @Override + public void run(String... args) { + DatasourceConfigContextHolder.setDefaultDatasource(); + List+ * 默认数据源 + *
+ * + * @author yangkai.shen + * @date Created in 2019/9/4 17:37 + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface DefaultDatasource { +} diff --git a/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/aspect/DatasourceSelectorAspect.java b/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/aspect/DatasourceSelectorAspect.java new file mode 100644 index 0000000..fbc4330 --- /dev/null +++ b/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/aspect/DatasourceSelectorAspect.java @@ -0,0 +1,70 @@ +package com.xkcoding.dynamic.datasource.aspect; + +import com.xkcoding.dynamic.datasource.annotation.DefaultDatasource; +import com.xkcoding.dynamic.datasource.datasource.DatasourceConfigContextHolder; +import lombok.RequiredArgsConstructor; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.Signature; +import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.http.HttpServletRequest; +import java.lang.reflect.Method; + +/** + *+ * 数据源选择器切面 + *
+ * + * @author yangkai.shen + * @date Created in 2019/9/4 16:52 + */ +@Aspect +@Component +@RequiredArgsConstructor(onConstructor_ = @Autowired) +public class DatasourceSelectorAspect { + @Pointcut("execution(public * com.xkcoding.dynamic.datasource.controller.*.*(..))") + public void datasourcePointcut() { + } + + /** + * 前置通知 用于拦截操作 + */ + @Before("datasourcePointcut()") + public void doBefore(JoinPoint joinPoint) { + Signature signature = joinPoint.getSignature(); + MethodSignature methodSignature = (MethodSignature) signature; + Method method = methodSignature.getMethod(); + + DefaultDatasource annotation = method.getAnnotation(DefaultDatasource.class); + if (null != annotation) { + DatasourceConfigContextHolder.setDefaultDatasource(); + } else { + RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); + ServletRequestAttributes attributes = (ServletRequestAttributes) requestAttributes; + HttpServletRequest request = attributes.getRequest(); + String configIdInHeader = request.getHeader("Datasource-Config-Id"); + if (StringUtils.hasText(configIdInHeader)) { + long configId = Long.parseLong(configIdInHeader); + DatasourceConfigContextHolder.setCurrentDatasourceConfig(configId); + } else { + DatasourceConfigContextHolder.setDefaultDatasource(); + } + } + } + + @AfterReturning("datasourcePointcut()") + public void doAfter() { + DatasourceConfigContextHolder.setDefaultDatasource(); + } + +} diff --git a/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/config/DatasourceConfiguration.java b/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/config/DatasourceConfiguration.java new file mode 100644 index 0000000..150ac64 --- /dev/null +++ b/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/config/DatasourceConfiguration.java @@ -0,0 +1,29 @@ +package com.xkcoding.dynamic.datasource.config; + +import com.xkcoding.dynamic.datasource.datasource.DynamicDataSource; +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 javax.sql.DataSource; + +/** + *+ * 数据源配置 + *
+ * + * @author yangkai.shen + * @date Created in 2019/9/4 10:27 + */ +@Configuration +public class DatasourceConfiguration { + + @Bean + @ConfigurationProperties(prefix = "spring.datasource") + public DataSource dataSource() { + DataSourceBuilder> dataSourceBuilder = DataSourceBuilder.create(); + dataSourceBuilder.type(DynamicDataSource.class); + return dataSourceBuilder.build(); + } +} diff --git a/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/config/MyMapper.java b/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/config/MyMapper.java new file mode 100644 index 0000000..2410581 --- /dev/null +++ b/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/config/MyMapper.java @@ -0,0 +1,17 @@ +package com.xkcoding.dynamic.datasource.config; + +import tk.mybatis.mapper.annotation.RegisterMapper; +import tk.mybatis.mapper.common.Mapper; +import tk.mybatis.mapper.common.MySqlMapper; + +/** + *+ * 通用 mapper 自定义 mapper 文件 + *
+ * + * @author yangkai.shen + * @date Created in 2019/9/4 16:23 + */ +@RegisterMapper +public interface MyMapper+ * mybatis配置 + *
+ * + * @author yangkai.shen + * @date Created in 2019/9/4 16:20 + */ +@Configuration +@MapperScan(basePackages = "com.xkcoding.dynamicdatasource.mapper", sqlSessionFactoryRef = "sqlSessionFactory") +public class MybatisConfiguration { + /** + * 创建会话工厂。 + * + * @param dataSource 数据源 + * @return 会话工厂 + */ + @Bean(name = "sqlSessionFactory") + @SneakyThrows + public SqlSessionFactory getSqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) { + SqlSessionFactoryBean bean = new SqlSessionFactoryBean(); + bean.setDataSource(dataSource); + return bean.getObject(); + } +} diff --git a/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/controller/DatasourceConfigController.java b/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/controller/DatasourceConfigController.java new file mode 100644 index 0000000..83bae72 --- /dev/null +++ b/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/controller/DatasourceConfigController.java @@ -0,0 +1,44 @@ +package com.xkcoding.dynamic.datasource.controller; + +import com.xkcoding.dynamic.datasource.annotation.DefaultDatasource; +import com.xkcoding.dynamic.datasource.datasource.DatasourceConfigCache; +import com.xkcoding.dynamic.datasource.mapper.DatasourceConfigMapper; +import com.xkcoding.dynamic.datasource.model.DatasourceConfig; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + *+ * 数据源配置 Controller + *
+ * + * @author yangkai.shen + * @date Created in 2019/9/4 17:31 + */ +@RestController +@RequiredArgsConstructor(onConstructor_ = @Autowired) +public class DatasourceConfigController { + private final DatasourceConfigMapper configMapper; + + /** + * 保存 + */ + @PostMapping("/config") + @DefaultDatasource + public DatasourceConfig insertConfig(@RequestBody DatasourceConfig config) { + configMapper.insertUseGeneratedKeys(config); + DatasourceConfigCache.INSTANCE.addConfig(config.getId(), config); + return config; + } + + /** + * 保存 + */ + @DeleteMapping("/config/{id}") + @DefaultDatasource + public void removeConfig(@PathVariable Long id) { + configMapper.deleteByPrimaryKey(id); + DatasourceConfigCache.INSTANCE.removeConfig(id); + } +} diff --git a/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/controller/UserController.java b/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/controller/UserController.java new file mode 100644 index 0000000..67ce6a9 --- /dev/null +++ b/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/controller/UserController.java @@ -0,0 +1,33 @@ +package com.xkcoding.dynamic.datasource.controller; + +import com.xkcoding.dynamic.datasource.mapper.UserMapper; +import com.xkcoding.dynamic.datasource.model.User; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + *+ * 用户 Controller + *
+ * + * @author yangkai.shen + * @date Created in 2019/9/4 16:40 + */ +@RestController +@RequiredArgsConstructor(onConstructor_ = @Autowired) +public class UserController { + private final UserMapper userMapper; + + /** + * 获取用户列表 + */ + @GetMapping("/user") + public List+ * 数据源配置缓存 + *
+ * + * @author yangkai.shen + * @date Created in 2019/9/4 17:13 + */ +public enum DatasourceConfigCache { + /** + * 当前实例 + */ + INSTANCE; + + /** + * 管理动态数据源列表。 + */ + private static final Map+ * 数据源标识管理 + *
+ * + * @author yangkai.shen + * @date Created in 2019/9/4 14:16 + */ +public class DatasourceConfigContextHolder { + private static final ThreadLocal+ * 数据源管理 + *
+ * + * @author yangkai.shen + * @date Created in 2019/9/4 14:23 + */ +public enum DatasourceHolder { + /** + * 当前实例 + */ + INSTANCE; + + /** + * 启动执行,定时5分钟清理一次 + */ + DatasourceHolder() { + DatasourceScheduler.INSTANCE.schedule(this::clearExpiredDatasource, 5 * 60 * 1000); + } + + /** + * 默认数据源的id + */ + public static final Long DEFAULT_ID = -1L; + + /** + * 管理动态数据源列表。 + */ + private static final Map+ * 数据源管理类 + *
+ * + * @author yangkai.shen + * @date Created in 2019/9/4 14:27 + */ +public class DatasourceManager { + /** + * 默认释放时间 + */ + private static final Long DEFAULT_RELEASE = 10L; + + /** + * 数据源 + */ + @Getter + private HikariDataSource dataSource; + + /** + * 上一次使用时间 + */ + private LocalDateTime lastUseTime; + + public DatasourceManager(HikariDataSource dataSource) { + this.dataSource = dataSource; + this.lastUseTime = LocalDateTime.now(); + } + + /** + * 是否已过期,如果过期则关闭数据源 + * + * @return 是否过期,{@code true} 过期,{@code false} 未过期 + */ + public boolean isExpired() { + if (LocalDateTime.now().isBefore(this.lastUseTime.plusMinutes(DEFAULT_RELEASE))) { + return false; + } + this.dataSource.close(); + return true; + } + + /** + * 刷新上次使用时间 + */ + public void refreshTime() { + this.lastUseTime = LocalDateTime.now(); + } +} diff --git a/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/datasource/DatasourceScheduler.java b/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/datasource/DatasourceScheduler.java new file mode 100644 index 0000000..f8a4939 --- /dev/null +++ b/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/datasource/DatasourceScheduler.java @@ -0,0 +1,44 @@ +package com.xkcoding.dynamic.datasource.datasource; + +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +/** + *+ * 数据源缓存释放调度器 + *
+ * + * @author yangkai.shen + * @date Created in 2019/9/4 14:42 + */ +public enum DatasourceScheduler { + /** + * 当前实例 + */ + INSTANCE; + + private AtomicInteger cacheTaskNumber = new AtomicInteger(1); + private ScheduledExecutorService scheduler; + + DatasourceScheduler() { + create(); + } + + private void create() { + this.shutdown(); + this.scheduler = new ScheduledThreadPoolExecutor(10, r -> new Thread(r, String.format("Datasource-Release-Task-%s", cacheTaskNumber.getAndIncrement()))); + } + + private void shutdown() { + if (null != this.scheduler) { + this.scheduler.shutdown(); + } + } + + public void schedule(Runnable task,long delay){ + this.scheduler.scheduleAtFixedRate(task, delay, delay, TimeUnit.MILLISECONDS); + } + +} diff --git a/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/datasource/DynamicDataSource.java b/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/datasource/DynamicDataSource.java new file mode 100644 index 0000000..4b1b2ce --- /dev/null +++ b/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/datasource/DynamicDataSource.java @@ -0,0 +1,61 @@ +package com.xkcoding.dynamic.datasource.datasource; + +import com.xkcoding.dynamic.datasource.model.DatasourceConfig; +import com.xkcoding.dynamic.datasource.utils.SpringUtil; +import com.zaxxer.hikari.HikariDataSource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; + +import java.sql.Connection; +import java.sql.SQLException; + +/** + *+ * 动态数据源 + *
+ * + * @author yangkai.shen + * @date Created in 2019/9/4 10:41 + */ +@Slf4j +public class DynamicDataSource extends HikariDataSource { + @Override + public Connection getConnection() throws SQLException { + // 获取当前数据源 id + Long id = DatasourceConfigContextHolder.getCurrentDatasourceConfig(); + // 根据当前id获取数据源 + HikariDataSource datasource = DatasourceHolder.INSTANCE.getDatasource(id); + + if (null == datasource) { + datasource = initDatasource(id); + } + + return datasource.getConnection(); + } + + private HikariDataSource initDatasource(Long id) { + HikariDataSource dataSource = new HikariDataSource(); + + if (DatasourceHolder.DEFAULT_ID.equals(id)) { + DataSourceProperties properties = SpringUtil.getBean(DataSourceProperties.class); + dataSource.setJdbcUrl(properties.getUrl()); + dataSource.setUsername(properties.getUsername()); + dataSource.setPassword(properties.getPassword()); + dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); + } else { + // 获取数据库的配置 + DatasourceConfig datasourceConfig = DatasourceConfigCache.INSTANCE.getConfig(id); + + if (datasourceConfig == null) { + throw new RuntimeException("无此数据源"); + } + + dataSource.setJdbcUrl(datasourceConfig.buildJdbcUrl()); + dataSource.setUsername(datasourceConfig.getUsername()); + dataSource.setPassword(datasourceConfig.getPassword()); + dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); + } + DatasourceHolder.INSTANCE.addDatasource(id, dataSource); + return dataSource; + } +} diff --git a/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/mapper/DatasourceConfigMapper.java b/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/mapper/DatasourceConfigMapper.java new file mode 100644 index 0000000..544e31f --- /dev/null +++ b/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/mapper/DatasourceConfigMapper.java @@ -0,0 +1,17 @@ +package com.xkcoding.dynamic.datasource.mapper; + +import com.xkcoding.dynamic.datasource.config.MyMapper; +import com.xkcoding.dynamic.datasource.model.DatasourceConfig; +import org.apache.ibatis.annotations.Mapper; + +/** + *+ * 数据源配置 Mapper + *
+ * + * @author yangkai.shen + * @date Created in 2019/9/4 16:20 + */ +@Mapper +public interface DatasourceConfigMapper extends MyMapper+ * 用户 Mapper + *
+ * + * @author yangkai.shen + * @date Created in 2019/9/4 16:49 + */ +public interface UserMapper extends MyMapper+ * 数据源配置表 + *
+ * + * @author yangkai.shen + * @date Created in 2019/9/4 10:58 + */ +@Data +@Table(name = "datasource_config") +public class DatasourceConfig implements Serializable { + /** + * 主键 + */ + @Id + @Column(name = "`id`") + @GeneratedValue(generator = "JDBC") + private Long id; + + /** + * 数据库地址 + */ + @Column(name = "`host`") + private String host; + + /** + * 数据库端口 + */ + @Column(name = "`port`") + private Integer port; + + /** + * 数据库用户名 + */ + @Column(name = "`username`") + private String username; + + /** + * 数据库密码 + */ + @Column(name = "`password`") + private String password; + + /** + * 数据库名称 + */ + @Column(name = "`database`") + private String database; + + /** + * 构造JDBC URL + * + * @return JDBC URL + */ + public String buildJdbcUrl() { + return String.format("jdbc:mysql://%s:%s/%s?useUnicode=true&characterEncoding=utf-8&useSSL=false", this.host, this.port, this.database); + } + +} diff --git a/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/model/User.java b/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/model/User.java new file mode 100644 index 0000000..0c29077 --- /dev/null +++ b/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/model/User.java @@ -0,0 +1,35 @@ +package com.xkcoding.dynamic.datasource.model; + +import lombok.Data; + +import javax.persistence.Column; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; +import java.io.Serializable; + +/** + *+ * 用户 + *
+ * + * @author yangkai.shen + * @date Created in 2019/9/4 16:41 + */ +@Data +@Table(name = "test_user") +public class User implements Serializable { + /** + * 主键 + */ + @Id + @Column(name = "`id`") + @GeneratedValue(generator = "JDBC") + private Long id; + + /** + * 姓名 + */ + @Column(name = "`name`") + private String name; +} diff --git a/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/utils/SpringUtil.java b/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/utils/SpringUtil.java new file mode 100644 index 0000000..a1fb444 --- /dev/null +++ b/spring-boot-demo-dynamic-datasource/src/main/java/com/xkcoding/dynamic/datasource/utils/SpringUtil.java @@ -0,0 +1,86 @@ +package com.xkcoding.dynamic.datasource.utils; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; + +/** + *+ * Spring 工具类 + *
+ * + * @author yangkai.shen + * @date Created in 2019/9/4 16:16 + */ +@Slf4j +@Service +@Lazy(false) +public class SpringUtil implements ApplicationContextAware, DisposableBean { + + private static ApplicationContext applicationContext = null; + + /** + * 取得存储在静态变量中的ApplicationContext. + */ + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + /** + * 实现ApplicationContextAware接口, 注入Context到静态变量中. + */ + @Override + public void setApplicationContext(ApplicationContext applicationContext) { + SpringUtil.applicationContext = applicationContext; + } + + /** + * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. + */ + @SuppressWarnings("unchecked") + public static