From 3a217c9ea2f24bb260edd9a03344fb2aa374f400 Mon Sep 17 00:00:00 2001 From: dingzhongyuan Date: Mon, 21 Jun 2021 15:41:44 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=9A=E6=95=B0=E6=8D=AE=E6=BA=90=E6=9B=BF?= =?UTF-8?q?=E6=8D=A2=E6=88=90dynamic-datasource?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 9 ++ .../main/java/com/ruoyi/RuoYiApplication.java | 5 +- .../src/main/resources/application-dev.yml | 109 ++++++------- .../src/main/resources/application-prod.yml | 108 ++++++------- .../ruoyi/common/annotation/DataSource.java | 56 +++---- .../framework/aspectj/DataSourceAspect.java | 146 +++++++++--------- .../ruoyi/framework/config/DruidConfig.java | 126 --------------- .../config/DynamicDataSourceConfig.java | 67 ++++++++ .../config/properties/DruidProperties.java | 2 +- .../datasource/DynamicDataSource.java | 26 ---- .../DynamicDataSourceContextHolder.java | 45 ------ ruoyi-system/pom.xml | 6 + .../service/impl/SysConfigServiceImpl.java | 4 +- .../service/impl/SysDeptServiceImpl.java | 25 +++ .../service/impl/SysMenuServiceImpl.java | 2 +- .../service/impl/SysUserServiceImpl.java | 6 + 16 files changed, 332 insertions(+), 410 deletions(-) delete mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/DynamicDataSourceConfig.java delete mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java delete mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java diff --git a/pom.xml b/pom.xml index 4beed40ac..9988b565e 100644 --- a/pom.xml +++ b/pom.xml @@ -25,6 +25,7 @@ 1.7 0.9.1 3.4.3 + 3.3.6 5.6.5 2.2.6.RELEASE 11.0 @@ -79,6 +80,13 @@ ${jwt.version} + + + com.baomidou + dynamic-datasource-spring-boot-starter + ${datasource.version} + + com.baomidou mybatis-plus-boot-starter @@ -89,6 +97,7 @@ mybatis-plus-extension ${mybatis-plus.version} + cn.hutool hutool-all diff --git a/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java index 5b55927bf..f60978bed 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java @@ -1,16 +1,17 @@ package com.ruoyi; +import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; /** * 启动程序 - * + * * @author ruoyi */ -@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }) +@SpringBootApplication public class RuoYiApplication { public static void main(String[] args) diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml index eb54d9c64..ca000689b 100644 --- a/ruoyi-admin/src/main/resources/application-dev.yml +++ b/ruoyi-admin/src/main/resources/application-dev.yml @@ -1,70 +1,73 @@ # 数据源配置 spring: + autoconfigure: + exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure datasource: type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.cj.jdbc.Driver - druid: - # 主库数据源 - master: - url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true - username: root - password: root - # 从库数据源 - slave: - # 从数据源开关/默认关闭 - enabled: false - url: - username: - password: - # 初始连接数 - initialSize: 5 - # 最小连接池数量 - minIdle: 10 - # 最大连接池数量 - maxActive: 20 - # 配置获取连接等待超时的时间 - maxWait: 60000 - # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 - timeBetweenEvictionRunsMillis: 60000 - # 配置一个连接在池中最小生存的时间,单位是毫秒 - minEvictableIdleTimeMillis: 300000 - # 配置一个连接在池中最大生存的时间,单位是毫秒 - maxEvictableIdleTimeMillis: 900000 - # 配置检测连接是否有效 - validationQuery: SELECT 1 FROM DUAL - testWhileIdle: true - testOnBorrow: false - testOnReturn: false - webStatFilter: - enabled: true - statViewServlet: - enabled: true - # 设置白名单,不填则允许所有访问 - allow: - url-pattern: /druid/* - # 控制台管理用户名和密码 - login-username: ruoyi - login-password: 123456 - filter: - stat: + dynamic: + druid: + # 初始连接数 + initialSize: 5 + # 最小连接池数量 + minIdle: 10 + # 最大连接池数量 + maxActive: 20 + # 配置获取连接等待超时的时间 + maxWait: 60000 + # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 + timeBetweenEvictionRunsMillis: 60000 + # 配置一个连接在池中最小生存的时间,单位是毫秒 + minEvictableIdleTimeMillis: 300000 + # 配置一个连接在池中最大生存的时间,单位是毫秒 + maxEvictableIdleTimeMillis: 900000 + # 配置检测连接是否有效 + validationQuery: SELECT 1 FROM DUAL + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + filters: stat # 注意这个值和druid原生不一致,默认启动了stat + webStatFilter: enabled: true - # 慢SQL记录 - log-slow-sql: true - slow-sql-millis: 1000 - merge-sql: true - wall: - config: - multi-statement-allow: true + statViewServlet: + enabled: true + # 设置白名单,不填则允许所有访问 + allow: + url-pattern: /druid/* + # 控制台管理用户名和密码 + login-username: ruoyi + login-password: 123456 + filter: + stat: + enabled: true + # 慢SQL记录 + log-slow-sql: true + slow-sql-millis: 1000 + merge-sql: true + wall: + config: + multi-statement-allow: true + datasource: + # 主库数据源 + master: + url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true + username: root + password: root123456 + # 从库数据源 + slave: + url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true + username: root + password: root123456 # redis 配置 redis: # 地址 - host: localhost + host: 127.0.0.1 # 端口,默认为6379 port: 6379 # 数据库索引 database: 0 # 密码 - password: + password: root123456 # 连接超时时间 timeout: 10s # 是否开启ssl diff --git a/ruoyi-admin/src/main/resources/application-prod.yml b/ruoyi-admin/src/main/resources/application-prod.yml index 2ebdcbdc6..88b6a62d8 100644 --- a/ruoyi-admin/src/main/resources/application-prod.yml +++ b/ruoyi-admin/src/main/resources/application-prod.yml @@ -3,68 +3,70 @@ spring: datasource: type: com.alibaba.druid.pool.DruidDataSource driverClassName: com.mysql.cj.jdbc.Driver - druid: - # 主库数据源 - master: - url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true - username: root - password: root - # 从库数据源 - slave: - # 从数据源开关/默认关闭 - enabled: false - url: - username: - password: - # 初始连接数 - initialSize: 5 - # 最小连接池数量 - minIdle: 10 - # 最大连接池数量 - maxActive: 20 - # 配置获取连接等待超时的时间 - maxWait: 60000 - # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 - timeBetweenEvictionRunsMillis: 60000 - # 配置一个连接在池中最小生存的时间,单位是毫秒 - minEvictableIdleTimeMillis: 300000 - # 配置一个连接在池中最大生存的时间,单位是毫秒 - maxEvictableIdleTimeMillis: 900000 - # 配置检测连接是否有效 - validationQuery: SELECT 1 FROM DUAL - testWhileIdle: true - testOnBorrow: false - testOnReturn: false - webStatFilter: - enabled: true - statViewServlet: - enabled: true - # 设置白名单,不填则允许所有访问 - allow: - url-pattern: /druid/* - # 控制台管理用户名和密码 - login-username: ruoyi - login-password: 123456 - filter: - stat: + dynamic: + druid: + # 主库数据源 + master: + url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true + username: root + password: root123456 + # 从库数据源 + slave: + # 从数据源开关/默认关闭 + enabled: false + url: + username: + password: + # 初始连接数 + initialSize: 5 + # 最小连接池数量 + minIdle: 10 + # 最大连接池数量 + maxActive: 20 + # 配置获取连接等待超时的时间 + maxWait: 60000 + # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 + timeBetweenEvictionRunsMillis: 60000 + # 配置一个连接在池中最小生存的时间,单位是毫秒 + minEvictableIdleTimeMillis: 300000 + # 配置一个连接在池中最大生存的时间,单位是毫秒 + maxEvictableIdleTimeMillis: 900000 + # 配置检测连接是否有效 + validationQuery: SELECT 1 FROM DUAL + testWhileIdle: true + testOnBorrow: false + testOnReturn: false + webStatFilter: enabled: true - # 慢SQL记录 - log-slow-sql: true - slow-sql-millis: 1000 - merge-sql: true - wall: - config: - multi-statement-allow: true + statViewServlet: + enabled: true + # 设置白名单,不填则允许所有访问 + allow: + url-pattern: /druid/* + # 控制台管理用户名和密码 + login-username: ruoyi + login-password: 123456 + filter: + stat: + enabled: true + # 慢SQL记录 + log-slow-sql: true + slow-sql-millis: 1000 + merge-sql: true + wall: + config: + multi-statement-allow: true + # redis 配置 redis: # 地址 - host: 192.168.0.222 + host: 127.0.0.1 # 端口,默认为6379 port: 6379 # 数据库索引 database: 0 # 密码 - password: + password: root123456 # 连接超时时间 timeout: 10s # 是否开启ssl diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java index 79cd191f8..2737a85f5 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java @@ -1,28 +1,28 @@ -package com.ruoyi.common.annotation; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -import com.ruoyi.common.enums.DataSourceType; - -/** - * 自定义多数据源切换注解 - * - * 优先级:先方法,后类,如果方法覆盖了类上的数据源类型,以方法的为准,否则以类上的为准 - * - * @author ruoyi - */ -@Target({ ElementType.METHOD, ElementType.TYPE }) -@Retention(RetentionPolicy.RUNTIME) -@Documented -@Inherited -public @interface DataSource -{ - /** - * 切换数据源名称 - */ - public DataSourceType value() default DataSourceType.MASTER; -} +//package com.ruoyi.common.annotation; +// +//import java.lang.annotation.Documented; +//import java.lang.annotation.ElementType; +//import java.lang.annotation.Inherited; +//import java.lang.annotation.Retention; +//import java.lang.annotation.RetentionPolicy; +//import java.lang.annotation.Target; +//import com.ruoyi.common.enums.DataSourceType; +// +///** +// * 自定义多数据源切换注解 +// * +// * 优先级:先方法,后类,如果方法覆盖了类上的数据源类型,以方法的为准,否则以类上的为准 +// * +// * @author ruoyi +// */ +//@Target({ ElementType.METHOD, ElementType.TYPE }) +//@Retention(RetentionPolicy.RUNTIME) +//@Documented +//@Inherited +//public @interface DataSource +//{ +// /** +// * 切换数据源名称 +// */ +// public DataSourceType value() default DataSourceType.MASTER; +//} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java index f92a9647a..1bb4274c8 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java @@ -1,73 +1,73 @@ -package com.ruoyi.framework.aspectj; - -import cn.hutool.core.lang.Validator; -import com.ruoyi.common.annotation.DataSource; -import com.ruoyi.framework.datasource.DynamicDataSourceContextHolder; -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.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.core.annotation.Order; -import org.springframework.stereotype.Component; - -import java.util.Objects; - -/** - * 多数据源处理 - * - * @author ruoyi - */ -@Aspect -@Order(1) -@Component -public class DataSourceAspect -{ - protected Logger logger = LoggerFactory.getLogger(getClass()); - - @Pointcut("@annotation(com.ruoyi.common.annotation.DataSource)" - + "|| @within(com.ruoyi.common.annotation.DataSource)") - public void dsPointCut() - { - - } - - @Around("dsPointCut()") - public Object around(ProceedingJoinPoint point) throws Throwable - { - DataSource dataSource = getDataSource(point); - - if (Validator.isNotNull(dataSource)) - { - DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name()); - } - - try - { - return point.proceed(); - } - finally - { - // 销毁数据源 在执行方法之后 - DynamicDataSourceContextHolder.clearDataSourceType(); - } - } - - /** - * 获取需要切换的数据源 - */ - public DataSource getDataSource(ProceedingJoinPoint point) - { - MethodSignature signature = (MethodSignature) point.getSignature(); - DataSource dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class); - if (Objects.nonNull(dataSource)) - { - return dataSource; - } - - return AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class); - } -} +//package com.ruoyi.framework.aspectj; +// +//import cn.hutool.core.lang.Validator; +//import com.ruoyi.common.annotation.DataSource; +//import com.ruoyi.framework.datasource.DynamicDataSourceContextHolder; +//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.slf4j.Logger; +//import org.slf4j.LoggerFactory; +//import org.springframework.core.annotation.AnnotationUtils; +//import org.springframework.core.annotation.Order; +//import org.springframework.stereotype.Component; +// +//import java.util.Objects; +// +///** +// * 多数据源处理 +// * +// * @author ruoyi +// */ +//@Aspect +//@Order(1) +//@Component +//public class DataSourceAspect +//{ +// protected Logger logger = LoggerFactory.getLogger(getClass()); +// +// @Pointcut("@annotation(com.ruoyi.common.annotation.DataSource)" +// + "|| @within(com.ruoyi.common.annotation.DataSource)") +// public void dsPointCut() +// { +// +// } +// +// @Around("dsPointCut()") +// public Object around(ProceedingJoinPoint point) throws Throwable +// { +// DataSource dataSource = getDataSource(point); +// +// if (Validator.isNotNull(dataSource)) +// { +// DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name()); +// } +// +// try +// { +// return point.proceed(); +// } +// finally +// { +// // 销毁数据源 在执行方法之后 +// DynamicDataSourceContextHolder.clearDataSourceType(); +// } +// } +// +// /** +// * 获取需要切换的数据源 +// */ +// public DataSource getDataSource(ProceedingJoinPoint point) +// { +// MethodSignature signature = (MethodSignature) point.getSignature(); +// DataSource dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class); +// if (Objects.nonNull(dataSource)) +// { +// return dataSource; +// } +// +// return AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class); +// } +//} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java deleted file mode 100644 index 3fab843f9..000000000 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.ruoyi.framework.config; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import javax.servlet.Filter; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.sql.DataSource; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.boot.web.servlet.FilterRegistrationBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; -import com.alibaba.druid.pool.DruidDataSource; -import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder; -import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties; -import com.alibaba.druid.util.Utils; -import com.ruoyi.common.enums.DataSourceType; -import com.ruoyi.common.utils.spring.SpringUtils; -import com.ruoyi.framework.config.properties.DruidProperties; -import com.ruoyi.framework.datasource.DynamicDataSource; - -/** - * druid 配置多数据源 - * - * @author ruoyi - */ -@Configuration -public class DruidConfig -{ - @Bean - @ConfigurationProperties("spring.datasource.druid.master") - public DataSource masterDataSource(DruidProperties druidProperties) - { - DruidDataSource dataSource = DruidDataSourceBuilder.create().build(); - return druidProperties.dataSource(dataSource); - } - - @Bean - @ConfigurationProperties("spring.datasource.druid.slave") - @ConditionalOnProperty(prefix = "spring.datasource.druid.slave", name = "enabled", havingValue = "true") - public DataSource slaveDataSource(DruidProperties druidProperties) - { - DruidDataSource dataSource = DruidDataSourceBuilder.create().build(); - return druidProperties.dataSource(dataSource); - } - - @Bean(name = "dynamicDataSource") - @Primary - public DynamicDataSource dataSource(DataSource masterDataSource) - { - Map targetDataSources = new HashMap<>(); - targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource); - setDataSource(targetDataSources, DataSourceType.SLAVE.name(), "slaveDataSource"); - return new DynamicDataSource(masterDataSource, targetDataSources); - } - - /** - * 设置数据源 - * - * @param targetDataSources 备选数据源集合 - * @param sourceName 数据源名称 - * @param beanName bean名称 - */ - public void setDataSource(Map targetDataSources, String sourceName, String beanName) - { - try - { - DataSource dataSource = SpringUtils.getBean(beanName); - targetDataSources.put(sourceName, dataSource); - } - catch (Exception e) - { - } - } - - /** - * 去除监控页面底部的广告 - */ - @SuppressWarnings({ "rawtypes", "unchecked" }) - @Bean - @ConditionalOnProperty(name = "spring.datasource.druid.statViewServlet.enabled", havingValue = "true") - public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties) - { - // 获取web监控页面的参数 - DruidStatProperties.StatViewServlet config = properties.getStatViewServlet(); - // 提取common.js的配置路径 - String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*"; - String commonJsPattern = pattern.replaceAll("\\*", "js/common.js"); - final String filePath = "support/http/resources/js/common.js"; - // 创建filter进行过滤 - Filter filter = new Filter() - { - @Override - public void init(javax.servlet.FilterConfig filterConfig) throws ServletException - { - } - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) - throws IOException, ServletException - { - chain.doFilter(request, response); - // 重置缓冲区,响应头不会被重置 -// response.resetBuffer(); - // 获取common.js - String text = Utils.readFromResource(filePath); - // 正则替换banner, 除去底部的广告信息 - text = text.replaceAll("
", ""); - text = text.replaceAll("powered.*?shrek.wang", ""); - response.getWriter().write(text); - } - @Override - public void destroy() - { - } - }; - FilterRegistrationBean registrationBean = new FilterRegistrationBean(); - registrationBean.setFilter(filter); - registrationBean.addUrlPatterns(commonJsPattern); - return registrationBean; - } -} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DynamicDataSourceConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DynamicDataSourceConfig.java new file mode 100644 index 000000000..6f7071c59 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DynamicDataSourceConfig.java @@ -0,0 +1,67 @@ +package com.ruoyi.framework.config; + +import com.baomidou.dynamic.datasource.plugin.MasterSlaveAutoRoutingPlugin; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +/** + * 在纯的读写分离环境,写操作全部是master,读操作全部是slave + * @author ding + */ +@Configuration +public class DynamicDataSourceConfig { + + @Bean + public MasterSlaveAutoRoutingPlugin masterSlaveAutoRoutingPlugin(){ + return new MasterSlaveAutoRoutingPlugin(); + } + + // /** +// * 去除监控页面底部的广告 +// */ +// @SuppressWarnings({ "rawtypes", "unchecked" }) +// @Bean +// @ConditionalOnProperty(name = "spring.datasource.dynamic.druid.statViewServlet.enabled", havingValue = "true") +// public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties) +// { +// // 获取web监控页面的参数 +// DruidStatProperties.StatViewServlet config = properties.getStatViewServlet(); +// // 提取common.js的配置路径 +// String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*"; +// String commonJsPattern = pattern.replaceAll("\\*", "js/common.js"); +// final String filePath = "support/http/resources/js/common.js"; +// // 创建filter进行过滤 +// Filter filter = new Filter() +// { +// @Override +// public void init(javax.servlet.FilterConfig filterConfig) throws ServletException +// { +// } +// @Override +// public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) +// throws IOException, ServletException +// { +// chain.doFilter(request, response); +// // 重置缓冲区,响应头不会被重置 +//// response.resetBuffer(); +// // 获取common.js +// String text = Utils.readFromResource(filePath); +// // 正则替换banner, 除去底部的广告信息 +// text = text.replaceAll("
", ""); +// text = text.replaceAll("powered.*?shrek.wang", ""); +// response.getWriter().write(text); +// } +// @Override +// public void destroy() +// { +// } +// }; +// FilterRegistrationBean registrationBean = new FilterRegistrationBean(); +// registrationBean.setFilter(filter); +// registrationBean.addUrlPatterns(commonJsPattern); +// return registrationBean; +// } + +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java index 03ddc2c5a..f5dd83da0 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java @@ -12,7 +12,7 @@ import org.springframework.context.annotation.Configuration; */ @Data @Configuration -@ConfigurationProperties(prefix = "spring.datasource.druid") +@ConfigurationProperties(prefix = "spring.datasource.dynamic.druid") public class DruidProperties { /** 初始连接数 */ diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java deleted file mode 100644 index e70b8cfa7..000000000 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.ruoyi.framework.datasource; - -import java.util.Map; -import javax.sql.DataSource; -import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; - -/** - * 动态数据源 - * - * @author ruoyi - */ -public class DynamicDataSource extends AbstractRoutingDataSource -{ - public DynamicDataSource(DataSource defaultTargetDataSource, Map targetDataSources) - { - super.setDefaultTargetDataSource(defaultTargetDataSource); - super.setTargetDataSources(targetDataSources); - super.afterPropertiesSet(); - } - - @Override - protected Object determineCurrentLookupKey() - { - return DynamicDataSourceContextHolder.getDataSourceType(); - } -} \ No newline at end of file diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java deleted file mode 100644 index 3572db917..000000000 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.ruoyi.framework.datasource; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * 数据源切换处理 - * - * @author ruoyi - */ -public class DynamicDataSourceContextHolder -{ - public static final Logger log = LoggerFactory.getLogger(DynamicDataSourceContextHolder.class); - - /** - * 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本, - * 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。 - */ - private static final ThreadLocal CONTEXT_HOLDER = new ThreadLocal<>(); - - /** - * 设置数据源的变量 - */ - public static void setDataSourceType(String dsType) - { - log.info("切换到{}数据源", dsType); - CONTEXT_HOLDER.set(dsType); - } - - /** - * 获得数据源的变量 - */ - public static String getDataSourceType() - { - return CONTEXT_HOLDER.get(); - } - - /** - * 清空数据源变量 - */ - public static void clearDataSourceType() - { - CONTEXT_HOLDER.remove(); - } -} diff --git a/ruoyi-system/pom.xml b/ruoyi-system/pom.xml index 2f5579f41..62d0b75b1 100644 --- a/ruoyi-system/pom.xml +++ b/ruoyi-system/pom.xml @@ -23,6 +23,12 @@ ruoyi-common
+ + + com.baomidou + dynamic-datasource-spring-boot-starter + + diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java index d0b37c5e3..55ea8b6a3 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java @@ -5,7 +5,7 @@ import cn.hutool.core.lang.Validator; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; -import com.ruoyi.common.annotation.DataSource; +//import com.ruoyi.common.annotation.DataSource; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.page.TableDataInfo; @@ -67,7 +67,7 @@ public class SysConfigServiceImpl extends ServiceImpl implements ISysDeptService { @Autowired @@ -39,6 +45,10 @@ public class SysDeptServiceImpl extends ServiceImpl impl @Autowired private SysUserMapper userMapper; + //测试当前数据源 + @Autowired + private DataSource dataSource; + /** * 查询部门管理数据 * @@ -48,6 +58,10 @@ public class SysDeptServiceImpl extends ServiceImpl impl @Override @DataScope(deptAlias = "d") public List selectDeptList(SysDept dept) { + DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource; + DataSource datasource=ds.determineDataSource(); + String dataName = DynamicDataSourceContextHolder.peek(); + log.info("--查询部门管理数据---当前数据源名称:"+dataName); return baseMapper.selectDeptList(dept); } @@ -109,7 +123,12 @@ public class SysDeptServiceImpl extends ServiceImpl impl * @return 部门信息 */ @Override + @DS("slave") public SysDept selectDeptById(Long deptId) { + DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource; + DataSource datasource=ds.determineDataSource(); + String dataName = DynamicDataSourceContextHolder.peek(); + log.info("mp内置方法--根据部门ID查询信息---当前数据源名称:"+dataName); return getById(deptId); } @@ -179,6 +198,7 @@ public class SysDeptServiceImpl extends ServiceImpl impl * @return 结果 */ @Override + @DS("slave") public int insertDept(SysDept dept) { SysDept info = getById(dept.getParentId()); // 如果父节点不为正常状态,则不允许新增子节点 @@ -186,6 +206,8 @@ public class SysDeptServiceImpl extends ServiceImpl impl throw new CustomException("部门停用,不允许新增"); } dept.setAncestors(info.getAncestors() + "," + dept.getParentId()); + String dataName = DynamicDataSourceContextHolder.peek(); + log.info("mp内置方法--新增保存部门信息---当前数据源名称:"+dataName); return baseMapper.insert(dept); } @@ -196,6 +218,7 @@ public class SysDeptServiceImpl extends ServiceImpl impl * @return 结果 */ @Override + @DS("slave") public int updateDept(SysDept dept) { SysDept newParentDept = getById(dept.getParentId()); SysDept oldDept = getById(dept.getDeptId()); @@ -205,6 +228,8 @@ public class SysDeptServiceImpl extends ServiceImpl impl dept.setAncestors(newAncestors); updateDeptChildren(dept.getDeptId(), newAncestors, oldAncestors); } + String dataName = DynamicDataSourceContextHolder.peek(); + log.info("mp内置方法--修改保存部门信息---当前数据源名称:"+dataName); int result = baseMapper.updateById(dept); if (UserConstants.DEPT_NORMAL.equals(dept.getStatus())) { // 如果该部门是启用状态,则启用该部门的所有上级部门 diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java index 6f7cc414e..b04d3b267 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java @@ -25,7 +25,7 @@ import java.util.stream.Collectors; /** * 菜单 业务层处理 - * + * * @author ruoyi */ @Service diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java index dd12f10b2..8017bfcdd 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java @@ -1,6 +1,8 @@ package com.ruoyi.system.service.impl; import cn.hutool.core.lang.Validator; +import com.baomidou.dynamic.datasource.annotation.DS; +import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -34,6 +36,7 @@ import java.util.List; */ @Slf4j @Service +@DS("slave") public class SysUserServiceImpl extends ServiceImpl implements ISysUserService { @Autowired @@ -53,7 +56,10 @@ public class SysUserServiceImpl extends ServiceImpl impl @Override @DataScope(deptAlias = "d", userAlias = "u", isUser = true) + @DS("master") public TableDataInfo selectPageUserList(SysUser user) { + String dataName = DynamicDataSourceContextHolder.peek(); + log.info("自定义方法--获取用户列表---当前数据源名称:"+dataName); return PageUtils.buildDataInfo(baseMapper.selectPageUserList(PageUtils.buildPage(), user)); }