Commit 61799385c9d55dabe0c5d1caf52f5bbb9cba3efd
Committed by
Gitee
!28 完成多数据源配置
Merge pull request !28 from timfruit/feature/multi-datasource
Showing
22 changed files
with
235 additions
and
569 deletions
README.md
| @@ -35,12 +35,12 @@ | @@ -35,12 +35,12 @@ | ||
| 35 | | | 部门管理 | 配置系统组织机构(公司、部门、小组),树结构展现支持数据权限 | | 35 | | | 部门管理 | 配置系统组织机构(公司、部门、小组),树结构展现支持数据权限 | |
| 36 | | | 岗位管理 | 配置系统用户所属担任职务 | | 36 | | | 岗位管理 | 配置系统用户所属担任职务 | |
| 37 | | | 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护 | | 37 | | | 字典管理 | 对系统中经常使用的一些较为固定的数据进行维护 | |
| 38 | -| | 通知公告 | 系统通知公告信息发布维护 | | 38 | +| 🚀 | 短信管理 | 短信渠道、短息模板、短信日志,对接阿里云、云片等主流短信平台 | |
| 39 | | 🚀 | 操作日志 | 系统正常操作日志记录和查询,集成 Swagger 生成日志内容 | | 39 | | 🚀 | 操作日志 | 系统正常操作日志记录和查询,集成 Swagger 生成日志内容 | |
| 40 | | | 登录日志 | 系统登录日志记录查询包含登录异常 | | 40 | | | 登录日志 | 系统登录日志记录查询包含登录异常 | |
| 41 | +| | 通知公告 | 系统通知公告信息发布维护 | | ||
| 41 | 42 | ||
| 42 | 计划新增功能: | 43 | 计划新增功能: |
| 43 | -* 短信 | ||
| 44 | * 邮件 | 44 | * 邮件 |
| 45 | * 钉钉、飞书等通知 | 45 | * 钉钉、飞书等通知 |
| 46 | 46 | ||
| @@ -87,14 +87,15 @@ | @@ -87,14 +87,15 @@ | ||
| 87 | 87 | ||
| 88 | ## 技术栈 | 88 | ## 技术栈 |
| 89 | 89 | ||
| 90 | -**后端** | 90 | +### 后端 |
| 91 | 91 | ||
| 92 | | 框架 | 说明 | 版本 | 学习指南 | | 92 | | 框架 | 说明 | 版本 | 学习指南 | |
| 93 | | --- | --- | --- | --- | | 93 | | --- | --- | --- | --- | |
| 94 | | [Spring Boot](https://spring.io/projects/spring-boot) | 应用开发框架 | 2.4.2 | [文档](https://github.com/YunaiV/SpringBoot-Labs) | | 94 | | [Spring Boot](https://spring.io/projects/spring-boot) | 应用开发框架 | 2.4.2 | [文档](https://github.com/YunaiV/SpringBoot-Labs) | |
| 95 | | [MySQL](https://www.mysql.com/cn/) | 数据库服务器 | 5.7 | | | 95 | | [MySQL](https://www.mysql.com/cn/) | 数据库服务器 | 5.7 | | |
| 96 | | [Druid](https://github.com/alibaba/druid) | JDBC 连接池、监控组件 | 1.2.4 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) | | 96 | | [Druid](https://github.com/alibaba/druid) | JDBC 连接池、监控组件 | 1.2.4 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) | |
| 97 | -| [MyBatis-Plus](https://mp.baomidou.com/) | MyBatis 增强工具包 | 3.4.1 | [文档](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) | | 97 | +| [MyBatis Plus](https://mp.baomidou.com/) | MyBatis 增强工具包 | 3.4.1 | [文档](http://www.iocoder.cn/Spring-Boot/MyBatis/?yudao) | |
| 98 | +| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 3.3.2 | [文档](hhttp://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) | | ||
| 98 | | [Redis](https://redis.io/) | key-value 数据库 | 5.0 | | | 99 | | [Redis](https://redis.io/) | key-value 数据库 | 5.0 | | |
| 99 | | [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 3.1.46 | [文档](http://www.iocoder.cn/Spring-Boot/Redis/?yudao) | | 100 | | [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 3.1.46 | [文档](http://www.iocoder.cn/Spring-Boot/Redis/?yudao) | |
| 100 | | [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架 | 5.4.2 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) | | 101 | | [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架 | 5.4.2 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) | |
| @@ -111,7 +112,7 @@ | @@ -111,7 +112,7 @@ | ||
| 111 | | [JUnit](https://junit.org/junit5/) | Java 单元测试框架 | 5.7.0 | - | | 112 | | [JUnit](https://junit.org/junit5/) | Java 单元测试框架 | 5.7.0 | - | |
| 112 | | [Mockito](https://github.com/mockito/mockito) | Java Mock 框架 | 3.6.28 | - | | 113 | | [Mockito](https://github.com/mockito/mockito) | Java Mock 框架 | 3.6.28 | - | |
| 113 | 114 | ||
| 114 | -**前端** | 115 | +### 前端 |
| 115 | 116 | ||
| 116 | | 框架 | 说明 | 版本 | | 117 | | 框架 | 说明 | 版本 | |
| 117 | | --- | --- | --- | | 118 | | --- | --- | --- | |
pom.xml
| @@ -30,6 +30,7 @@ | @@ -30,6 +30,7 @@ | ||
| 30 | <mysql-connector-java.version>5.1.46</mysql-connector-java.version> | 30 | <mysql-connector-java.version>5.1.46</mysql-connector-java.version> |
| 31 | <druid.version>1.2.4</druid.version> | 31 | <druid.version>1.2.4</druid.version> |
| 32 | <mybatis-plus.version>3.4.2</mybatis-plus.version> | 32 | <mybatis-plus.version>3.4.2</mybatis-plus.version> |
| 33 | + <dynamic-datasource.version>3.3.2</dynamic-datasource.version> | ||
| 33 | <redisson.version>3.15.1</redisson.version> | 34 | <redisson.version>3.15.1</redisson.version> |
| 34 | <!-- Config 配置中心相关 --> | 35 | <!-- Config 配置中心相关 --> |
| 35 | <apollo.version>1.7.0</apollo.version> | 36 | <apollo.version>1.7.0</apollo.version> |
| @@ -139,6 +140,11 @@ | @@ -139,6 +140,11 @@ | ||
| 139 | <artifactId>mybatis-plus-boot-starter</artifactId> | 140 | <artifactId>mybatis-plus-boot-starter</artifactId> |
| 140 | <version>${mybatis-plus.version}</version> | 141 | <version>${mybatis-plus.version}</version> |
| 141 | </dependency> | 142 | </dependency> |
| 143 | + <dependency> | ||
| 144 | + <groupId>com.baomidou</groupId> | ||
| 145 | + <artifactId>dynamic-datasource-spring-boot-starter</artifactId> <!-- 多数据源 --> | ||
| 146 | + <version>${dynamic-datasource.version}</version> | ||
| 147 | + </dependency> | ||
| 142 | 148 | ||
| 143 | <dependency> | 149 | <dependency> |
| 144 | <groupId>org.redisson</groupId> | 150 | <groupId>org.redisson</groupId> |
ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java deleted
| 1 | -package com.ruoyi.common.annotation; | ||
| 2 | - | ||
| 3 | -import java.lang.annotation.Documented; | ||
| 4 | -import java.lang.annotation.ElementType; | ||
| 5 | -import java.lang.annotation.Retention; | ||
| 6 | -import java.lang.annotation.RetentionPolicy; | ||
| 7 | -import java.lang.annotation.Target; | ||
| 8 | - | ||
| 9 | -/** | ||
| 10 | - * 数据权限过滤注解 | ||
| 11 | - * | ||
| 12 | - * @author ruoyi | ||
| 13 | - */ | ||
| 14 | -@Target(ElementType.METHOD) | ||
| 15 | -@Retention(RetentionPolicy.RUNTIME) | ||
| 16 | -@Documented | ||
| 17 | -public @interface DataScope { | ||
| 18 | - /** | ||
| 19 | - * 部门表的别名 | ||
| 20 | - */ | ||
| 21 | - public String deptAlias() default ""; | ||
| 22 | - | ||
| 23 | - /** | ||
| 24 | - * 用户表的别名 | ||
| 25 | - */ | ||
| 26 | - public String userAlias() default ""; | ||
| 27 | -} |
ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScopeAspect.java deleted
| 1 | -package com.ruoyi.framework.aspectj; | ||
| 2 | - | ||
| 3 | -import java.lang.reflect.Method; | ||
| 4 | - | ||
| 5 | -import org.aspectj.lang.JoinPoint; | ||
| 6 | -import org.aspectj.lang.Signature; | ||
| 7 | -import org.aspectj.lang.annotation.Aspect; | ||
| 8 | -import org.aspectj.lang.annotation.Before; | ||
| 9 | -import org.aspectj.lang.annotation.Pointcut; | ||
| 10 | -import org.aspectj.lang.reflect.MethodSignature; | ||
| 11 | -import org.springframework.stereotype.Component; | ||
| 12 | -import com.ruoyi.common.annotation.DataScope; | ||
| 13 | -import com.ruoyi.common.core.domain.BaseEntity; | ||
| 14 | -import com.ruoyi.common.core.domain.entity.SysRole; | ||
| 15 | -import com.ruoyi.common.core.domain.entity.SysUser; | ||
| 16 | -import com.ruoyi.common.core.domain.model.LoginUser; | ||
| 17 | -import com.ruoyi.common.utils.ServletUtils; | ||
| 18 | -import com.ruoyi.common.utils.StringUtils; | ||
| 19 | -import com.ruoyi.common.utils.spring.SpringUtils; | ||
| 20 | -import com.ruoyi.framework.web.service.TokenService; | ||
| 21 | - | ||
| 22 | -/** | ||
| 23 | - * 数据过滤处理 | ||
| 24 | - * | ||
| 25 | - * @author ruoyi | ||
| 26 | - */ | ||
| 27 | -@Aspect | ||
| 28 | -@Component | ||
| 29 | -public class DataScopeAspect { | ||
| 30 | - /** | ||
| 31 | - * 全部数据权限 | ||
| 32 | - */ | ||
| 33 | - public static final String DATA_SCOPE_ALL = "1"; | ||
| 34 | - | ||
| 35 | - /** | ||
| 36 | - * 自定数据权限 | ||
| 37 | - */ | ||
| 38 | - public static final String DATA_SCOPE_CUSTOM = "2"; | ||
| 39 | - | ||
| 40 | - /** | ||
| 41 | - * 部门数据权限 | ||
| 42 | - */ | ||
| 43 | - public static final String DATA_SCOPE_DEPT = "3"; | ||
| 44 | - | ||
| 45 | - /** | ||
| 46 | - * 部门及以下数据权限 | ||
| 47 | - */ | ||
| 48 | - public static final String DATA_SCOPE_DEPT_AND_CHILD = "4"; | ||
| 49 | - | ||
| 50 | - /** | ||
| 51 | - * 仅本人数据权限 | ||
| 52 | - */ | ||
| 53 | - public static final String DATA_SCOPE_SELF = "5"; | ||
| 54 | - | ||
| 55 | - /** | ||
| 56 | - * 数据权限过滤关键字 | ||
| 57 | - */ | ||
| 58 | - public static final String DATA_SCOPE = "dataScope"; | ||
| 59 | - | ||
| 60 | - // 配置织入点 | ||
| 61 | - @Pointcut("@annotation(com.ruoyi.common.annotation.DataScope)") | ||
| 62 | - public void dataScopePointCut() { | ||
| 63 | - } | ||
| 64 | - | ||
| 65 | - @Before("dataScopePointCut()") | ||
| 66 | - public void doBefore(JoinPoint point) throws Throwable { | ||
| 67 | - handleDataScope(point); | ||
| 68 | - } | ||
| 69 | - | ||
| 70 | - protected void handleDataScope(final JoinPoint joinPoint) { | ||
| 71 | - // 获得注解 | ||
| 72 | - DataScope controllerDataScope = getAnnotationLog(joinPoint); | ||
| 73 | - if (controllerDataScope == null) { | ||
| 74 | - return; | ||
| 75 | - } | ||
| 76 | - // 获取当前的用户 | ||
| 77 | - LoginUser loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest()); | ||
| 78 | - if (StringUtils.isNotNull(loginUser)) { | ||
| 79 | - SysUser currentUser = loginUser.getUser(); | ||
| 80 | - // 如果是超级管理员,则不过滤数据 | ||
| 81 | - if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin()) { | ||
| 82 | - dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(), | ||
| 83 | - controllerDataScope.userAlias()); | ||
| 84 | - } | ||
| 85 | - } | ||
| 86 | - } | ||
| 87 | - | ||
| 88 | - /** | ||
| 89 | - * 数据范围过滤 | ||
| 90 | - * | ||
| 91 | - * @param joinPoint 切点 | ||
| 92 | - * @param user 用户 | ||
| 93 | - * @param userAlias 别名 | ||
| 94 | - */ | ||
| 95 | - public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias) { | ||
| 96 | - StringBuilder sqlString = new StringBuilder(); | ||
| 97 | - | ||
| 98 | - for (SysRole role : user.getRoles()) { | ||
| 99 | - String dataScope = role.getDataScope(); | ||
| 100 | - if (DATA_SCOPE_ALL.equals(dataScope)) { | ||
| 101 | - sqlString = new StringBuilder(); | ||
| 102 | - break; | ||
| 103 | - } else if (DATA_SCOPE_CUSTOM.equals(dataScope)) { | ||
| 104 | - sqlString.append(StringUtils.format( | ||
| 105 | - " OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias, | ||
| 106 | - role.getRoleId())); | ||
| 107 | - } else if (DATA_SCOPE_DEPT.equals(dataScope)) { | ||
| 108 | - sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId())); | ||
| 109 | - } else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope)) { | ||
| 110 | - sqlString.append(StringUtils.format( | ||
| 111 | - " OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )", | ||
| 112 | - deptAlias, user.getDeptId(), user.getDeptId())); | ||
| 113 | - } else if (DATA_SCOPE_SELF.equals(dataScope)) { | ||
| 114 | - if (StringUtils.isNotBlank(userAlias)) { | ||
| 115 | - sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId())); | ||
| 116 | - } else { | ||
| 117 | - // 数据权限为仅本人且没有userAlias别名不查询任何数据 | ||
| 118 | - sqlString.append(" OR 1=0 "); | ||
| 119 | - } | ||
| 120 | - } | ||
| 121 | - } | ||
| 122 | - | ||
| 123 | - if (StringUtils.isNotBlank(sqlString.toString())) { | ||
| 124 | - Object params = joinPoint.getArgs()[0]; | ||
| 125 | - if (StringUtils.isNotNull(params) && params instanceof BaseEntity) { | ||
| 126 | - BaseEntity baseEntity = (BaseEntity) params; | ||
| 127 | - baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")"); | ||
| 128 | - } | ||
| 129 | - } | ||
| 130 | - } | ||
| 131 | - | ||
| 132 | - /** | ||
| 133 | - * 是否存在注解,如果存在就获取 | ||
| 134 | - */ | ||
| 135 | - private DataScope getAnnotationLog(JoinPoint joinPoint) { | ||
| 136 | - Signature signature = joinPoint.getSignature(); | ||
| 137 | - MethodSignature methodSignature = (MethodSignature) signature; | ||
| 138 | - Method method = methodSignature.getMethod(); | ||
| 139 | - | ||
| 140 | - if (method != null) { | ||
| 141 | - return method.getAnnotation(DataScope.class); | ||
| 142 | - } | ||
| 143 | - return null; | ||
| 144 | - } | ||
| 145 | -} |
ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java deleted
| 1 | -package com.ruoyi.common.annotation; | ||
| 2 | - | ||
| 3 | -import java.lang.annotation.Documented; | ||
| 4 | -import java.lang.annotation.ElementType; | ||
| 5 | -import java.lang.annotation.Inherited; | ||
| 6 | -import java.lang.annotation.Retention; | ||
| 7 | -import java.lang.annotation.RetentionPolicy; | ||
| 8 | -import java.lang.annotation.Target; | ||
| 9 | - | ||
| 10 | -import com.ruoyi.common.enums.DataSourceType; | ||
| 11 | - | ||
| 12 | -/** | ||
| 13 | - * 自定义多数据源切换注解 | ||
| 14 | - * <p> | ||
| 15 | - * 优先级:先方法,后类,如果方法覆盖了类上的数据源类型,以方法的为准,否则以类上的为准 | ||
| 16 | - * | ||
| 17 | - * @author ruoyi | ||
| 18 | - */ | ||
| 19 | -@Target({ElementType.METHOD, ElementType.TYPE}) | ||
| 20 | -@Retention(RetentionPolicy.RUNTIME) | ||
| 21 | -@Documented | ||
| 22 | -@Inherited | ||
| 23 | -public @interface DataSource { | ||
| 24 | - /** | ||
| 25 | - * 切换数据源名称 | ||
| 26 | - */ | ||
| 27 | - public DataSourceType value() default DataSourceType.MASTER; | ||
| 28 | -} |
ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSourceAspect.java deleted
| 1 | -package com.ruoyi.framework.aspectj; | ||
| 2 | - | ||
| 3 | -import java.util.Objects; | ||
| 4 | - | ||
| 5 | -import org.aspectj.lang.ProceedingJoinPoint; | ||
| 6 | -import org.aspectj.lang.annotation.Around; | ||
| 7 | -import org.aspectj.lang.annotation.Aspect; | ||
| 8 | -import org.aspectj.lang.annotation.Pointcut; | ||
| 9 | -import org.aspectj.lang.reflect.MethodSignature; | ||
| 10 | -import org.slf4j.Logger; | ||
| 11 | -import org.slf4j.LoggerFactory; | ||
| 12 | -import org.springframework.core.annotation.AnnotationUtils; | ||
| 13 | -import org.springframework.core.annotation.Order; | ||
| 14 | -import org.springframework.stereotype.Component; | ||
| 15 | -import com.ruoyi.common.annotation.DataSource; | ||
| 16 | -import com.ruoyi.common.utils.StringUtils; | ||
| 17 | -import com.ruoyi.framework.datasource.DynamicDataSourceContextHolder; | ||
| 18 | - | ||
| 19 | -/** | ||
| 20 | - * 多数据源处理 | ||
| 21 | - * | ||
| 22 | - * @author ruoyi | ||
| 23 | - */ | ||
| 24 | -@Aspect | ||
| 25 | -@Order(1) | ||
| 26 | -@Component | ||
| 27 | -public class DataSourceAspect { | ||
| 28 | - protected Logger logger = LoggerFactory.getLogger(getClass()); | ||
| 29 | - | ||
| 30 | - @Pointcut("@annotation(com.ruoyi.common.annotation.DataSource)" | ||
| 31 | - + "|| @within(com.ruoyi.common.annotation.DataSource)") | ||
| 32 | - public void dsPointCut() { | ||
| 33 | - | ||
| 34 | - } | ||
| 35 | - | ||
| 36 | - @Around("dsPointCut()") | ||
| 37 | - public Object around(ProceedingJoinPoint point) throws Throwable { | ||
| 38 | - DataSource dataSource = getDataSource(point); | ||
| 39 | - | ||
| 40 | - if (StringUtils.isNotNull(dataSource)) { | ||
| 41 | - DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name()); | ||
| 42 | - } | ||
| 43 | - | ||
| 44 | - try { | ||
| 45 | - return point.proceed(); | ||
| 46 | - } finally { | ||
| 47 | - // 销毁数据源 在执行方法之后 | ||
| 48 | - DynamicDataSourceContextHolder.clearDataSourceType(); | ||
| 49 | - } | ||
| 50 | - } | ||
| 51 | - | ||
| 52 | - /** | ||
| 53 | - * 获取需要切换的数据源 | ||
| 54 | - */ | ||
| 55 | - public DataSource getDataSource(ProceedingJoinPoint point) { | ||
| 56 | - MethodSignature signature = (MethodSignature) point.getSignature(); | ||
| 57 | - DataSource dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class); | ||
| 58 | - if (Objects.nonNull(dataSource)) { | ||
| 59 | - return dataSource; | ||
| 60 | - } | ||
| 61 | - | ||
| 62 | - return AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class); | ||
| 63 | - } | ||
| 64 | -} |
ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSourceType.java deleted
ruoyi-common/src/main/java/com/ruoyi/common/annotation/DynamicDataSource.java deleted
| 1 | -package com.ruoyi.framework.datasource; | ||
| 2 | - | ||
| 3 | -import java.util.Map; | ||
| 4 | -import javax.sql.DataSource; | ||
| 5 | - | ||
| 6 | -import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; | ||
| 7 | - | ||
| 8 | -/** | ||
| 9 | - * 动态数据源 | ||
| 10 | - * | ||
| 11 | - * @author ruoyi | ||
| 12 | - */ | ||
| 13 | -public class DynamicDataSource extends AbstractRoutingDataSource { | ||
| 14 | - public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources) { | ||
| 15 | - super.setDefaultTargetDataSource(defaultTargetDataSource); | ||
| 16 | - super.setTargetDataSources(targetDataSources); | ||
| 17 | - super.afterPropertiesSet(); | ||
| 18 | - } | ||
| 19 | - | ||
| 20 | - @Override | ||
| 21 | - protected Object determineCurrentLookupKey() { | ||
| 22 | - return DynamicDataSourceContextHolder.getDataSourceType(); | ||
| 23 | - } | ||
| 24 | -} |
ruoyi-common/src/main/java/com/ruoyi/common/annotation/DynamicDataSourceContextHolder.java deleted
| 1 | -package com.ruoyi.framework.datasource; | ||
| 2 | - | ||
| 3 | -import org.slf4j.Logger; | ||
| 4 | -import org.slf4j.LoggerFactory; | ||
| 5 | - | ||
| 6 | -/** | ||
| 7 | - * 数据源切换处理 | ||
| 8 | - * | ||
| 9 | - * @author ruoyi | ||
| 10 | - */ | ||
| 11 | -public class DynamicDataSourceContextHolder { | ||
| 12 | - public static final Logger log = LoggerFactory.getLogger(DynamicDataSourceContextHolder.class); | ||
| 13 | - | ||
| 14 | - /** | ||
| 15 | - * 使用ThreadLocal维护变量,ThreadLocal为每个使用该变量的线程提供独立的变量副本, | ||
| 16 | - * 所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。 | ||
| 17 | - */ | ||
| 18 | - private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>(); | ||
| 19 | - | ||
| 20 | - /** | ||
| 21 | - * 设置数据源的变量 | ||
| 22 | - */ | ||
| 23 | - public static void setDataSourceType(String dsType) { | ||
| 24 | - log.info("切换到{}数据源", dsType); | ||
| 25 | - CONTEXT_HOLDER.set(dsType); | ||
| 26 | - } | ||
| 27 | - | ||
| 28 | - /** | ||
| 29 | - * 获得数据源的变量 | ||
| 30 | - */ | ||
| 31 | - public static String getDataSourceType() { | ||
| 32 | - return CONTEXT_HOLDER.get(); | ||
| 33 | - } | ||
| 34 | - | ||
| 35 | - /** | ||
| 36 | - * 清空数据源变量 | ||
| 37 | - */ | ||
| 38 | - public static void clearDataSourceType() { | ||
| 39 | - CONTEXT_HOLDER.remove(); | ||
| 40 | - } | ||
| 41 | -} |
ruoyi-common/src/main/java/com/ruoyi/common/config/DruidConfig.java deleted
| 1 | -package com.ruoyi.framework.config; | ||
| 2 | - | ||
| 3 | -import java.io.IOException; | ||
| 4 | -import java.util.HashMap; | ||
| 5 | -import java.util.Map; | ||
| 6 | -import javax.servlet.Filter; | ||
| 7 | -import javax.servlet.FilterChain; | ||
| 8 | -import javax.servlet.ServletException; | ||
| 9 | -import javax.servlet.ServletRequest; | ||
| 10 | -import javax.servlet.ServletResponse; | ||
| 11 | -import javax.sql.DataSource; | ||
| 12 | - | ||
| 13 | -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||
| 14 | -import org.springframework.boot.context.properties.ConfigurationProperties; | ||
| 15 | -import org.springframework.boot.web.servlet.FilterRegistrationBean; | ||
| 16 | -import org.springframework.context.annotation.Bean; | ||
| 17 | -import org.springframework.context.annotation.Configuration; | ||
| 18 | -import org.springframework.context.annotation.Primary; | ||
| 19 | -import com.alibaba.druid.pool.DruidDataSource; | ||
| 20 | -import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder; | ||
| 21 | -import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties; | ||
| 22 | -import com.alibaba.druid.util.Utils; | ||
| 23 | -import com.ruoyi.common.enums.DataSourceType; | ||
| 24 | -import com.ruoyi.common.utils.spring.SpringUtils; | ||
| 25 | -import com.ruoyi.framework.config.properties.DruidProperties; | ||
| 26 | -import com.ruoyi.framework.datasource.DynamicDataSource; | ||
| 27 | - | ||
| 28 | -/** | ||
| 29 | - * druid 配置多数据源 | ||
| 30 | - * | ||
| 31 | - * @author ruoyi | ||
| 32 | - */ | ||
| 33 | -@Configuration | ||
| 34 | -public class DruidConfig { | ||
| 35 | - @Bean | ||
| 36 | - @ConfigurationProperties("spring.datasource.druid.master") | ||
| 37 | - public DataSource masterDataSource(DruidProperties druidProperties) { | ||
| 38 | - DruidDataSource dataSource = DruidDataSourceBuilder.create().build(); | ||
| 39 | - return druidProperties.dataSource(dataSource); | ||
| 40 | - } | ||
| 41 | - | ||
| 42 | - @Bean | ||
| 43 | - @ConfigurationProperties("spring.datasource.druid.slave") | ||
| 44 | - @ConditionalOnProperty(prefix = "spring.datasource.druid.slave", name = "enabled", havingValue = "true") | ||
| 45 | - public DataSource slaveDataSource(DruidProperties druidProperties) { | ||
| 46 | - DruidDataSource dataSource = DruidDataSourceBuilder.create().build(); | ||
| 47 | - return druidProperties.dataSource(dataSource); | ||
| 48 | - } | ||
| 49 | - | ||
| 50 | - @Bean(name = "dynamicDataSource") | ||
| 51 | - @Primary | ||
| 52 | - public DynamicDataSource dataSource(DataSource masterDataSource) { | ||
| 53 | - Map<Object, Object> targetDataSources = new HashMap<>(); | ||
| 54 | - targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource); | ||
| 55 | - setDataSource(targetDataSources, DataSourceType.SLAVE.name(), "slaveDataSource"); | ||
| 56 | - return new DynamicDataSource(masterDataSource, targetDataSources); | ||
| 57 | - } | ||
| 58 | - | ||
| 59 | - /** | ||
| 60 | - * 设置数据源 | ||
| 61 | - * | ||
| 62 | - * @param targetDataSources 备选数据源集合 | ||
| 63 | - * @param sourceName 数据源名称 | ||
| 64 | - * @param beanName bean名称 | ||
| 65 | - */ | ||
| 66 | - public void setDataSource(Map<Object, Object> targetDataSources, String sourceName, String beanName) { | ||
| 67 | - try { | ||
| 68 | - DataSource dataSource = SpringUtils.getBean(beanName); | ||
| 69 | - targetDataSources.put(sourceName, dataSource); | ||
| 70 | - } catch (Exception e) { | ||
| 71 | - } | ||
| 72 | - } | ||
| 73 | - | ||
| 74 | - /** | ||
| 75 | - * 去除监控页面底部的广告 | ||
| 76 | - */ | ||
| 77 | - @SuppressWarnings({"rawtypes", "unchecked"}) | ||
| 78 | - @Bean | ||
| 79 | - @ConditionalOnProperty(name = "spring.datasource.druid.statViewServlet.enabled", havingValue = "true") | ||
| 80 | - public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties) { | ||
| 81 | - // 获取web监控页面的参数 | ||
| 82 | - DruidStatProperties.StatViewServlet config = properties.getStatViewServlet(); | ||
| 83 | - // 提取common.js的配置路径 | ||
| 84 | - String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*"; | ||
| 85 | - String commonJsPattern = pattern.replaceAll("\\*", "js/common.js"); | ||
| 86 | - final String filePath = "support/http/resources/js/common.js"; | ||
| 87 | - // 创建filter进行过滤 | ||
| 88 | - Filter filter = new Filter() { | ||
| 89 | - @Override | ||
| 90 | - public void init(javax.servlet.FilterConfig filterConfig) throws ServletException { | ||
| 91 | - } | ||
| 92 | - | ||
| 93 | - @Override | ||
| 94 | - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) | ||
| 95 | - throws IOException, ServletException { | ||
| 96 | - chain.doFilter(request, response); | ||
| 97 | - // 重置缓冲区,响应头不会被重置 | ||
| 98 | - response.resetBuffer(); | ||
| 99 | - // 获取common.js | ||
| 100 | - String text = Utils.readFromResource(filePath); | ||
| 101 | - // 正则替换banner, 除去底部的广告信息 | ||
| 102 | - text = text.replaceAll("<a.*?banner\"></a><br/>", ""); | ||
| 103 | - text = text.replaceAll("powered.*?shrek.wang</a>", ""); | ||
| 104 | - response.getWriter().write(text); | ||
| 105 | - } | ||
| 106 | - | ||
| 107 | - @Override | ||
| 108 | - public void destroy() { | ||
| 109 | - } | ||
| 110 | - }; | ||
| 111 | - FilterRegistrationBean registrationBean = new FilterRegistrationBean(); | ||
| 112 | - registrationBean.setFilter(filter); | ||
| 113 | - registrationBean.addUrlPatterns(commonJsPattern); | ||
| 114 | - return registrationBean; | ||
| 115 | - } | ||
| 116 | -} |
ruoyi-common/src/main/resources/application-druid.yml deleted
| 1 | -# 数据源配置 | ||
| 2 | -spring: | ||
| 3 | - datasource: | ||
| 4 | - type: com.alibaba.druid.pool.DruidDataSource | ||
| 5 | - driverClassName: com.mysql.cj.jdbc.Driver | ||
| 6 | - druid: | ||
| 7 | - # 主库数据源 | ||
| 8 | - master: | ||
| 9 | - url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 | ||
| 10 | - username: root | ||
| 11 | - password: password | ||
| 12 | - # 从库数据源 | ||
| 13 | - slave: | ||
| 14 | - # 从数据源开关/默认关闭 | ||
| 15 | - enabled: false | ||
| 16 | - url: | ||
| 17 | - username: | ||
| 18 | - password: | ||
| 19 | - # 初始连接数 | ||
| 20 | - initialSize: 5 | ||
| 21 | - # 最小连接池数量 | ||
| 22 | - minIdle: 10 | ||
| 23 | - # 最大连接池数量 | ||
| 24 | - maxActive: 20 | ||
| 25 | - # 配置获取连接等待超时的时间 | ||
| 26 | - maxWait: 60000 | ||
| 27 | - # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 | ||
| 28 | - timeBetweenEvictionRunsMillis: 60000 | ||
| 29 | - # 配置一个连接在池中最小生存的时间,单位是毫秒 | ||
| 30 | - minEvictableIdleTimeMillis: 300000 | ||
| 31 | - # 配置一个连接在池中最大生存的时间,单位是毫秒 | ||
| 32 | - maxEvictableIdleTimeMillis: 900000 | ||
| 33 | - # 配置检测连接是否有效 | ||
| 34 | - validationQuery: SELECT 1 FROM DUAL | ||
| 35 | - testWhileIdle: true | ||
| 36 | - testOnBorrow: false | ||
| 37 | - testOnReturn: false |
src/main/java/cn/iocoder/dashboard/framework/datasource/config/DataSourceConfiguration.java
| 1 | package cn.iocoder.dashboard.framework.datasource.config; | 1 | package cn.iocoder.dashboard.framework.datasource.config; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.dashboard.framework.datasource.core.filter.DruidAdRemoveFilter; | ||
| 4 | +import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties; | ||
| 5 | +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | ||
| 6 | +import org.springframework.boot.web.servlet.FilterRegistrationBean; | ||
| 7 | +import org.springframework.context.annotation.Bean; | ||
| 3 | import org.springframework.context.annotation.Configuration; | 8 | import org.springframework.context.annotation.Configuration; |
| 4 | import org.springframework.transaction.annotation.EnableTransactionManagement; | 9 | import org.springframework.transaction.annotation.EnableTransactionManagement; |
| 5 | 10 | ||
| 6 | /** | 11 | /** |
| 7 | - * 数据库匹配类 | 12 | + * 数据库配置类 |
| 13 | + * | ||
| 14 | + * @author 芋道源码 | ||
| 8 | */ | 15 | */ |
| 9 | @Configuration | 16 | @Configuration |
| 10 | @EnableTransactionManagement(proxyTargetClass = true) // 启动事务管理 | 17 | @EnableTransactionManagement(proxyTargetClass = true) // 启动事务管理 |
| 11 | public class DataSourceConfiguration { | 18 | public class DataSourceConfiguration { |
| 19 | + | ||
| 20 | + /** | ||
| 21 | + * 创建 DruidAdRemoveFilter 过滤器,过滤 common.js 的广告 | ||
| 22 | + */ | ||
| 23 | + @Bean | ||
| 24 | + @ConditionalOnProperty(name = "spring.datasource.druid.web-stat-filter.enabled", havingValue = "true") | ||
| 25 | + public FilterRegistrationBean<DruidAdRemoveFilter> druidAdRemoveFilterFilter(DruidStatProperties properties) { | ||
| 26 | + // 获取 druid web 监控页面的参数 | ||
| 27 | + DruidStatProperties.StatViewServlet config = properties.getStatViewServlet(); | ||
| 28 | + // 提取 common.js 的配置路径 | ||
| 29 | + String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*"; | ||
| 30 | + String commonJsPattern = pattern.replaceAll("\\*", "js/common.js"); | ||
| 31 | + // 创建 DruidAdRemoveFilter Bean | ||
| 32 | + FilterRegistrationBean<DruidAdRemoveFilter> registrationBean = new FilterRegistrationBean<>(); | ||
| 33 | + registrationBean.setFilter(new DruidAdRemoveFilter()); | ||
| 34 | + registrationBean.addUrlPatterns(commonJsPattern); | ||
| 35 | + return registrationBean; | ||
| 36 | + } | ||
| 37 | + | ||
| 12 | } | 38 | } |
src/main/java/cn/iocoder/dashboard/framework/datasource/core/enums/DataSourceEnum.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.framework.datasource.core.enums; | ||
| 2 | + | ||
| 3 | +/** | ||
| 4 | + * 对应于多数据源中不同数据源配置 | ||
| 5 | + * | ||
| 6 | + * 通过在方法上,使用 {@link com.baomidou.dynamic.datasource.annotation.DS} 注解,设置使用的数据源。 | ||
| 7 | + * 注意,默认是 {@link #MASTER} 数据源 | ||
| 8 | + * | ||
| 9 | + * 对应官方文档为 http://dynamic-datasource.com/guide/customize/Annotation.html | ||
| 10 | + */ | ||
| 11 | +public interface DataSourceEnum { | ||
| 12 | + | ||
| 13 | + /** | ||
| 14 | + * 主库,推荐使用 {@link com.baomidou.dynamic.datasource.annotation.Master} 注解 | ||
| 15 | + */ | ||
| 16 | + String MASTER = "master"; | ||
| 17 | + /** | ||
| 18 | + * 从库,推荐使用 {@link com.baomidou.dynamic.datasource.annotation.Slave} 注解 | ||
| 19 | + */ | ||
| 20 | + String SLAVE = "slave"; | ||
| 21 | + | ||
| 22 | +} |
src/main/java/cn/iocoder/dashboard/framework/datasource/core/filter/DruidAdRemoveFilter.java
0 → 100644
| 1 | +package cn.iocoder.dashboard.framework.datasource.core.filter; | ||
| 2 | + | ||
| 3 | +import com.alibaba.druid.util.Utils; | ||
| 4 | +import org.springframework.web.filter.OncePerRequestFilter; | ||
| 5 | + | ||
| 6 | +import javax.servlet.FilterChain; | ||
| 7 | +import javax.servlet.ServletException; | ||
| 8 | +import javax.servlet.http.HttpServletRequest; | ||
| 9 | +import javax.servlet.http.HttpServletResponse; | ||
| 10 | +import java.io.IOException; | ||
| 11 | + | ||
| 12 | +/** | ||
| 13 | + * Druid 底部广告过滤器 | ||
| 14 | + * | ||
| 15 | + * @author 芋道源码 | ||
| 16 | + */ | ||
| 17 | +public class DruidAdRemoveFilter extends OncePerRequestFilter { | ||
| 18 | + | ||
| 19 | + /** | ||
| 20 | + * common.js 的路径 | ||
| 21 | + */ | ||
| 22 | + private static final String COMMON_JS_ILE_PATH = "support/http/resources/js/common.js"; | ||
| 23 | + | ||
| 24 | + @Override | ||
| 25 | + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) | ||
| 26 | + throws ServletException, IOException { | ||
| 27 | + chain.doFilter(request, response); | ||
| 28 | + // 重置缓冲区,响应头不会被重置 | ||
| 29 | + response.resetBuffer(); | ||
| 30 | + // 获取 common.js | ||
| 31 | + String text = Utils.readFromResource(COMMON_JS_ILE_PATH); | ||
| 32 | + // 正则替换 banner, 除去底部的广告信息 | ||
| 33 | + text = text.replaceAll("<a.*?banner\"></a><br/>", ""); | ||
| 34 | + text = text.replaceAll("powered.*?shrek.wang</a>", ""); | ||
| 35 | + response.getWriter().write(text); | ||
| 36 | + } | ||
| 37 | + | ||
| 38 | +} |
src/main/java/cn/iocoder/dashboard/modules/tool/dal/mysql/codegen/ToolSchemaTableMapper.java
| @@ -18,11 +18,7 @@ public interface ToolSchemaTableMapper extends BaseMapperX<ToolSchemaTableDO> { | @@ -18,11 +18,7 @@ public interface ToolSchemaTableMapper extends BaseMapperX<ToolSchemaTableDO> { | ||
| 18 | .likeIfPresent("table_comment", tableComment)); | 18 | .likeIfPresent("table_comment", tableComment)); |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | - default List<ToolSchemaTableDO> selectListByTableSchema(String tableSchema) { | ||
| 22 | - return selectList(new QueryWrapper<ToolSchemaTableDO>().eq("table_schema", tableSchema)); | ||
| 23 | - } | ||
| 24 | - | ||
| 25 | - default ToolSchemaTableDO selectByTableName1(String tableSchema, String tableName) { | 21 | + default ToolSchemaTableDO selectByTableSchemaAndTableName(String tableSchema, String tableName) { |
| 26 | return selectOne(new QueryWrapper<ToolSchemaTableDO>().eq("table_schema",tableSchema) | 22 | return selectOne(new QueryWrapper<ToolSchemaTableDO>().eq("table_schema",tableSchema) |
| 27 | .eq("table_name", tableName)); | 23 | .eq("table_name", tableName)); |
| 28 | } | 24 | } |
src/main/java/cn/iocoder/dashboard/modules/tool/service/codegen/impl/ToolCodegenServiceImpl.java
| @@ -101,10 +101,10 @@ public class ToolCodegenServiceImpl implements ToolCodegenService { | @@ -101,10 +101,10 @@ public class ToolCodegenServiceImpl implements ToolCodegenService { | ||
| 101 | 101 | ||
| 102 | @Override | 102 | @Override |
| 103 | public Long createCodegen(String tableName) { | 103 | public Long createCodegen(String tableName) { |
| 104 | - //获取当前schema | 104 | + // 获取当前schema |
| 105 | String tableSchema = codegenProperties.getDbSchemas().iterator().next(); | 105 | String tableSchema = codegenProperties.getDbSchemas().iterator().next(); |
| 106 | // 从数据库中,获得数据库表结构 | 106 | // 从数据库中,获得数据库表结构 |
| 107 | - ToolSchemaTableDO schemaTable = schemaTableMapper.selectByTableName1(tableSchema, tableName); | 107 | + ToolSchemaTableDO schemaTable = schemaTableMapper.selectByTableSchemaAndTableName(tableSchema, tableName); |
| 108 | List<ToolSchemaColumnDO> schemaColumns = schemaColumnMapper.selectListByTableName(tableSchema, tableName); | 108 | List<ToolSchemaColumnDO> schemaColumns = schemaColumnMapper.selectListByTableName(tableSchema, tableName); |
| 109 | // 导入 | 109 | // 导入 |
| 110 | return this.createCodegen0(ToolCodegenImportTypeEnum.DB, schemaTable, schemaColumns); | 110 | return this.createCodegen0(ToolCodegenImportTypeEnum.DB, schemaTable, schemaColumns); |
src/main/resources/application-dev.yaml
| @@ -4,34 +4,56 @@ server: | @@ -4,34 +4,56 @@ server: | ||
| 4 | --- #################### 数据库相关配置 #################### | 4 | --- #################### 数据库相关配置 #################### |
| 5 | 5 | ||
| 6 | spring: | 6 | spring: |
| 7 | - # 数据源配置项 TODO 多数据源;TODO 监控配置 | 7 | + # 数据源配置项 |
| 8 | + autoconfigure: | ||
| 9 | + exclude: | ||
| 10 | + - com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源 | ||
| 8 | datasource: | 11 | datasource: |
| 9 | - name: ruoyi-vue-pro | ||
| 10 | - url: jdbc:mysql://400-infra.server.iocoder.cn:3306/${spring.datasource.name}?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT | ||
| 11 | - driver-class-name: com.mysql.jdbc.Driver | ||
| 12 | - username: root | ||
| 13 | - password: 3WLiVUBEwTbvAfsh | ||
| 14 | - druid: | 12 | + druid: # Druid 【监控】相关的全局配置 |
| 15 | web-stat-filter: | 13 | web-stat-filter: |
| 16 | enabled: true | 14 | enabled: true |
| 17 | stat-view-servlet: | 15 | stat-view-servlet: |
| 18 | enabled: true | 16 | enabled: true |
| 19 | - # 设置白名单,不填则允许所有访问 | ||
| 20 | - allow: | 17 | + allow: # 设置白名单,不填则允许所有访问 |
| 21 | url-pattern: /druid/* | 18 | url-pattern: /druid/* |
| 22 | - # 控制台管理用户名和密码 | ||
| 23 | - login-username: | 19 | + login-username: # 控制台管理用户名和密码 |
| 24 | login-password: | 20 | login-password: |
| 25 | filter: | 21 | filter: |
| 26 | stat: | 22 | stat: |
| 27 | enabled: true | 23 | enabled: true |
| 28 | - # 慢 SQL 记录 | ||
| 29 | - log-slow-sql: true | 24 | + log-slow-sql: true # 慢 SQL 记录 |
| 30 | slow-sql-millis: 100 | 25 | slow-sql-millis: 100 |
| 31 | merge-sql: true | 26 | merge-sql: true |
| 32 | wall: | 27 | wall: |
| 33 | config: | 28 | config: |
| 34 | multi-statement-allow: true | 29 | multi-statement-allow: true |
| 30 | + dynamic: # 多数据源配置 | ||
| 31 | + druid: # Druid 【连接池】相关的全局配置 | ||
| 32 | + initial-size: 5 # 初始连接数 | ||
| 33 | + min-idle: 10 # 最小连接池数量 | ||
| 34 | + max-active: 20 # 最大连接池数量 | ||
| 35 | + max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 | ||
| 36 | + time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 | ||
| 37 | + min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 | ||
| 38 | + max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 | ||
| 39 | + validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 | ||
| 40 | + test-while-idle: true | ||
| 41 | + test-on-borrow: false | ||
| 42 | + test-on-return: false | ||
| 43 | + primary: master | ||
| 44 | + datasource: | ||
| 45 | + master: | ||
| 46 | + name: ruoyi-vue-pro | ||
| 47 | + url: jdbc:mysql://400-infra.server.iocoder.cn:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT | ||
| 48 | + driver-class-name: com.mysql.jdbc.Driver | ||
| 49 | + username: root | ||
| 50 | + password: 3WLiVUBEwTbvAfsh | ||
| 51 | + slave: # 模拟从库,可根据自己需要修改 # 模拟从库,可根据自己需要修改 | ||
| 52 | + name: ruoyi-vue-pro | ||
| 53 | + url: jdbc:mysql://400-infra.server.iocoder.cn:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT | ||
| 54 | + driver-class-name: com.mysql.jdbc.Driver | ||
| 55 | + username: root | ||
| 56 | + password: 3WLiVUBEwTbvAfsh | ||
| 35 | 57 | ||
| 36 | # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 | 58 | # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 |
| 37 | redis: | 59 | redis: |
| @@ -77,9 +99,9 @@ apollo: | @@ -77,9 +99,9 @@ apollo: | ||
| 77 | eagerLoad: | 99 | eagerLoad: |
| 78 | enabled: true # 设置 Apollo 在日志初始化前生效,可以实现日志的动态级别配置 | 100 | enabled: true # 设置 Apollo 在日志初始化前生效,可以实现日志的动态级别配置 |
| 79 | jdbc: # 自定义的 JDBC 配置项,用于数据库的地址 | 101 | jdbc: # 自定义的 JDBC 配置项,用于数据库的地址 |
| 80 | - url: ${spring.datasource.url} | ||
| 81 | - username: ${spring.datasource.username} | ||
| 82 | - password: ${spring.datasource.password} | 102 | + url: ${spring.datasource.dynamic.datasource.master.url} |
| 103 | + username: ${spring.datasource.dynamic.datasource.master.username} | ||
| 104 | + password: ${spring.datasource.dynamic.datasource.master.password} | ||
| 83 | 105 | ||
| 84 | --- #################### 服务保障相关配置 #################### | 106 | --- #################### 服务保障相关配置 #################### |
| 85 | 107 | ||
| @@ -155,7 +177,7 @@ yudao: | @@ -155,7 +177,7 @@ yudao: | ||
| 155 | base-path: http://127.0.0.1:${server.port}${yudao.web.api-prefix}/system/file/get/ | 177 | base-path: http://127.0.0.1:${server.port}${yudao.web.api-prefix}/system/file/get/ |
| 156 | codegen: | 178 | codegen: |
| 157 | base-package: ${yudao.info.base-package} | 179 | base-package: ${yudao.info.base-package} |
| 158 | - db-schemas: ${spring.datasource.name} | 180 | + db-schemas: ${spring.datasource.dynamic.datasource.master.name} |
| 159 | xss: | 181 | xss: |
| 160 | enable: false | 182 | enable: false |
| 161 | exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系 | 183 | exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系 |
src/main/resources/application-local.yaml
| @@ -4,34 +4,56 @@ server: | @@ -4,34 +4,56 @@ server: | ||
| 4 | --- #################### 数据库相关配置 #################### | 4 | --- #################### 数据库相关配置 #################### |
| 5 | 5 | ||
| 6 | spring: | 6 | spring: |
| 7 | - # 数据源配置项 TODO 多数据源;TODO 监控配置 | 7 | + # 数据源配置项 |
| 8 | + autoconfigure: | ||
| 9 | + exclude: | ||
| 10 | + - com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源 | ||
| 8 | datasource: | 11 | datasource: |
| 9 | - name: ruoyi-vue-pro | ||
| 10 | - url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.name}?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT | ||
| 11 | - driver-class-name: com.mysql.jdbc.Driver | ||
| 12 | - username: root | ||
| 13 | - password: 123456 | ||
| 14 | - druid: | 12 | + druid: # Druid 【监控】相关的全局配置 |
| 15 | web-stat-filter: | 13 | web-stat-filter: |
| 16 | enabled: true | 14 | enabled: true |
| 17 | stat-view-servlet: | 15 | stat-view-servlet: |
| 18 | enabled: true | 16 | enabled: true |
| 19 | - # 设置白名单,不填则允许所有访问 | ||
| 20 | - allow: | 17 | + allow: # 设置白名单,不填则允许所有访问 |
| 21 | url-pattern: /druid/* | 18 | url-pattern: /druid/* |
| 22 | - # 控制台管理用户名和密码 | ||
| 23 | - login-username: | 19 | + login-username: # 控制台管理用户名和密码 |
| 24 | login-password: | 20 | login-password: |
| 25 | filter: | 21 | filter: |
| 26 | stat: | 22 | stat: |
| 27 | enabled: true | 23 | enabled: true |
| 28 | - # 慢 SQL 记录 | ||
| 29 | - log-slow-sql: true | 24 | + log-slow-sql: true # 慢 SQL 记录 |
| 30 | slow-sql-millis: 100 | 25 | slow-sql-millis: 100 |
| 31 | merge-sql: true | 26 | merge-sql: true |
| 32 | wall: | 27 | wall: |
| 33 | config: | 28 | config: |
| 34 | multi-statement-allow: true | 29 | multi-statement-allow: true |
| 30 | + dynamic: # 多数据源配置 | ||
| 31 | + druid: # Druid 【连接池】相关的全局配置 | ||
| 32 | + initial-size: 5 # 初始连接数 | ||
| 33 | + min-idle: 10 # 最小连接池数量 | ||
| 34 | + max-active: 20 # 最大连接池数量 | ||
| 35 | + max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 | ||
| 36 | + time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 | ||
| 37 | + min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 | ||
| 38 | + max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 | ||
| 39 | + validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 | ||
| 40 | + test-while-idle: true | ||
| 41 | + test-on-borrow: false | ||
| 42 | + test-on-return: false | ||
| 43 | + primary: master | ||
| 44 | + datasource: | ||
| 45 | + master: | ||
| 46 | + name: ruoyi-vue-pro | ||
| 47 | + url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT | ||
| 48 | + driver-class-name: com.mysql.jdbc.Driver | ||
| 49 | + username: root | ||
| 50 | + password: 123456 | ||
| 51 | + slave: # 模拟从库,可根据自己需要修改 | ||
| 52 | + name: ruoyi-vue-pro | ||
| 53 | + url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT | ||
| 54 | + driver-class-name: com.mysql.jdbc.Driver | ||
| 55 | + username: root | ||
| 56 | + password: 123456 | ||
| 35 | 57 | ||
| 36 | # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 | 58 | # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 |
| 37 | redis: | 59 | redis: |
| @@ -77,9 +99,9 @@ apollo: | @@ -77,9 +99,9 @@ apollo: | ||
| 77 | eagerLoad: | 99 | eagerLoad: |
| 78 | enabled: true # 设置 Apollo 在日志初始化前生效,可以实现日志的动态级别配置 | 100 | enabled: true # 设置 Apollo 在日志初始化前生效,可以实现日志的动态级别配置 |
| 79 | jdbc: # 自定义的 JDBC 配置项,用于数据库的地址 | 101 | jdbc: # 自定义的 JDBC 配置项,用于数据库的地址 |
| 80 | - url: ${spring.datasource.url} | ||
| 81 | - username: ${spring.datasource.username} | ||
| 82 | - password: ${spring.datasource.password} | 102 | + url: ${spring.datasource.dynamic.datasource.master.url} |
| 103 | + username: ${spring.datasource.dynamic.datasource.master.username} | ||
| 104 | + password: ${spring.datasource.dynamic.datasource.master.password} | ||
| 83 | 105 | ||
| 84 | --- #################### 服务保障相关配置 #################### | 106 | --- #################### 服务保障相关配置 #################### |
| 85 | 107 | ||
| @@ -155,7 +177,7 @@ yudao: | @@ -155,7 +177,7 @@ yudao: | ||
| 155 | base-path: http://127.0.0.1:${server.port}${yudao.web.api-prefix}/system/file/get/ | 177 | base-path: http://127.0.0.1:${server.port}${yudao.web.api-prefix}/system/file/get/ |
| 156 | codegen: | 178 | codegen: |
| 157 | base-package: ${yudao.info.base-package} | 179 | base-package: ${yudao.info.base-package} |
| 158 | - db-schemas: ${spring.datasource.name} | 180 | + db-schemas: ${spring.datasource.dynamic.datasource.master.name} |
| 159 | xss: | 181 | xss: |
| 160 | enable: false | 182 | enable: false |
| 161 | exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系 | 183 | exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系 |
src/main/resources/application.yaml
| @@ -12,7 +12,6 @@ spring: | @@ -12,7 +12,6 @@ spring: | ||
| 12 | max-file-size: 16MB # 单个文件大小 | 12 | max-file-size: 16MB # 单个文件大小 |
| 13 | max-request-size: 32MB # 设置总上传的文件大小 | 13 | max-request-size: 32MB # 设置总上传的文件大小 |
| 14 | 14 | ||
| 15 | - # Jackson 配置项 | ||
| 16 | jackson: | 15 | jackson: |
| 17 | serialization: | 16 | serialization: |
| 18 | write-dates-as-timestamps: true # 设置 Date 的格式,使用时间戳 | 17 | write-dates-as-timestamps: true # 设置 Date 的格式,使用时间戳 |
| @@ -32,3 +31,6 @@ mybatis-plus: | @@ -32,3 +31,6 @@ mybatis-plus: | ||
| 32 | logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) | 31 | logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) |
| 33 | mapper-locations: classpath*:mapper/*.xml | 32 | mapper-locations: classpath*:mapper/*.xml |
| 34 | type-aliases-package: ${yudao.info.base-package}.modules.*.dal.dataobject | 33 | type-aliases-package: ${yudao.info.base-package}.modules.*.dal.dataobject |
| 34 | + | ||
| 35 | +--- #################### 芋道相关配置 #################### | ||
| 36 | + |
src/test-integration/java/cn/iocoder/dashboard/BaseDbAndRedisIntegrationTest.java
| @@ -3,7 +3,7 @@ package cn.iocoder.dashboard; | @@ -3,7 +3,7 @@ package cn.iocoder.dashboard; | ||
| 3 | import cn.iocoder.dashboard.framework.datasource.config.DataSourceConfiguration; | 3 | import cn.iocoder.dashboard.framework.datasource.config.DataSourceConfiguration; |
| 4 | import cn.iocoder.dashboard.framework.mybatis.config.MybatisConfiguration; | 4 | import cn.iocoder.dashboard.framework.mybatis.config.MybatisConfiguration; |
| 5 | import cn.iocoder.dashboard.framework.redis.config.RedisConfig; | 5 | import cn.iocoder.dashboard.framework.redis.config.RedisConfig; |
| 6 | -import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure; | 6 | +import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration; |
| 7 | import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration; | 7 | import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration; |
| 8 | import org.redisson.spring.starter.RedissonAutoConfiguration; | 8 | import org.redisson.spring.starter.RedissonAutoConfiguration; |
| 9 | import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; | 9 | import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; |
| @@ -19,13 +19,14 @@ public class BaseDbAndRedisIntegrationTest { | @@ -19,13 +19,14 @@ public class BaseDbAndRedisIntegrationTest { | ||
| 19 | 19 | ||
| 20 | @Import({ | 20 | @Import({ |
| 21 | // DB 配置类 | 21 | // DB 配置类 |
| 22 | + DynamicDataSourceAutoConfiguration.class, // Dynamic Datasource 配置类 | ||
| 22 | DataSourceConfiguration.class, // 自己的 DB 配置类 | 23 | DataSourceConfiguration.class, // 自己的 DB 配置类 |
| 23 | DataSourceAutoConfiguration.class, // Spring DB 自动配置类 | 24 | DataSourceAutoConfiguration.class, // Spring DB 自动配置类 |
| 24 | DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类 | 25 | DataSourceTransactionManagerAutoConfiguration.class, // Spring 事务自动配置类 |
| 25 | - DruidDataSourceAutoConfigure.class, // Druid 自动配置类 | ||
| 26 | // MyBatis 配置类 | 26 | // MyBatis 配置类 |
| 27 | MybatisConfiguration.class, // 自己的 MyBatis 配置类 | 27 | MybatisConfiguration.class, // 自己的 MyBatis 配置类 |
| 28 | MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类 | 28 | MybatisPlusAutoConfiguration.class, // MyBatis 的自动配置类 |
| 29 | + | ||
| 29 | // Redis 配置类 | 30 | // Redis 配置类 |
| 30 | RedisAutoConfiguration.class, // Spring Redis 自动配置类 | 31 | RedisAutoConfiguration.class, // Spring Redis 自动配置类 |
| 31 | RedisConfig.class, // 自己的 Redis 配置类 | 32 | RedisConfig.class, // 自己的 Redis 配置类 |
src/test-integration/java/cn/iocoder/dashboard/modules/tool/dal/mysql/codegen/ToolInformationSchemaTableMapperTest.java
| 1 | package cn.iocoder.dashboard.modules.tool.dal.mysql.codegen; | 1 | package cn.iocoder.dashboard.modules.tool.dal.mysql.codegen; |
| 2 | 2 | ||
| 3 | import cn.iocoder.dashboard.BaseDbUnitTest; | 3 | import cn.iocoder.dashboard.BaseDbUnitTest; |
| 4 | -import cn.iocoder.dashboard.modules.tool.dal.dataobject.codegen.ToolSchemaTableDO; | ||
| 5 | -import org.junit.jupiter.api.Test; | ||
| 6 | 4 | ||
| 7 | import javax.annotation.Resource; | 5 | import javax.annotation.Resource; |
| 8 | -import java.util.List; | ||
| 9 | - | ||
| 10 | -import static org.junit.jupiter.api.Assertions.assertTrue; | ||
| 11 | 6 | ||
| 12 | class ToolInformationSchemaTableMapperTest extends BaseDbUnitTest { | 7 | class ToolInformationSchemaTableMapperTest extends BaseDbUnitTest { |
| 13 | 8 | ||
| 14 | @Resource | 9 | @Resource |
| 15 | private ToolSchemaTableMapper toolInformationSchemaTableMapper; | 10 | private ToolSchemaTableMapper toolInformationSchemaTableMapper; |
| 16 | 11 | ||
| 17 | - @Test | ||
| 18 | - public void tstSelectListByTableSchema() { | ||
| 19 | - List<ToolSchemaTableDO> tables = toolInformationSchemaTableMapper | ||
| 20 | - .selectListByTableSchema("ruoyi-vue-pro"); | ||
| 21 | - assertTrue(tables.size() > 0); | ||
| 22 | - } | ||
| 23 | - | ||
| 24 | } | 12 | } |
src/test-integration/resources/application-integration-test.yaml
| @@ -7,12 +7,55 @@ spring: | @@ -7,12 +7,55 @@ spring: | ||
| 7 | 7 | ||
| 8 | spring: | 8 | spring: |
| 9 | # 数据源配置项 | 9 | # 数据源配置项 |
| 10 | + autoconfigure: | ||
| 11 | + exclude: | ||
| 12 | + - com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源 | ||
| 10 | datasource: | 13 | datasource: |
| 11 | - name: ruoyi-vue-pro | ||
| 12 | - url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.name}?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT | ||
| 13 | - driver-class-name: com.mysql.jdbc.Driver | ||
| 14 | - username: root | ||
| 15 | - password: 123456 | 14 | + druid: # Druid 【监控】相关的全局配置 |
| 15 | + web-stat-filter: | ||
| 16 | + enabled: true | ||
| 17 | + stat-view-servlet: | ||
| 18 | + enabled: true | ||
| 19 | + allow: # 设置白名单,不填则允许所有访问 | ||
| 20 | + url-pattern: /druid/* | ||
| 21 | + login-username: # 控制台管理用户名和密码 | ||
| 22 | + login-password: | ||
| 23 | + filter: | ||
| 24 | + stat: | ||
| 25 | + enabled: true | ||
| 26 | + log-slow-sql: true # 慢 SQL 记录 | ||
| 27 | + slow-sql-millis: 100 | ||
| 28 | + merge-sql: true | ||
| 29 | + wall: | ||
| 30 | + config: | ||
| 31 | + multi-statement-allow: true | ||
| 32 | + dynamic: # 多数据源配置 | ||
| 33 | + druid: # Druid 【连接池】相关的全局配置 | ||
| 34 | + initial-size: 5 # 初始连接数 | ||
| 35 | + min-idle: 10 # 最小连接池数量 | ||
| 36 | + max-active: 20 # 最大连接池数量 | ||
| 37 | + max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 | ||
| 38 | + time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 | ||
| 39 | + min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 | ||
| 40 | + max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 | ||
| 41 | + validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 | ||
| 42 | + test-while-idle: true | ||
| 43 | + test-on-borrow: false | ||
| 44 | + test-on-return: false | ||
| 45 | + primary: master | ||
| 46 | + datasource: | ||
| 47 | + master: | ||
| 48 | + name: ruoyi-vue-pro | ||
| 49 | + url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT | ||
| 50 | + driver-class-name: com.mysql.jdbc.Driver | ||
| 51 | + username: root | ||
| 52 | + password: 123456 | ||
| 53 | + slave: # 模拟从库,可根据自己需要修改 | ||
| 54 | + name: ruoyi-vue-pro | ||
| 55 | + url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT | ||
| 56 | + driver-class-name: com.mysql.jdbc.Driver | ||
| 57 | + username: root | ||
| 58 | + password: 123456 | ||
| 16 | 59 | ||
| 17 | # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 | 60 | # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 |
| 18 | redis: | 61 | redis: |
| @@ -70,7 +113,7 @@ yudao: | @@ -70,7 +113,7 @@ yudao: | ||
| 70 | base-path: http://127.0.0.1:${server.port}/${yudao.web.api-prefix}/file/get/ | 113 | base-path: http://127.0.0.1:${server.port}/${yudao.web.api-prefix}/file/get/ |
| 71 | codegen: | 114 | codegen: |
| 72 | base-package: ${yudao.info.base-package}.modules | 115 | base-package: ${yudao.info.base-package}.modules |
| 73 | - db-schemas: ${spring.datasource.name} | 116 | + db-schemas: ${spring.datasource.dynamic.datasource.master.name} |
| 74 | xss: | 117 | xss: |
| 75 | enable: false | 118 | enable: false |
| 76 | exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系 | 119 | exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系 |