diff --git a/.gitee/ISSUE_TEMPLATE.zh-CN.md b/.gitee/ISSUE_TEMPLATE.zh-CN.md index 22cb51d52..b6fcbea86 100644 --- a/.gitee/ISSUE_TEMPLATE.zh-CN.md +++ b/.gitee/ISSUE_TEMPLATE.zh-CN.md @@ -1,4 +1,4 @@ -### 使用版本 +### 使用版本(未按照模板填写直接删除) ### 问题描述 diff --git a/README.md b/README.md index d6a2409a5..203a03dbc 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,8 @@ [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/blob/master/LICENSE) [![使用IntelliJ IDEA开发维护](https://img.shields.io/badge/IntelliJ%20IDEA-提供支持-blue.svg)](https://www.jetbrains.com/?from=RuoYi-Vue-Plus)
-[![RuoYi-Vue-Plus](https://img.shields.io/badge/RuoYi_Vue_Plus-4.0.1-success.svg)](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus) -[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-2.5-blue.svg)]() +[![RuoYi-Vue-Plus](https://img.shields.io/badge/RuoYi_Vue_Plus-4.1.0-success.svg)](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus) +[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-2.6-blue.svg)]() [![JDK-8+](https://img.shields.io/badge/JDK-8-green.svg)]() [![JDK-11](https://img.shields.io/badge/JDK-11-green.svg)]() @@ -25,6 +25,9 @@ | 容器框架 | Undertow | [Undertow官网](https://undertow.io/) | 基于 XNIO 的高性能容器 | | 权限认证框架 | Sa-Token、Jwt | [Sa-Token官网](https://sa-token.dev33.cn/) | 强解耦、强扩展 | | 关系数据库 | MySQL | [MySQL官网](https://dev.mysql.com/) | 适配 8.X 最低 5.7 | +| 关系数据库 | Oracle | [Oracle官网](https://www.oracle.com/cn/database/) | 适配 11g 12c | +| 关系数据库 | PostgreSQL | [PostgreSQL官网](https://www.postgresql.org/) | 适配 13 14 | +| 关系数据库 | SQLServer | [SQLServer官网](https://docs.microsoft.com/zh-cn/sql/sql-server) | 适配 2017 2019 | | 缓存数据库 | Redis | [Redis官网](https://redis.io/) | 适配 6.X 最低 4.X | | 数据库框架 | Mybatis-Plus | [Mybatis-Plus文档](https://baomidou.com/guide/) | 快速 CRUD 增加开发效率 | | 数据库框架 | p6spy | [p6spy官网](https://p6spy.readthedocs.io/) | 更强劲的 SQL 分析 | diff --git a/pom.xml b/pom.xml index b0c52d5fe..4fc098f5b 100644 --- a/pom.xml +++ b/pom.xml @@ -6,46 +6,49 @@ com.ruoyi ruoyi-vue-plus - 4.0.1 + 4.1.0 RuoYi-Vue-Plus https://gitee.com/JavaLionLi/RuoYi-Vue-Plus RuoYi-Vue-Plus后台管理系统 - 4.0.1 - 2.6.4 + 4.1.0 + 2.6.7 UTF-8 UTF-8 1.8 3.2.2 + 2.2.0 1.2.8 3.0.3 1.5.22 4.1.2 + 1.21 3.0.5 - 3.3.0 2.3 1.29.0 3.5.1 3.9.1 - 5.7.21 - 4.9.2 - 2.6.2 - 3.16.8 + 5.7.22 + 4.9.3 + 2.6.6 + 3.17.0 2.2.1 - 3.5.0 + 3.5.1 1.3.6 2.3.0 3.0.1 + + 30.0-jre - 7.9.3 + 7.9.5 3.14.0 - 5.6.68 - 8.3.7 + 5.6.72 + 8.3.8 localhost @@ -109,6 +112,13 @@ ${poi.version} + + + org.apache.commons + commons-compress + ${commons-compress.version} + + com.alibaba easyexcel @@ -125,12 +135,6 @@ - - cglib - cglib - ${cglib.version} - - org.apache.velocity @@ -222,6 +226,20 @@ com.yomahub tlog-web-spring-boot-starter ${tlog.version} + + + log4j + log4j + + + dom4j + dom4j + + + commons-beanutils + commons-beanutils + + @@ -230,6 +248,13 @@ ${tlog.version} + + + com.google.guava + guava + ${guava.version} + + com.ruoyi diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml index 1c8c759e9..411d3b9aa 100644 --- a/ruoyi-admin/pom.xml +++ b/ruoyi-admin/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.0.1 + 4.1.0 4.0.0 jar @@ -29,6 +29,21 @@ mysql mysql-connector-java + + + com.oracle.database.jdbc + ojdbc8 + + + + org.postgresql + postgresql + + + + com.microsoft.sqlserver + mssql-jdbc + diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java index fad8b5bf3..facf6ce99 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java @@ -7,6 +7,7 @@ import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.entity.SysMenu; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.model.LoginBody; +import com.ruoyi.common.core.domain.model.SmsLoginBody; import com.ruoyi.common.helper.LoginHelper; import com.ruoyi.system.domain.vo.RouterVo; import com.ruoyi.system.service.ISysMenuService; @@ -22,6 +23,7 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; +import javax.validation.constraints.NotBlank; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -60,6 +62,38 @@ public class SysLoginController { return R.ok(ajax); } + /** + * 短信登录(示例) + * + * @param smsLoginBody 登录信息 + * @return 结果 + */ + @ApiOperation("短信登录(示例)") + @PostMapping("/smsLogin") + public R> smsLogin(@Validated @RequestBody SmsLoginBody smsLoginBody) { + Map ajax = new HashMap<>(); + // 生成令牌 + String token = loginService.smsLogin(smsLoginBody.getPhonenumber(), smsLoginBody.getSmsCode()); + ajax.put(Constants.TOKEN, token); + return R.ok(ajax); + } + + /** + * 小程序登录(示例) + * + * @param xcxCode 小程序code + * @return 结果 + */ + @ApiOperation("小程序登录(示例)") + @PostMapping("/xcxLogin") + public R> xcxLogin(@NotBlank(message = "{xcx.code.not.blank}") String xcxCode) { + Map ajax = new HashMap<>(); + // 生成令牌 + String token = loginService.xcxLogin(xcxCode); + ajax.put(Constants.TOKEN, token); + return R.ok(ajax); + } + @ApiOperation("登出方法") @PostMapping("/logout") public R logout() { diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssConfigController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssConfigController.java index e344dea98..cf2fd1178 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssConfigController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssConfigController.java @@ -59,7 +59,7 @@ public class SysOssConfigController extends BaseController { @GetMapping("/{ossConfigId}") public R getInfo(@ApiParam("OSS配置ID") @NotNull(message = "主键不能为空") - @PathVariable("ossConfigId") Integer ossConfigId) { + @PathVariable("ossConfigId") Long ossConfigId) { return R.ok(iSysOssConfigService.queryById(ossConfigId)); } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssController.java index 4342716f7..a128a15ff 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssController.java @@ -18,7 +18,6 @@ import com.ruoyi.common.utils.file.FileUtils; import com.ruoyi.system.domain.SysOss; import com.ruoyi.system.domain.bo.SysOssBo; import com.ruoyi.system.domain.vo.SysOssVo; -import com.ruoyi.system.service.ISysConfigService; import com.ruoyi.system.service.ISysOssService; import io.swagger.annotations.*; import lombok.RequiredArgsConstructor; @@ -48,7 +47,6 @@ import java.util.Map; public class SysOssController extends BaseController { private final ISysOssService iSysOssService; - private final ISysConfigService iSysConfigService; /** * 查询OSS对象存储列表 @@ -77,7 +75,8 @@ public class SysOssController extends BaseController { SysOss oss = iSysOssService.upload(file); Map map = new HashMap<>(2); map.put("url", oss.getUrl()); - map.put("fileName", oss.getFileName()); + map.put("fileName", oss.getOriginalName()); + map.put("ossId", oss.getOssId().toString()); return R.ok(map); } diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml index ba38be663..45eb5be97 100644 --- a/ruoyi-admin/src/main/resources/application-dev.yml +++ b/ruoyi-admin/src/main/resources/application-dev.yml @@ -1,41 +1,34 @@ ---- # 监控配置 -spring: - boot: - admin: - # Spring Boot Admin Client 客户端的相关配置 - client: - # 增加客户端开关 - enabled: true - # 设置 Spring Boot Admin Server 地址 - url: http://localhost:9090/admin - instance: - service-host-type: IP - username: ruoyi - password: 123456 +--- # 监控中心配置 +spring.boot.admin.client: + # 增加客户端开关 + enabled: true + url: http://localhost:9090/admin + instance: + service-host-type: IP + username: ruoyi + password: 123456 --- # xxl-job 配置 -xxl: - job: - # 执行器开关 - enabled: true - # 调度中心地址:如调度中心集群部署存在多个地址则用逗号分隔。 - admin-addresses: http://localhost:9100/xxl-job-admin - # 执行器通讯TOKEN:非空时启用 - access-token: xxl-job - # 执行器配置 - executor: - # 执行器AppName:执行器心跳注册分组依据;为空则关闭自动注册 - appname: xxl-job-executor - # 执行器端口号 执行器从9101开始往后写 - port: 9101 - # 执行器注册:默认IP:PORT - address: - # 执行器IP:默认自动获取IP - ip: - # 执行器运行日志文件存储磁盘路径 - logpath: ./logs/xxl-job - # 执行器日志文件保存天数:大于3生效 - logretentiondays: 30 +xxl.job: + # 执行器开关 + enabled: true + # 调度中心地址:如调度中心集群部署存在多个地址则用逗号分隔。 + admin-addresses: http://localhost:9100/xxl-job-admin + # 执行器通讯TOKEN:非空时启用 + access-token: xxl-job + executor: + # 执行器AppName:执行器心跳注册分组依据;为空则关闭自动注册 + appname: xxl-job-executor + # 执行器端口号 执行器从9101开始往后写 + port: 9101 + # 执行器注册:默认IP:PORT + address: + # 执行器IP:默认自动获取IP + ip: + # 执行器运行日志文件存储磁盘路径 + logpath: ./logs/xxl-job + # 执行器日志文件保存天数:大于3生效 + logretentiondays: 30 --- # 数据源配置 spring: @@ -47,6 +40,8 @@ spring: p6spy: true # 设置默认的数据源或者数据源组,默认值即为 master primary: master + # 严格模式 匹配不到数据源则报错 + strict: true datasource: # 主库数据源 master: @@ -63,6 +58,23 @@ spring: url: username: password: +# oracle: +# driverClassName: oracle.jdbc.OracleDriver +# url: jdbc:oracle:thin:@//localhost:1521/XE +# username: ROOT +# password: root +# druid: +# validationQuery: SELECT 1 FROM DUAL +# postgres: +# driverClassName: org.postgresql.Driver +# url: jdbc:postgresql://localhost:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true +# username: root +# password: root +# sqlserver: +# driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver +# url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;rewriteBatchedStatements=true +# username: SA +# password: root druid: # 初始连接数 initialSize: 5 @@ -79,7 +91,7 @@ spring: # 配置一个连接在池中最大生存的时间,单位是毫秒 maxEvictableIdleTimeMillis: 900000 # 配置检测连接是否有效 - validationQuery: SELECT 1 FROM DUAL + validationQuery: SELECT 1 testWhileIdle: true testOnBorrow: false testOnReturn: false @@ -87,29 +99,27 @@ spring: filters: stat --- # druid 配置 -spring: - datasource: - druid: - webStatFilter: - enabled: 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 +spring.datasource.druid: + webStatFilter: + enabled: 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 单机配置(单机与集群只能开启一个另一个需要注释掉) spring: @@ -132,8 +142,6 @@ redisson: threads: 4 # Netty线程池数量 nettyThreads: 8 - # 传输模式 - transportMode: "NIO" # 单节点配置 singleServerConfig: # 客户端名称 @@ -146,9 +154,5 @@ redisson: idleConnectionTimeout: 10000 # 命令等待超时,单位:毫秒 timeout: 3000 - # 如果尝试在此限制之内发送成功,则开始启用 timeout 计时。 - retryAttempts: 3 - # 命令重试发送时间间隔,单位:毫秒 - retryInterval: 1500 # 发布和订阅连接池大小 subscriptionConnectionPoolSize: 50 diff --git a/ruoyi-admin/src/main/resources/application-prod.yml b/ruoyi-admin/src/main/resources/application-prod.yml index 493ce547f..6a28bccfb 100644 --- a/ruoyi-admin/src/main/resources/application-prod.yml +++ b/ruoyi-admin/src/main/resources/application-prod.yml @@ -1,48 +1,37 @@ ---- # 配置临时路径存储 -spring: - servlet: - multipart: - # 临时文件存储位置 避免临时文件被系统清理报错 - location: /ruoyi/server/temp +--- # 临时文件存储位置 避免临时文件被系统清理报错 +spring.servlet.multipart.location: /ruoyi/server/temp ---- # 监控配置 -spring: - boot: - admin: - # Spring Boot Admin Client 客户端的相关配置 - client: - # 增加客户端开关 - enabled: true - # 设置 Spring Boot Admin Server 地址 - url: http://172.30.0.90:9090/admin - instance: - service-host-type: IP - username: ruoyi - password: 123456 +--- # 监控中心配置 +spring.boot.admin.client: + # 增加客户端开关 + enabled: true + url: http://172.30.0.90:9090/admin + instance: + service-host-type: IP + username: ruoyi + password: 123456 --- # xxl-job 配置 -xxl: - job: - # 执行器开关 - enabled: true - # 调度中心地址:如调度中心集群部署存在多个地址则用逗号分隔。 - admin-addresses: http://172.30.0.92:9100/xxl-job-admin - # 执行器通讯TOKEN:非空时启用 - access-token: xxl-job - # 执行器配置 - executor: - # 执行器AppName:执行器心跳注册分组依据;为空则关闭自动注册 - appname: xxl-job-executor - # 执行器端口号 执行器从9101开始往后写 - port: 9101 - # 执行器注册:默认IP:PORT - address: - # 执行器IP:默认自动获取IP - ip: - # 执行器运行日志文件存储磁盘路径 - logpath: ./logs/xxl-job - # 执行器日志文件保存天数:大于3生效 - logretentiondays: 30 +xxl.job: + # 执行器开关 + enabled: true + # 调度中心地址:如调度中心集群部署存在多个地址则用逗号分隔。 + admin-addresses: http://172.30.0.92:9100/xxl-job-admin + # 执行器通讯TOKEN:非空时启用 + access-token: xxl-job + executor: + # 执行器AppName:执行器心跳注册分组依据;为空则关闭自动注册 + appname: xxl-job-executor + # 执行器端口号 执行器从9101开始往后写 + port: 9101 + # 执行器注册:默认IP:PORT + address: + # 执行器IP:默认自动获取IP + ip: + # 执行器运行日志文件存储磁盘路径 + logpath: ./logs/xxl-job + # 执行器日志文件保存天数:大于3生效 + logretentiondays: 30 --- # 数据源配置 spring: @@ -54,6 +43,8 @@ spring: p6spy: false # 设置默认的数据源或者数据源组,默认值即为 master primary: master + # 严格模式 匹配不到数据源则报错 + strict: true datasource: # 主库数据源 master: @@ -70,6 +61,23 @@ spring: url: username: password: +# oracle: +# driverClassName: oracle.jdbc.OracleDriver +# url: jdbc:oracle:thin:@//172.30.0.36:1521/XE +# username: ROOT +# password: root +# druid: +# validationQuery: SELECT 1 FROM DUAL +# postgres: +# driverClassName: org.postgresql.Driver +# url: jdbc:postgresql://172.30.0.36:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true +# username: root +# password: root +# sqlserver: +# driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver +# url: jdbc:sqlserver://172.30.0.36:1433;DatabaseName=tempdb;SelectMethod=cursor;rewriteBatchedStatements=true +# username: SA +# password: root druid: # 初始连接数 initialSize: 5 @@ -86,7 +94,7 @@ spring: # 配置一个连接在池中最大生存的时间,单位是毫秒 maxEvictableIdleTimeMillis: 900000 # 配置检测连接是否有效 - validationQuery: SELECT 1 FROM DUAL + validationQuery: SELECT 1 testWhileIdle: true testOnBorrow: false testOnReturn: false @@ -94,29 +102,27 @@ spring: filters: stat --- # druid 配置 -spring: - datasource: - druid: - webStatFilter: - enabled: 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 +spring.datasource.druid: + webStatFilter: + enabled: 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 单机配置(单机与集群只能开启一个另一个需要注释掉) spring: @@ -139,8 +145,6 @@ redisson: threads: 16 # Netty线程池数量 nettyThreads: 32 - # 传输模式 - transportMode: "NIO" # 单节点配置 singleServerConfig: # 客户端名称 @@ -153,9 +157,5 @@ redisson: idleConnectionTimeout: 10000 # 命令等待超时,单位:毫秒 timeout: 3000 - # 如果尝试在此限制之内发送成功,则开始启用 timeout 计时。 - retryAttempts: 3 - # 命令重试发送时间间隔,单位:毫秒 - retryInterval: 1500 # 发布和订阅连接池大小 subscriptionConnectionPoolSize: 50 diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 8c0b6e432..c692fc267 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -75,10 +75,6 @@ spring: restart: # 热部署开关 enabled: true - # 与vue整合部署使用 - thymeleaf: - # 将系统模板放置到最前面 否则会与 springboot-admin 页面冲突 - template-resolver-order: 1 mvc: pathmatch: # 适配 boot 2.6 路由与 springfox 兼容 @@ -107,16 +103,12 @@ sa-token: is-concurrent: true # 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token) is-share: false - # 是否尝试从请求体里读取token - is-read-body: false # 是否尝试从header里读取token is-read-head: true # 是否尝试从cookie里读取token is-read-cookie: false # token前缀 token-prefix: "Bearer" - # token风格 - token-style: uuid # jwt秘钥 jwt-secret-key: abcdefghijklmnopqrstuvwxyz # 是否输出操作日志 @@ -127,6 +119,8 @@ security: # 排除路径 excludes: - /login + - /smsLogin + - /xcxLogin - /logout - /register - /captchaImage @@ -136,23 +130,17 @@ security: - /**/*.css - /**/*.js # swagger 文档配置 + - /favicon.ico - /doc.html - /swagger-resources/** - /webjars/** - /*/api-docs # druid 监控配置 - /druid/** - # 用户放行 - permit-all: # actuator 监控配置 - /actuator - /actuator/** -# 重复提交 -repeat-submit: - # 全局间隔时间(毫秒) - interval: 5000 - # MyBatisPlus配置 # https://baomidou.com/config/ mybatis-plus: @@ -165,25 +153,15 @@ mybatis-plus: typeAliasesPackage: com.ruoyi.**.domain # 启动时是否检查 MyBatis XML 文件的存在,默认不检查 checkConfigLocation: false - # 通过该属性可指定 MyBatis 的执行器,MyBatis 的执行器总共有三种: - # SIMPLE:每个语句创建新的预处理器 REUSE:会复用预处理器 BATCH:批量执行所有的更新 - executorType: SIMPLE configuration: # 自动驼峰命名规则(camel case)映射 mapUnderscoreToCamelCase: true - # 当设置为 true 的时候,懒加载的对象可能被任何懒属性全部加载,否则,每个属性都按需加载。需要和 lazyLoadingEnabled 一起使用。 - aggressiveLazyLoading: true # MyBatis 自动映射策略 # NONE:不启用 PARTIAL:只对非嵌套 resultMap 自动映射 FULL:对所有 resultMap 自动映射 autoMappingBehavior: PARTIAL # MyBatis 自动映射时未知列或未知属性处理策 # NONE:不做处理 WARNING:打印相关警告 FAILING:抛出异常和详细信息 autoMappingUnknownColumnBehavior: NONE - # Mybatis一级缓存,默认为 SESSION - # SESSION session级别缓存 STATEMENT 关闭一级缓存 - localCacheScope: SESSION - # 开启Mybatis二级缓存,默认为 true - cacheEnabled: false # 更详细的日志输出 会有性能损耗 org.apache.ibatis.logging.stdout.StdOutImpl # 关闭日志记录 (可单纯使用 p6spy 分析) org.apache.ibatis.logging.nologging.NoLoggingImpl # 默认日志输出 org.apache.ibatis.logging.slf4j.Slf4jImpl @@ -191,16 +169,10 @@ mybatis-plus: global-config: # 是否打印 Logo banner banner: true - # 是否初始化 SqlRunner - enableSqlRunner: false dbConfig: # 主键类型 # AUTO 自增 NONE 空 INPUT 用户输入 ASSIGN_ID 雪花 ASSIGN_UUID 唯一 UUID - idType: AUTO - # 表名是否使用驼峰转下划线命名,只对表名生效 - tableUnderline: true - # 大写命名,对表名和字段名均生效 - capitalMode: false + idType: ASSIGN_ID # 逻辑已删除值 logicDeleteValue: 2 # 逻辑未删除值 @@ -271,20 +243,10 @@ xss: thread-pool: # 是否开启线程池 enabled: false - # 核心线程池大小 - corePoolSize: 8 - # 最大可创建的线程数 - maxPoolSize: 16 # 队列最大长度 queueCapacity: 128 # 线程池维护线程所允许的空闲时间 keepAliveSeconds: 300 - # 线程池对拒绝任务(无线程可用)的处理策略 - # CALLER_RUNS_POLICY 调用方执行 - # DISCARD_OLDEST_POLICY 放弃最旧的 - # DISCARD_POLICY 丢弃 - # ABORT_POLICY 中止 - rejectedExecutionHandler: CALLER_RUNS_POLICY --- # redisson 缓存配置 redisson: @@ -312,8 +274,6 @@ lock4j: management: endpoints: web: - # Actuator 提供的 API 接口的根目录。默认为 /actuator - base-path: /actuator exposure: # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。 # 生产环境不建议放开所有 根据项目需求放开即可 diff --git a/ruoyi-admin/src/main/resources/i18n/messages.properties b/ruoyi-admin/src/main/resources/i18n/messages.properties index ee68c98c1..ac1d8c230 100644 --- a/ruoyi-admin/src/main/resources/i18n/messages.properties +++ b/ruoyi-admin/src/main/resources/i18n/messages.properties @@ -18,6 +18,7 @@ user.password.not.blank=用户密码不能为空 user.password.length.valid=用户密码长度必须在{min}到{max}个字符之间 user.password.not.valid=* 5-50个字符 user.email.not.valid=邮箱格式错误 +user.phonenumber.not.blank=用户手机号不能为空 user.mobile.phone.number.not.valid=手机号格式错误 user.login.success=登录成功 user.register.success=注册成功 @@ -36,3 +37,9 @@ no.update.permission=您没有修改数据的权限,请联系管理员添加 no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}] no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}] no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}] +repeat.submit.message=不允许重复提交,请稍候再试 +rate.limiter.message=访问过于频繁,请稍候再试 +sms.code.not.blank=短信验证码不能为空 +sms.code.retry.limit.count=短信验证码输入错误{0}次 +sms.code.retry.limit.exceed=短信验证码错误次数过多,帐户锁定{0}分钟 +xcx.code.not.blank=小程序code不能为空 diff --git a/ruoyi-admin/src/main/resources/i18n/messages_en_US.properties b/ruoyi-admin/src/main/resources/i18n/messages_en_US.properties index 960538a55..9076f79f7 100644 --- a/ruoyi-admin/src/main/resources/i18n/messages_en_US.properties +++ b/ruoyi-admin/src/main/resources/i18n/messages_en_US.properties @@ -18,6 +18,7 @@ user.password.not.blank=Password cannot be empty user.password.length.valid=Password length must be between {min} and {max} characters user.password.not.valid=* 5-50 characters user.email.not.valid=Mailbox format error +user.phonenumber.not.blank=Phone number cannot be blank user.mobile.phone.number.not.valid=Phone number format error user.login.success=Login successful user.register.success=Register successful @@ -36,3 +37,9 @@ no.update.permission=You do not have permission to modify data,please contact no.delete.permission=You do not have permission to delete data,please contact your administrator to add permissions [{0}] no.export.permission=You do not have permission to export data,please contact your administrator to add permissions [{0}] no.view.permission=You do not have permission to view data,please contact your administrator to add permissions [{0}] +repeat.submit.message=Repeat submit is not allowed, please try again later +rate.limiter.message=Visit too frequently, please try again later +sms.code.not.blank=Sms code cannot be blank +sms.code.retry.limit.count=Sms code input error {0} times +sms.code.retry.limit.exceed=Too many sms code errors, account locked for {0} minutes +xcx.code.not.blank=Mini program code cannot be blank diff --git a/ruoyi-admin/src/main/resources/i18n/messages_zh_CN.properties b/ruoyi-admin/src/main/resources/i18n/messages_zh_CN.properties index ee68c98c1..ac1d8c230 100644 --- a/ruoyi-admin/src/main/resources/i18n/messages_zh_CN.properties +++ b/ruoyi-admin/src/main/resources/i18n/messages_zh_CN.properties @@ -18,6 +18,7 @@ user.password.not.blank=用户密码不能为空 user.password.length.valid=用户密码长度必须在{min}到{max}个字符之间 user.password.not.valid=* 5-50个字符 user.email.not.valid=邮箱格式错误 +user.phonenumber.not.blank=用户手机号不能为空 user.mobile.phone.number.not.valid=手机号格式错误 user.login.success=登录成功 user.register.success=注册成功 @@ -36,3 +37,9 @@ no.update.permission=您没有修改数据的权限,请联系管理员添加 no.delete.permission=您没有删除数据的权限,请联系管理员添加权限 [{0}] no.export.permission=您没有导出数据的权限,请联系管理员添加权限 [{0}] no.view.permission=您没有查看数据的权限,请联系管理员添加权限 [{0}] +repeat.submit.message=不允许重复提交,请稍候再试 +rate.limiter.message=访问过于频繁,请稍候再试 +sms.code.not.blank=短信验证码不能为空 +sms.code.retry.limit.count=短信验证码输入错误{0}次 +sms.code.retry.limit.exceed=短信验证码错误次数过多,帐户锁定{0}分钟 +xcx.code.not.blank=小程序code不能为空 diff --git a/ruoyi-admin/src/main/resources/logback.xml b/ruoyi-admin/src/main/resources/logback.xml index e8d627531..4d6b910d3 100644 --- a/ruoyi-admin/src/main/resources/logback.xml +++ b/ruoyi-admin/src/main/resources/logback.xml @@ -77,6 +77,26 @@ + + + + 0 + + 512 + + + + + + + + 0 + + 512 + + + + @@ -88,8 +108,8 @@ - - + + diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml index 81a983f99..bb476cbdd 100644 --- a/ruoyi-common/pom.xml +++ b/ruoyi-common/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.0.1 + 4.1.0 4.0.0 @@ -69,11 +69,6 @@ easyexcel - - cglib - cglib - - org.yaml diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java index a87466768..d30962d0e 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java @@ -22,8 +22,8 @@ public @interface RepeatSubmit { TimeUnit timeUnit() default TimeUnit.MILLISECONDS; /** - * 提示消息 + * 提示消息 支持国际化 格式为 {code} */ - String message() default "不允许重复提交,请稍候再试"; + String message() default "{repeat.submit.message}"; } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java index 5e07c96c0..e2ffebdc0 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java @@ -65,12 +65,12 @@ public interface Constants { /** * 登录用户 redis key */ - public static final String LOGIN_TOKEN_KEY = "Authorization:login:token:"; + String LOGIN_TOKEN_KEY = "Authorization:login:token:"; /** * 在线用户 redis key */ - public static final String ONLINE_TOKEN_KEY = "online_tokens:"; + String ONLINE_TOKEN_KEY = "online_tokens:"; /** * 防重提交 redis key diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java index 406d14413..9f800be2f 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java @@ -22,11 +22,21 @@ public interface UserConstants { */ String EXCEPTION = "1"; + /** + * 用户正常状态 + */ + String USER_NORMAL = "0"; + /** * 用户封禁状态 */ String USER_DISABLE = "1"; + /** + * 角色正常状态 + */ + String ROLE_NORMAL = "0"; + /** * 角色封禁状态 */ @@ -62,6 +72,16 @@ public interface UserConstants { */ String NO_FRAME = "1"; + /** + * 菜单正常状态 + */ + String MENU_NORMAL = "0"; + + /** + * 菜单停用状态 + */ + String MENU_DISABLE = "1"; + /** * 菜单类型(目录) */ diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java index 5e7af7398..f44eacd49 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java @@ -16,7 +16,7 @@ import java.util.List; @Data @EqualsAndHashCode(callSuper = true) -public class TreeEntity extends BaseEntity { +public class TreeEntity extends BaseEntity { private static final long serialVersionUID = 1L; @@ -38,6 +38,6 @@ public class TreeEntity extends BaseEntity { */ @TableField(exist = false) @ApiModelProperty(value = "子部门") - private List children = new ArrayList<>(); + private List children = new ArrayList<>(); } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java index 46e99368c..2dc3bdc40 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java @@ -24,7 +24,7 @@ import javax.validation.constraints.Size; @EqualsAndHashCode(callSuper = true) @TableName("sys_dept") @ApiModel("部门业务对象") -public class SysDept extends TreeEntity { +public class SysDept extends TreeEntity { private static final long serialVersionUID = 1L; /** @@ -47,7 +47,7 @@ public class SysDept extends TreeEntity { */ @ApiModelProperty(value = "显示顺序") @NotNull(message = "显示顺序不能为空") - private Long orderNum; + private Integer orderNum; /** * 负责人 diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java index dc7f0512f..c61c91726 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java @@ -42,7 +42,7 @@ public class SysDictData extends BaseEntity { */ @ApiModelProperty(value = "字典排序") @ExcelProperty(value = "字典排序") - private Long dictSort; + private Integer dictSort; /** * 字典标签 diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java index 082a5bee7..942c2f97b 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java @@ -14,6 +14,7 @@ import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; import javax.validation.constraints.Size; /** @@ -53,6 +54,7 @@ public class SysDictType extends BaseEntity { @ExcelProperty(value = "字典类型") @NotBlank(message = "字典类型不能为空") @Size(min = 0, max = 100, message = "字典类型类型长度不能超过100个字符") + @Pattern(regexp = "^[a-z][a-z0-9_]*$", message = "字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)") private String dictType; /** diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java index 8eb97d0ee..cf337fbeb 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java @@ -1,8 +1,8 @@ package com.ruoyi.common.core.domain.entity; -import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonInclude; import com.ruoyi.common.core.domain.TreeEntity; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -23,7 +23,7 @@ import javax.validation.constraints.Size; @EqualsAndHashCode(callSuper = true) @TableName("sys_menu") @ApiModel("菜单权限业务对象") -public class SysMenu extends TreeEntity { +public class SysMenu extends TreeEntity { /** * 菜单ID @@ -45,7 +45,7 @@ public class SysMenu extends TreeEntity { */ @ApiModelProperty(value = "显示顺序") @NotNull(message = "显示顺序不能为空") - private Long orderNum; + private Integer orderNum; /** * 路由地址 @@ -65,8 +65,7 @@ public class SysMenu extends TreeEntity { * 路由参数 */ @ApiModelProperty(value = "路由参数") - @TableField("`query`") - private String query; + private String queryParam; /** * 是否为外链(0是 1否) @@ -103,6 +102,7 @@ public class SysMenu extends TreeEntity { * 权限字符串 */ @ApiModelProperty(value = "权限字符串") + @JsonInclude(JsonInclude.Include.NON_NULL) @Size(min = 0, max = 100, message = "权限标识长度不能超过100个字符") private String perms; diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java index 662989efe..804815738 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java @@ -16,6 +16,7 @@ import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; /** @@ -62,8 +63,8 @@ public class SysRole extends BaseEntity { */ @ApiModelProperty(value = "角色排序") @ExcelProperty(value = "角色排序") - @NotBlank(message = "显示顺序不能为空") - private String roleSort; + @NotNull(message = "显示顺序不能为空") + private Integer roleSort; /** * 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限) @@ -77,13 +78,13 @@ public class SysRole extends BaseEntity { * 菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示) */ @ApiModelProperty(value = "菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示)") - private boolean menuCheckStrictly; + private Boolean menuCheckStrictly; /** * 部门树选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示 ) */ @ApiModelProperty(value = "部门树选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示 )") - private boolean deptCheckStrictly; + private Boolean deptCheckStrictly; /** * 角色状态(0正常 1停用) @@ -135,5 +136,4 @@ public class SysRole extends BaseEntity { public boolean isAdmin() { return UserConstants.ADMIN_ID.equals(this.roleId); } - } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/SmsLoginBody.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/SmsLoginBody.java new file mode 100644 index 000000000..f3ef445c5 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/SmsLoginBody.java @@ -0,0 +1,33 @@ +package com.ruoyi.common.core.domain.model; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +/** + * 短信登录对象 + * + * @author Lion Li + */ + +@Data +@ApiModel("短信登录对象") +public class SmsLoginBody { + + /** + * 用户名 + */ + @NotBlank(message = "{user.phonenumber.not.blank}") + @ApiModelProperty(value = "用户手机号") + private String phonenumber; + + /** + * 用户密码 + */ + @NotBlank(message = "{sms.code.not.blank}") + @ApiModelProperty(value = "短信验证码") + private String smsCode; + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/XcxLoginUser.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/XcxLoginUser.java new file mode 100644 index 000000000..83313a0fd --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/XcxLoginUser.java @@ -0,0 +1,24 @@ +package com.ruoyi.common.core.domain.model; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; + +/** + * 小程序登录用户身份权限 + * + * @author Lion Li + */ +@Data +@EqualsAndHashCode(callSuper = true) +@NoArgsConstructor +public class XcxLoginUser extends LoginUser { + + private static final long serialVersionUID = 1L; + + /** + * openid + */ + private String openid; + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataBaseType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataBaseType.java new file mode 100644 index 000000000..5d0f05ad7 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataBaseType.java @@ -0,0 +1,49 @@ +package com.ruoyi.common.enums; + +import com.ruoyi.common.utils.StringUtils; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 数据库类型 + * + * @author Lion Li + */ +@Getter +@AllArgsConstructor +public enum DataBaseType { + + /** + * MySQL + */ + MY_SQL("MySQL"), + + /** + * Oracle + */ + ORACLE("Oracle"), + + /** + * PostgreSQL + */ + POSTGRE_SQL("PostgreSQL"), + + /** + * SQL Server + */ + SQL_SERVER("Microsoft SQL Server"); + + private final String type; + + public static DataBaseType find(String databaseProductName) { + if (StringUtils.isBlank(databaseProductName)) { + return null; + } + for (DataBaseType type : values()) { + if (type.getType().equals(databaseProductName)) { + return type; + } + } + return null; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/DeviceType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DeviceType.java index e6ac849df..118a2128a 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/enums/DeviceType.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DeviceType.java @@ -21,7 +21,12 @@ public enum DeviceType { /** * app端 */ - APP("app"); + APP("app"), + + /** + * 小程序端 + */ + XCX("xcx"); private final String device; } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/LoginType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/LoginType.java new file mode 100644 index 000000000..c91a4b94f --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/LoginType.java @@ -0,0 +1,39 @@ +package com.ruoyi.common.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 登录类型 + * + * @author Lion Li + */ +@Getter +@AllArgsConstructor +public enum LoginType { + + /** + * 密码登录 + */ + PASSWORD("user.password.retry.limit.exceed", "user.password.retry.limit.count"), + + /** + * 短信登录 + */ + SMS("sms.code.retry.limit.exceed", "sms.code.retry.limit.count"), + + /** + * 小程序登录 + */ + XCX("", ""); + + /** + * 登录重试超出限制提示 + */ + final String retryLimitExceed; + + /** + * 登录重试限制计数提示 + */ + final String retryLimitCount; +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/ThreadPoolRejectedPolicy.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/ThreadPoolRejectedPolicy.java deleted file mode 100644 index 5529bb336..000000000 --- a/ruoyi-common/src/main/java/com/ruoyi/common/enums/ThreadPoolRejectedPolicy.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.ruoyi.common.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.concurrent.RejectedExecutionHandler; -import java.util.concurrent.ThreadPoolExecutor; - -/** - * 线程池 拒绝策略 泛型 - * - * @author Lion Li - */ -@Getter -@AllArgsConstructor -public enum ThreadPoolRejectedPolicy { - - CALLER_RUNS_POLICY("调用方执行", ThreadPoolExecutor.CallerRunsPolicy.class), - DISCARD_OLDEST_POLICY("放弃最旧的", ThreadPoolExecutor.DiscardOldestPolicy.class), - DISCARD_POLICY("丢弃", ThreadPoolExecutor.DiscardPolicy.class), - ABORT_POLICY("中止", ThreadPoolExecutor.AbortPolicy.class); - - private final String name; - private final Class clazz; - -} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/helper/DataBaseHelper.java b/ruoyi-common/src/main/java/com/ruoyi/common/helper/DataBaseHelper.java new file mode 100644 index 000000000..196035629 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/helper/DataBaseHelper.java @@ -0,0 +1,72 @@ +package com.ruoyi.common.helper; + +import cn.hutool.core.convert.Convert; +import com.baomidou.dynamic.datasource.DynamicRoutingDataSource; +import com.ruoyi.common.enums.DataBaseType; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.spring.SpringUtils; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.SQLException; + +/** + * 数据库助手 + * + * @author Lion Li + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class DataBaseHelper { + + private static final DynamicRoutingDataSource DS = SpringUtils.getBean(DynamicRoutingDataSource.class); + + /** + * 获取当前数据库类型 + */ + public static DataBaseType getDataBaseType() { + DataSource dataSource = DS.determineDataSource(); + try (Connection conn = dataSource.getConnection()) { + DatabaseMetaData metaData = conn.getMetaData(); + String databaseProductName = metaData.getDatabaseProductName(); + return DataBaseType.find(databaseProductName); + } catch (SQLException e) { + throw new ServiceException(e.getMessage()); + } + } + + public static boolean isMySql() { + return DataBaseType.MY_SQL == getDataBaseType(); + } + + public static boolean isOracle() { + return DataBaseType.ORACLE == getDataBaseType(); + } + + public static boolean isPostgerSql() { + return DataBaseType.POSTGRE_SQL == getDataBaseType(); + } + + public static boolean isSqlServer() { + return DataBaseType.SQL_SERVER == getDataBaseType(); + } + + public static String findInSet(Object var1, String var2) { + DataBaseType dataBasyType = getDataBaseType(); + String var = Convert.toStr(var1); + if (dataBasyType == DataBaseType.SQL_SERVER) { + // charindex(',100,' , ',0,100,101,') <> 0 + return "charindex('," + var + ",' , ','+" + var2 + "+',') <> 0"; + } else if (dataBasyType == DataBaseType.POSTGRE_SQL) { + // (select position(',100,' in ',0,100,101,')) <> 0 + return "(select position('," + var + ",' in ','||" + var2 + "||',')) <> 0"; + } else if (dataBasyType == DataBaseType.ORACLE) { + // instr(',0,100,101,' , ',100,') <> 0 + return "instr(','||" + var2 + "||',' , '," + var + ",') <> 0"; + } + // find_in_set(100 , '0,100,101') + return "find_in_set(" + var + " , " + var2 + ") <> 0"; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/BeanCopyUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/BeanCopyUtils.java index 23ace00f9..93906046d 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/BeanCopyUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/BeanCopyUtils.java @@ -1,15 +1,20 @@ package com.ruoyi.common.utils; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.SimpleCache; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ReflectUtil; -import cn.hutool.extra.cglib.CglibUtil; +import cn.hutool.core.util.StrUtil; import lombok.AccessLevel; import lombok.NoArgsConstructor; +import org.springframework.cglib.beans.BeanCopier; +import org.springframework.cglib.beans.BeanMap; +import org.springframework.cglib.core.Converter; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** * bean深拷贝工具(基于 cglib 性能优异) @@ -37,7 +42,8 @@ public class BeanCopyUtils { if (ObjectUtil.isNull(desc)) { return null; } - return CglibUtil.copy(source, desc); + final V target = ReflectUtil.newInstanceIfPossible(desc); + return copy(source, target); } /** @@ -54,7 +60,8 @@ public class BeanCopyUtils { if (ObjectUtil.isNull(desc)) { return null; } - CglibUtil.copy(source, desc); + BeanCopier beanCopier = BeanCopierCache.INSTANCE.get(source.getClass(), desc.getClass(), null); + beanCopier.copy(source, desc, null); return desc; } @@ -72,7 +79,11 @@ public class BeanCopyUtils { if (CollUtil.isEmpty(sourceList)) { return CollUtil.newArrayList(); } - return CglibUtil.copyList(sourceList, () -> ReflectUtil.newInstanceIfPossible(desc)); + return sourceList.stream().map(source -> { + V target = ReflectUtil.newInstanceIfPossible(desc); + copy(source, target); + return target; + }).collect(Collectors.toList()); } /** @@ -81,11 +92,12 @@ public class BeanCopyUtils { * @param bean 数据来源实体 * @return map对象 */ + @SuppressWarnings("unchecked") public static Map copyToMap(T bean) { if (ObjectUtil.isNull(bean)) { return null; } - return CglibUtil.toMap(bean); + return BeanMap.create(bean); } /** @@ -102,7 +114,8 @@ public class BeanCopyUtils { if (ObjectUtil.isNull(beanClass)) { return null; } - return CglibUtil.toBean(map, beanClass); + T bean = ReflectUtil.newInstanceIfPossible(beanClass); + return mapToBean(map, bean); } /** @@ -119,6 +132,54 @@ public class BeanCopyUtils { if (ObjectUtil.isNull(bean)) { return null; } - return CglibUtil.fillBean(map, bean); + BeanMap.create(bean).putAll(map); + return bean; } + + /** + * BeanCopier属性缓存
+ * 缓存用于防止多次反射造成的性能问题 + * + * @author Looly + * @since 5.4.1 + */ + public enum BeanCopierCache { + /** + * BeanCopier属性缓存单例 + */ + INSTANCE; + + private final SimpleCache cache = new SimpleCache<>(); + + /** + * 获得类与转换器生成的key在{@link BeanCopier}的Map中对应的元素 + * + * @param srcClass 源Bean的类 + * @param targetClass 目标Bean的类 + * @param converter 转换器 + * @return Map中对应的BeanCopier + */ + public BeanCopier get(Class srcClass, Class targetClass, Converter converter) { + final String key = genKey(srcClass, targetClass, converter); + return cache.get(key, () -> BeanCopier.create(srcClass, targetClass, converter != null)); + } + + /** + * 获得类与转换器生成的key + * + * @param srcClass 源Bean的类 + * @param targetClass 目标Bean的类 + * @param converter 转换器 + * @return 属性名和Map映射的key + */ + private String genKey(Class srcClass, Class targetClass, Converter converter) { + final StringBuilder key = StrUtil.builder() + .append(srcClass.getName()).append('#').append(targetClass.getName()); + if(null != converter){ + key.append('#').append(converter.getClass().getName()); + } + return key.toString(); + } + } + } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java index e3cb9c56a..c64f1f8a1 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java @@ -22,17 +22,17 @@ import java.util.Date; @NoArgsConstructor(access = AccessLevel.PRIVATE) public class DateUtils extends org.apache.commons.lang3.time.DateUtils { - public static String YYYY = "yyyy"; + public static final String YYYY = "yyyy"; - public static String YYYY_MM = "yyyy-MM"; + public static final String YYYY_MM = "yyyy-MM"; - public static String YYYY_MM_DD = "yyyy-MM-dd"; + public static final String YYYY_MM_DD = "yyyy-MM-dd"; - public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss"; + public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss"; - public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; + public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; - private static String[] parsePatterns = { + private static final String[] PARSE_PATTERNS = { "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"}; @@ -55,27 +55,27 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils { return dateTimeNow(YYYY_MM_DD); } - public static final String getTime() { + public static String getTime() { return dateTimeNow(YYYY_MM_DD_HH_MM_SS); } - public static final String dateTimeNow() { + public static String dateTimeNow() { return dateTimeNow(YYYYMMDDHHMMSS); } - public static final String dateTimeNow(final String format) { + public static String dateTimeNow(final String format) { return parseDateToStr(format, new Date()); } - public static final String dateTime(final Date date) { + public static String dateTime(final Date date) { return parseDateToStr(YYYY_MM_DD, date); } - public static final String parseDateToStr(final String format, final Date date) { + public static String parseDateToStr(final String format, final Date date) { return new SimpleDateFormat(format).format(date); } - public static final Date dateTime(final String format, final String ts) { + public static Date dateTime(final String format, final String ts) { try { return new SimpleDateFormat(format).parse(ts); } catch (ParseException e) { @@ -86,7 +86,7 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils { /** * 日期路径 即年/月/日 如2018/08/08 */ - public static final String datePath() { + public static String datePath() { Date now = new Date(); return DateFormatUtils.format(now, "yyyy/MM/dd"); } @@ -94,7 +94,7 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils { /** * 日期路径 即年/月/日 如20180808 */ - public static final String dateTime() { + public static String dateTime() { Date now = new Date(); return DateFormatUtils.format(now, "yyyyMMdd"); } @@ -107,7 +107,7 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils { return null; } try { - return parseDate(str.toString(), parsePatterns); + return parseDate(str.toString(), PARSE_PATTERNS); } catch (ParseException e) { return null; } @@ -124,8 +124,7 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils { /** * 计算相差天数 */ - public static int differentDaysByMillisecond(Date date1, Date date2) - { + public static int differentDaysByMillisecond(Date date1, Date date2) { return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24))); } diff --git a/ruoyi-demo/pom.xml b/ruoyi-demo/pom.xml index 329b4e7ee..2fe2c184e 100644 --- a/ruoyi-demo/pom.xml +++ b/ruoyi-demo/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.0.1 + 4.1.0 4.0.0 diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestBatchController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestBatchController.java index 1bb9d9fa0..aa1f064a0 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestBatchController.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestBatchController.java @@ -45,7 +45,7 @@ public class TestBatchController extends BaseController { List list = new ArrayList<>(); for (int i = 0; i < 1000; i++) { TestDemo testDemo = new TestDemo(); - testDemo.setOrderNum(-1L); + testDemo.setOrderNum(-1); testDemo.setTestKey("批量新增"); testDemo.setValue("测试新增"); list.add(testDemo); @@ -65,7 +65,7 @@ public class TestBatchController extends BaseController { List list = new ArrayList<>(); for (int i = 0; i < 1000; i++) { TestDemo testDemo = new TestDemo(); - testDemo.setOrderNum(-1L); + testDemo.setOrderNum(-1); testDemo.setTestKey("批量新增"); testDemo.setValue("测试新增"); list.add(testDemo); } diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestDemoController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestDemoController.java index 593f22adf..d1f994e5d 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestDemoController.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestDemoController.java @@ -117,7 +117,7 @@ public class TestDemoController extends BaseController { @ApiOperation("新增测试单表") @SaCheckPermission("demo:demo:add") @Log(title = "测试单表", businessType = BusinessType.INSERT) - @RepeatSubmit(interval = 2, timeUnit = TimeUnit.SECONDS, message = "不允许重复提交") + @RepeatSubmit(interval = 2, timeUnit = TimeUnit.SECONDS, message = "{repeat.submit.message}") @PostMapping() public R add(@RequestBody TestDemoBo bo) { // 使用校验工具对标 @Validated(AddGroup.class) 注解 diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestDemo.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestDemo.java index c079d122b..dc19ce2c7 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestDemo.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestDemo.java @@ -39,7 +39,7 @@ public class TestDemo extends BaseEntity { * 排序号 */ @OrderBy(asc = false, sort = 1) - private Long orderNum; + private Integer orderNum; /** * key键 diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestTree.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestTree.java index 1ca4a7ad4..b480aa0c1 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestTree.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestTree.java @@ -17,7 +17,7 @@ import lombok.EqualsAndHashCode; @Data @EqualsAndHashCode(callSuper = true) @TableName("test_tree") -public class TestTree extends TreeEntity { +public class TestTree extends TreeEntity { private static final long serialVersionUID = 1L; diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestTreeBo.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestTreeBo.java index 29f4ac973..211a79f14 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestTreeBo.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestTreeBo.java @@ -21,7 +21,7 @@ import javax.validation.constraints.NotNull; @Data @EqualsAndHashCode(callSuper = true) @ApiModel("测试树表业务对象") -public class TestTreeBo extends TreeEntity { +public class TestTreeBo extends TreeEntity { /** * 主键 diff --git a/ruoyi-extend/pom.xml b/ruoyi-extend/pom.xml index 3b80b15ca..5e3725e57 100644 --- a/ruoyi-extend/pom.xml +++ b/ruoyi-extend/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.0.1 + 4.1.0 4.0.0 ruoyi-extend diff --git a/ruoyi-extend/ruoyi-monitor-admin/pom.xml b/ruoyi-extend/ruoyi-monitor-admin/pom.xml index e811fd3be..8fed38aad 100644 --- a/ruoyi-extend/ruoyi-monitor-admin/pom.xml +++ b/ruoyi-extend/ruoyi-monitor-admin/pom.xml @@ -5,7 +5,7 @@ ruoyi-extend com.ruoyi - 4.0.1 + 4.1.0 4.0.0 jar diff --git a/ruoyi-extend/ruoyi-xxl-job-admin/pom.xml b/ruoyi-extend/ruoyi-xxl-job-admin/pom.xml index 65125b905..d61f79dc5 100644 --- a/ruoyi-extend/ruoyi-xxl-job-admin/pom.xml +++ b/ruoyi-extend/ruoyi-xxl-job-admin/pom.xml @@ -4,14 +4,12 @@ ruoyi-extend com.ruoyi - 4.0.1 + 4.1.0 ruoyi-xxl-job-admin jar - 2.1.4 - 8.0.23 @@ -62,13 +60,12 @@ org.mybatis.spring.boot mybatis-spring-boot-starter - ${mybatis-spring-boot-starter.version} + ${spring-boot.mybatis} mysql mysql-connector-java - ${mysql-connector-java.version} diff --git a/ruoyi-framework/pom.xml b/ruoyi-framework/pom.xml index 9f28913f9..6d7f41006 100644 --- a/ruoyi-framework/pom.xml +++ b/ruoyi-framework/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.0.1 + 4.1.0 4.0.0 diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java index 298eb43bf..542b16bfd 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java @@ -3,6 +3,7 @@ package com.ruoyi.framework.aspectj; import com.ruoyi.common.annotation.RateLimiter; import com.ruoyi.common.enums.LimitType; import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.MessageUtils; import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.redis.RedisUtils; import lombok.extern.slf4j.Slf4j; @@ -37,7 +38,7 @@ public class RateLimiterAspect { } long number = RedisUtils.rateLimiter(combineKey, rateType, count, time); if (number == -1) { - throw new ServiceException("访问过于频繁,请稍候再试"); + throw new ServiceException(MessageUtils.message("rate.limiter.message")); } log.info("限制令牌 => {}, 剩余令牌 => {}, 缓存key => '{}'", count, number, combineKey); } catch (ServiceException e) { diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RepeatSubmitAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RepeatSubmitAspect.java index e7bbbdd6b..aedc4431c 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RepeatSubmitAspect.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RepeatSubmitAspect.java @@ -5,15 +5,18 @@ import cn.hutool.core.util.ObjectUtil; import cn.hutool.crypto.SecureUtil; import com.ruoyi.common.annotation.RepeatSubmit; import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.domain.R; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.JsonUtils; +import com.ruoyi.common.utils.MessageUtils; import com.ruoyi.common.utils.ServletUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.redis.RedisUtils; -import com.ruoyi.framework.config.properties.RepeatSubmitProperties; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; @@ -27,7 +30,7 @@ import java.util.Map; import java.util.concurrent.TimeUnit; /** - * 防止重复提交 + * 防止重复提交(参考美团GTIS防重系统) * * @author Lion Li */ @@ -37,12 +40,12 @@ import java.util.concurrent.TimeUnit; @Component public class RepeatSubmitAspect { - private final RepeatSubmitProperties repeatSubmitProperties; + private static final ThreadLocal KEY_CACHE = new ThreadLocal<>(); @Before("@annotation(repeatSubmit)") public void doBefore(JoinPoint point, RepeatSubmit repeatSubmit) throws Throwable { // 如果注解不为0 则使用注解数值 - long interval = repeatSubmitProperties.getInterval(); + long interval = 0; if (repeatSubmit.interval() > 0) { interval = repeatSubmit.timeUnit().toMillis(repeatSubmit.interval()); } @@ -64,11 +67,45 @@ public class RepeatSubmitAspect { String key = RedisUtils.getCacheObject(cacheRepeatKey); if (key == null) { RedisUtils.setCacheObject(cacheRepeatKey, "", interval, TimeUnit.MILLISECONDS); + KEY_CACHE.set(cacheRepeatKey); } else { - throw new ServiceException(repeatSubmit.message()); + String message = repeatSubmit.message(); + if (StringUtils.startsWith(message, "{") && StringUtils.endsWith(message, "}")) { + message = MessageUtils.message(StringUtils.substring(message, 1, message.length() - 1)); + } + throw new ServiceException(message); } } + /** + * 处理完请求后执行 + * + * @param joinPoint 切点 + */ + @AfterReturning(pointcut = "@annotation(repeatSubmit)", returning = "jsonResult") + public void doAfterReturning(JoinPoint joinPoint, RepeatSubmit repeatSubmit, Object jsonResult) { + if (jsonResult instanceof R) { + R r = (R) jsonResult; + if (r.getCode() == R.SUCCESS) { + return; + } + RedisUtils.deleteObject(KEY_CACHE.get()); + KEY_CACHE.remove(); + } + } + + /** + * 拦截异常操作 + * + * @param joinPoint 切点 + * @param e 异常 + */ + @AfterThrowing(value = "@annotation(repeatSubmit)", throwing = "e") + public void doAfterThrowing(JoinPoint joinPoint, RepeatSubmit repeatSubmit, Exception e) { + RedisUtils.deleteObject(KEY_CACHE.get()); + KEY_CACHE.remove(); + } + /** * 参数拼装 */ diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java index 3d4bc9e8b..b284216f5 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java @@ -18,10 +18,10 @@ import java.awt.*; @Configuration public class CaptchaConfig { - private final int width = 160; - private final int height = 60; - private final Color background = Color.PINK; - private final Font font = new Font("Arial", Font.BOLD, 48); + private static final int WIDTH = 160; + private static final int HEIGHT = 60; + private static final Color BACKGROUND = Color.PINK; + private static final Font FONT = new Font("Arial", Font.BOLD, 48); /** * 圆圈干扰验证码 @@ -29,9 +29,9 @@ public class CaptchaConfig { @Lazy @Bean public CircleCaptcha circleCaptcha() { - CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(width, height); - captcha.setBackground(background); - captcha.setFont(font); + CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(WIDTH, HEIGHT); + captcha.setBackground(BACKGROUND); + captcha.setFont(FONT); return captcha; } @@ -41,9 +41,9 @@ public class CaptchaConfig { @Lazy @Bean public LineCaptcha lineCaptcha() { - LineCaptcha captcha = CaptchaUtil.createLineCaptcha(width, height); - captcha.setBackground(background); - captcha.setFont(font); + LineCaptcha captcha = CaptchaUtil.createLineCaptcha(WIDTH, HEIGHT); + captcha.setBackground(BACKGROUND); + captcha.setFont(FONT); return captcha; } @@ -53,9 +53,9 @@ public class CaptchaConfig { @Lazy @Bean public ShearCaptcha shearCaptcha() { - ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(width, height); - captcha.setBackground(background); - captcha.setFont(font); + ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(WIDTH, HEIGHT); + captcha.setBackground(BACKGROUND); + captcha.setFont(FONT); return captcha; } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java index a8bec417a..da18cfd17 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java @@ -53,8 +53,7 @@ public class RedisConfig extends CachingConfigurerSupport { Config config = new Config(); config.setThreads(redissonProperties.getThreads()) .setNettyThreads(redissonProperties.getNettyThreads()) - .setCodec(JsonJacksonCodec.INSTANCE) - .setTransportMode(redissonProperties.getTransportMode()); + .setCodec(JsonJacksonCodec.INSTANCE); RedissonProperties.SingleServerConfig singleServerConfig = redissonProperties.getSingleServerConfig(); if (ObjectUtil.isNotNull(singleServerConfig)) { @@ -65,8 +64,6 @@ public class RedisConfig extends CachingConfigurerSupport { .setDatabase(redisProperties.getDatabase()) .setPassword(StringUtils.isNotBlank(redisProperties.getPassword()) ? redisProperties.getPassword() : null) .setTimeout(singleServerConfig.getTimeout()) - .setRetryAttempts(singleServerConfig.getRetryAttempts()) - .setRetryInterval(singleServerConfig.getRetryInterval()) .setClientName(singleServerConfig.getClientName()) .setIdleConnectionTimeout(singleServerConfig.getIdleConnectionTimeout()) .setSubscriptionConnectionPoolSize(singleServerConfig.getSubscriptionConnectionPoolSize()) @@ -87,11 +84,8 @@ public class RedisConfig extends CachingConfigurerSupport { .setConnectTimeout(((Long) redisProperties.getTimeout().toMillis()).intValue()) .setPassword(StringUtils.isNotBlank(redisProperties.getPassword()) ? redisProperties.getPassword() : null) .setTimeout(clusterServersConfig.getTimeout()) - .setRetryAttempts(clusterServersConfig.getRetryAttempts()) - .setRetryInterval(clusterServersConfig.getRetryInterval()) .setClientName(clusterServersConfig.getClientName()) .setIdleConnectionTimeout(clusterServersConfig.getIdleConnectionTimeout()) - .setPingConnectionInterval(clusterServersConfig.getPingConnectionInterval()) .setSubscriptionConnectionPoolSize(clusterServersConfig.getSubscriptionConnectionPoolSize()) .setMasterConnectionMinimumIdleSize(clusterServersConfig.getMasterConnectionMinimumIdleSize()) .setMasterConnectionPoolSize(clusterServersConfig.getMasterConnectionPoolSize()) @@ -144,8 +138,6 @@ public class RedisConfig extends CachingConfigurerSupport { * threads: 16 * # Netty线程池数量 * nettyThreads: 32 - * # 传输模式 - * transportMode: "NIO" * # 集群配置 * clusterServersConfig: * # 客户端名称 @@ -160,14 +152,8 @@ public class RedisConfig extends CachingConfigurerSupport { * slaveConnectionPoolSize: 64 * # 连接空闲超时,单位:毫秒 * idleConnectionTimeout: 10000 - * # ping连接间隔 - * pingConnectionInterval: 1000 * # 命令等待超时,单位:毫秒 * timeout: 3000 - * # 如果尝试在此限制之内发送成功,则开始启用 timeout 计时。 - * retryAttempts: 3 - * # 命令重试发送时间间隔,单位:毫秒 - * retryInterval: 1500 * # 发布和订阅连接池大小 * subscriptionConnectionPoolSize: 50 * # 读取模式 diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SaTokenConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SaTokenConfig.java index 54f373bea..671400f6f 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SaTokenConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SaTokenConfig.java @@ -5,7 +5,7 @@ import cn.dev33.satoken.interceptor.SaRouteInterceptor; import cn.dev33.satoken.jwt.StpLogicJwtForStyle; import cn.dev33.satoken.router.SaRouter; import cn.dev33.satoken.stp.StpLogic; -import cn.hutool.core.util.ObjectUtil; +import cn.dev33.satoken.stp.StpUtil; import com.ruoyi.common.helper.LoginHelper; import com.ruoyi.framework.config.properties.SecurityProperties; import lombok.RequiredArgsConstructor; @@ -43,15 +43,17 @@ public class SaTokenConfig implements WebMvcConfigurer { .match("/**") // 排除下不需要拦截的 .notMatch(securityProperties.getExcludes()) + // 对未排除的路径进行检查 .check(() -> { - Long userId = LoginHelper.getUserId(); - if (ObjectUtil.isNotNull(userId)) { - // 有效率影响 用于临时测试 - // if (log.isDebugEnabled()) { - // log.debug("剩余有效时间: {}", StpUtil.getTokenTimeout()); - // log.debug("临时有效时间: {}", StpUtil.getTokenActivityTimeout()); - // } - } + // 检查是否登录 是否有token + StpUtil.checkLogin(); + + // 有效率影响 用于临时测试 + // if (log.isDebugEnabled()) { + // log.debug("剩余有效时间: {}", StpUtil.getTokenTimeout()); + // log.debug("临时有效时间: {}", StpUtil.getTokenActivityTimeout()); + // } + }); }) { @SuppressWarnings("all") diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java index f6e07fedc..ebf236c87 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java @@ -1,7 +1,6 @@ package com.ruoyi.framework.config; import com.ruoyi.common.utils.Threads; -import com.ruoyi.common.utils.reflect.ReflectUtils; import com.ruoyi.framework.config.properties.ThreadPoolProperties; import org.apache.commons.lang3.concurrent.BasicThreadFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -10,7 +9,6 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; -import java.util.concurrent.RejectedExecutionHandler; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor; @@ -23,6 +21,11 @@ import java.util.concurrent.ThreadPoolExecutor; @Configuration public class ThreadPoolConfig { + /** + * 核心线程数 = cpu 核心数 + 1 + */ + private final int core = Runtime.getRuntime().availableProcessors() + 1; + @Autowired private ThreadPoolProperties threadPoolProperties; @@ -30,12 +33,11 @@ public class ThreadPoolConfig { @ConditionalOnProperty(prefix = "thread-pool", name = "enabled", havingValue = "true") public ThreadPoolTaskExecutor threadPoolTaskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); - executor.setMaxPoolSize(threadPoolProperties.getMaxPoolSize()); - executor.setCorePoolSize(threadPoolProperties.getCorePoolSize()); + executor.setMaxPoolSize(core); + executor.setCorePoolSize(core * 2); executor.setQueueCapacity(threadPoolProperties.getQueueCapacity()); executor.setKeepAliveSeconds(threadPoolProperties.getKeepAliveSeconds()); - RejectedExecutionHandler handler = ReflectUtils.newInstance(threadPoolProperties.getRejectedExecutionHandler().getClazz()); - executor.setRejectedExecutionHandler(handler); + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); return executor; } @@ -44,7 +46,7 @@ public class ThreadPoolConfig { */ @Bean(name = "scheduledExecutorService") protected ScheduledExecutorService scheduledExecutorService() { - return new ScheduledThreadPoolExecutor(threadPoolProperties.getCorePoolSize(), + return new ScheduledThreadPoolExecutor(core, new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(), new ThreadPoolExecutor.CallerRunsPolicy()) { @Override diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/RedissonProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/RedissonProperties.java index eae9e3fc8..cd320eb50 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/RedissonProperties.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/RedissonProperties.java @@ -4,7 +4,6 @@ import lombok.Data; import lombok.NoArgsConstructor; import org.redisson.config.ReadMode; import org.redisson.config.SubscriptionMode; -import org.redisson.config.TransportMode; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @@ -30,11 +29,6 @@ public class RedissonProperties { */ private int nettyThreads; - /** - * 传输模式 - */ - private TransportMode transportMode; - /** * 单机服务配置 */ @@ -79,16 +73,6 @@ public class RedissonProperties { */ private int timeout; - /** - * 如果尝试在此限制之内发送成功,则开始启用 timeout 计时。 - */ - private int retryAttempts; - - /** - * 命令重试发送时间间隔,单位:毫秒 - */ - private int retryInterval; - /** * 发布和订阅连接池大小 */ @@ -130,26 +114,11 @@ public class RedissonProperties { */ private int idleConnectionTimeout; - /** - * ping超时 - */ - private int pingConnectionInterval; - /** * 命令等待超时,单位:毫秒 */ private int timeout; - /** - * 如果尝试在此限制之内发送成功,则开始启用 timeout 计时。 - */ - private int retryAttempts; - - /** - * 命令重试发送时间间隔,单位:毫秒 - */ - private int retryInterval; - /** * 发布和订阅连接池大小 */ diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/RepeatSubmitProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/RepeatSubmitProperties.java deleted file mode 100644 index fa65b28c3..000000000 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/RepeatSubmitProperties.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.ruoyi.framework.config.properties; - -import lombok.Data; -import org.springframework.boot.context.properties.ConfigurationProperties; -import org.springframework.stereotype.Component; - -/** - * 重复提交 配置属性 - * - * @author Lion Li - */ -@Data -@Component -@ConfigurationProperties(prefix = "repeat-submit") -public class RepeatSubmitProperties { - - /** - * 间隔时间(毫秒) - */ - private int interval; - -} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/ThreadPoolProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/ThreadPoolProperties.java index fbffc0f45..fe0673321 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/ThreadPoolProperties.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/ThreadPoolProperties.java @@ -1,6 +1,5 @@ package com.ruoyi.framework.config.properties; -import com.ruoyi.common.enums.ThreadPoolRejectedPolicy; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @@ -20,16 +19,6 @@ public class ThreadPoolProperties { */ private boolean enabled; - /** - * 核心线程池大小 - */ - private int corePoolSize; - - /** - * 最大可创建的线程数 - */ - private int maxPoolSize; - /** * 队列最大长度 */ @@ -40,9 +29,4 @@ public class ThreadPoolProperties { */ private int keepAliveSeconds; - /** - * 线程池对拒绝任务(无线程可用)的处理策略 - */ - private ThreadPoolRejectedPolicy rejectedExecutionHandler; - } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/listener/UserActionListener.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/listener/UserActionListener.java index c4252b448..75277c257 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/listener/UserActionListener.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/listener/UserActionListener.java @@ -53,7 +53,7 @@ public class UserActionListener implements SaTokenListener { dto.setUserName(user.getUsername()); dto.setDeptName(user.getDeptName()); RedisUtils.setCacheObject(Constants.ONLINE_TOKEN_KEY + tokenValue, dto, tokenConfig.getTimeout(), TimeUnit.SECONDS); - log.info("user doLogin, useId:{}, token:{}", loginId, tokenValue); + log.info("user doLogin, userId:{}, token:{}", loginId, tokenValue); } else if (userType == UserType.APP_USER) { // app端 自行根据业务编写 } @@ -65,7 +65,7 @@ public class UserActionListener implements SaTokenListener { @Override public void doLogout(String loginType, Object loginId, String tokenValue) { RedisUtils.deleteObject(Constants.ONLINE_TOKEN_KEY + tokenValue); - log.info("user doLogout, useId:{}, token:{}", loginId, tokenValue); + log.info("user doLogout, userId:{}, token:{}", loginId, tokenValue); } /** @@ -74,7 +74,7 @@ public class UserActionListener implements SaTokenListener { @Override public void doKickout(String loginType, Object loginId, String tokenValue) { RedisUtils.deleteObject(Constants.ONLINE_TOKEN_KEY + tokenValue); - log.info("user doLogoutByLoginId, useId:{}, token:{}", loginId, tokenValue); + log.info("user doLogoutByLoginId, userId:{}, token:{}", loginId, tokenValue); } /** @@ -83,7 +83,7 @@ public class UserActionListener implements SaTokenListener { @Override public void doReplaced(String loginType, Object loginId, String tokenValue) { RedisUtils.deleteObject(Constants.ONLINE_TOKEN_KEY + tokenValue); - log.info("user doReplaced, useId:{}, token:{}", loginId, tokenValue); + log.info("user doReplaced, userId:{}, token:{}", loginId, tokenValue); } /** diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/satoken/service/SaInterfaceImpl.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/satoken/service/SaPermissionImpl.java similarity index 79% rename from ruoyi-framework/src/main/java/com/ruoyi/framework/satoken/service/SaInterfaceImpl.java rename to ruoyi-framework/src/main/java/com/ruoyi/framework/satoken/service/SaPermissionImpl.java index 8e97d0578..057d18336 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/satoken/service/SaInterfaceImpl.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/satoken/service/SaPermissionImpl.java @@ -9,9 +9,17 @@ import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; +/** + * sa-token 权限管理实现类 + * + * @author Lion Li + */ @Component -public class SaInterfaceImpl implements StpInterface { +public class SaPermissionImpl implements StpInterface { + /** + * 获取菜单权限列表 + */ @Override public List getPermissionList(Object loginId, String loginType) { LoginUser loginUser = LoginHelper.getLoginUser(); @@ -19,11 +27,14 @@ public class SaInterfaceImpl implements StpInterface { if (userType == UserType.SYS_USER) { return new ArrayList<>(loginUser.getMenuPermission()); } else if (userType == UserType.APP_USER) { - // app端权限返回 自行根据业务编写 + // 其他端 自行根据业务编写 } return new ArrayList<>(); } + /** + * 获取角色权限列表 + */ @Override public List getRoleList(Object loginId, String loginType) { LoginUser loginUser = LoginHelper.getLoginUser(); @@ -31,7 +42,7 @@ public class SaInterfaceImpl implements StpInterface { if (userType == UserType.SYS_USER) { return new ArrayList<>(loginUser.getRolePermission()); } else if (userType == UserType.APP_USER) { - // app端权限返回 自行根据业务编写 + // 其他端 自行根据业务编写 } return new ArrayList<>(); } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java index 90b265e27..326c96a7b 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java @@ -9,7 +9,9 @@ import com.ruoyi.common.core.domain.R; import com.ruoyi.common.exception.DemoModeException; import com.ruoyi.common.exception.ServiceException; import lombok.extern.slf4j.Slf4j; +import org.mybatis.spring.MyBatisSystemException; import org.springframework.context.support.DefaultMessageSourceResolvable; +import org.springframework.dao.DuplicateKeyException; import org.springframework.validation.BindException; import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.bind.MethodArgumentNotValidException; @@ -71,6 +73,31 @@ public class GlobalExceptionHandler { return R.fail(e.getMessage()); } + /** + * 主键或UNIQUE索引,数据重复异常 + */ + @ExceptionHandler(DuplicateKeyException.class) + public R handleDuplicateKeyException(DuplicateKeyException e, HttpServletRequest request) { + String requestURI = request.getRequestURI(); + log.error("请求地址'{}',数据库中已存在记录'{}'", requestURI, e.getMessage()); + return R.fail("数据库中已存在该记录,请联系管理员确认"); + } + + /** + * Mybatis系统异常 通用处理 + */ + @ExceptionHandler(MyBatisSystemException.class) + public R handleCannotFindDataSourceException(MyBatisSystemException e, HttpServletRequest request) { + String requestURI = request.getRequestURI(); + String message = e.getMessage(); + if (message.contains("CannotFindDataSourceException")) { + log.error("请求地址'{}', 未找到数据源", requestURI); + return R.fail("未找到数据源,请联系管理员确认"); + } + log.error("请求地址'{}', Mybatis系统异常", requestURI, e); + return R.fail(message); + } + /** * 业务异常 */ diff --git a/ruoyi-generator/pom.xml b/ruoyi-generator/pom.xml index f44a9e5f1..bed61d9b9 100644 --- a/ruoyi-generator/pom.xml +++ b/ruoyi-generator/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.0.1 + 4.1.0 4.0.0 diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java index 09bf1aeb1..e9e61e72b 100644 --- a/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java @@ -5,13 +5,12 @@ import cn.hutool.core.convert.Convert; import cn.hutool.core.io.IoUtil; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.PageQuery; +import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.generator.domain.GenTable; import com.ruoyi.generator.domain.GenTableColumn; -import com.ruoyi.generator.service.IGenTableColumnService; import com.ruoyi.generator.service.IGenTableService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -38,7 +37,6 @@ import java.util.Map; public class GenController extends BaseController { private final IGenTableService genTableService; - private final IGenTableColumnService genTableColumnService; /** * 查询代码生成列表 @@ -55,11 +53,11 @@ public class GenController extends BaseController { */ @ApiOperation("修改代码生成业务") @SaCheckPermission("tool:gen:query") - @GetMapping(value = "/{talbleId}") - public R> getInfo(@PathVariable Long talbleId) { - GenTable table = genTableService.selectGenTableById(talbleId); + @GetMapping(value = "/{tableId}") + public R> getInfo(@PathVariable Long tableId) { + GenTable table = genTableService.selectGenTableById(tableId); List tables = genTableService.selectGenTableAll(); - List list = genTableColumnService.selectGenTableColumnListByTableId(talbleId); + List list = genTableService.selectGenTableColumnListByTableId(tableId); Map map = new HashMap(); map.put("info", table); map.put("rows", list); @@ -82,10 +80,10 @@ public class GenController extends BaseController { */ @ApiOperation("查询数据表字段列表") @SaCheckPermission("tool:gen:list") - @GetMapping(value = "/column/{talbleId}") + @GetMapping(value = "/column/{tableId}") public TableDataInfo columnList(Long tableId) { TableDataInfo dataInfo = new TableDataInfo<>(); - List list = genTableColumnService.selectGenTableColumnListByTableId(tableId); + List list = genTableService.selectGenTableColumnListByTableId(tableId); dataInfo.setRows(list); dataInfo.setTotal(list.size()); return dataInfo; diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java index f8bbc474c..45e9168e5 100644 --- a/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java @@ -150,6 +150,12 @@ public class GenTable extends BaseEntity { @TableField(exist = false) private String treeName; + /* + * 菜单id列表 + */ + @TableField(exist = false) + private List menuIds; + /** * 上级菜单ID字段 */ diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java index 763acd74c..1ea991796 100644 --- a/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java @@ -8,7 +8,7 @@ import com.ruoyi.common.core.domain.BaseEntity; import com.ruoyi.common.utils.StringUtils; import lombok.Data; import lombok.EqualsAndHashCode; -import lombok.experimental.Accessors; +import org.apache.ibatis.type.JdbcType; import javax.validation.constraints.NotBlank; @@ -42,7 +42,7 @@ public class GenTableColumn extends BaseEntity { /** * 列描述 */ - @TableField(updateStrategy = FieldStrategy.IGNORED) + @TableField(updateStrategy = FieldStrategy.IGNORED, jdbcType = JdbcType.VARCHAR) private String columnComment; /** @@ -64,43 +64,43 @@ public class GenTableColumn extends BaseEntity { /** * 是否主键(1是) */ - @TableField(updateStrategy = FieldStrategy.IGNORED) + @TableField(updateStrategy = FieldStrategy.IGNORED, jdbcType = JdbcType.VARCHAR) private String isPk; /** * 是否自增(1是) */ - @TableField(updateStrategy = FieldStrategy.IGNORED) + @TableField(updateStrategy = FieldStrategy.IGNORED, jdbcType = JdbcType.VARCHAR) private String isIncrement; /** * 是否必填(1是) */ - @TableField(updateStrategy = FieldStrategy.IGNORED) + @TableField(updateStrategy = FieldStrategy.IGNORED, jdbcType = JdbcType.VARCHAR) private String isRequired; /** * 是否为插入字段(1是) */ - @TableField(updateStrategy = FieldStrategy.IGNORED) + @TableField(updateStrategy = FieldStrategy.IGNORED, jdbcType = JdbcType.VARCHAR) private String isInsert; /** * 是否编辑字段(1是) */ - @TableField(updateStrategy = FieldStrategy.IGNORED) + @TableField(updateStrategy = FieldStrategy.IGNORED, jdbcType = JdbcType.VARCHAR) private String isEdit; /** * 是否列表字段(1是) */ - @TableField(updateStrategy = FieldStrategy.IGNORED) + @TableField(updateStrategy = FieldStrategy.IGNORED, jdbcType = JdbcType.VARCHAR) private String isList; /** * 是否查询字段(1是) */ - @TableField(updateStrategy = FieldStrategy.IGNORED) + @TableField(updateStrategy = FieldStrategy.IGNORED, jdbcType = JdbcType.VARCHAR) private String isQuery; /** diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java index cbb92fdc4..f70a11eb6 100644 --- a/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java @@ -16,26 +16,13 @@ import java.util.List; @InterceptorIgnore(dataPermission = "true") public interface GenTableMapper extends BaseMapperPlus { - - Page selectPageGenTableList(@Param("page") Page page, @Param("genTable") GenTable genTable); - - Page selectPageDbTableList(@Param("page") Page page, @Param("genTable") GenTable genTable); - - /** - * 查询业务列表 - * - * @param genTable 业务信息 - * @return 业务集合 - */ - List selectGenTableList(GenTable genTable); - /** * 查询据库列表 * - * @param genTable 业务信息 + * @param genTable 查询条件 * @return 数据库表集合 */ - List selectDbTableList(GenTable genTable); + Page selectPageDbTableList(@Param("page") Page page, @Param("genTable") GenTable genTable); /** * 查询据库列表 diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java deleted file mode 100644 index 78260aa78..000000000 --- a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.ruoyi.generator.service; - -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import com.ruoyi.generator.domain.GenTableColumn; -import com.ruoyi.generator.mapper.GenTableColumnMapper; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -import java.util.Arrays; -import java.util.List; - -/** - * 业务字段 服务层实现 - * - * @author Lion Li - */ -@RequiredArgsConstructor -@Service -public class GenTableColumnServiceImpl implements IGenTableColumnService { - - private final GenTableColumnMapper baseMapper; - - /** - * 查询业务字段列表 - * - * @param tableId 业务字段编号 - * @return 业务字段集合 - */ - @Override - public List selectGenTableColumnListByTableId(Long tableId) { - return baseMapper.selectList(new LambdaQueryWrapper() - .eq(GenTableColumn::getTableId, tableId) - .orderByAsc(GenTableColumn::getSort)); - } - - /** - * 新增业务字段 - * - * @param genTableColumn 业务字段信息 - * @return 结果 - */ - @Override - public int insertGenTableColumn(GenTableColumn genTableColumn) { - return baseMapper.insert(genTableColumn); - } - - /** - * 修改业务字段 - * - * @param genTableColumn 业务字段信息 - * @return 结果 - */ - @Override - public int updateGenTableColumn(GenTableColumn genTableColumn) { - return baseMapper.updateById(genTableColumn); - } - - /** - * 删除业务字段对象 - * - * @param ids 需要删除的数据ID - * @return 结果 - */ - @Override - public int deleteGenTableColumnByIds(String ids) { - return baseMapper.deleteBatchIds(Arrays.asList(ids.split(","))); - } -} diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java index 154f02630..9dccab2d1 100644 --- a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java @@ -3,8 +3,13 @@ package com.ruoyi.generator.service; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.lang.Dict; +import cn.hutool.core.lang.Snowflake; +import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjectUtil; +import com.baomidou.dynamic.datasource.annotation.DS; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.GenConstants; @@ -28,7 +33,6 @@ import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.Velocity; import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; import java.io.ByteArrayOutputStream; import java.io.File; @@ -46,6 +50,7 @@ import java.util.zip.ZipOutputStream; * * @author Lion Li */ +@DS("#header.datasource") @Slf4j @RequiredArgsConstructor @Service @@ -54,6 +59,19 @@ public class GenTableServiceImpl implements IGenTableService { private final GenTableMapper baseMapper; private final GenTableColumnMapper genTableColumnMapper; + /** + * 查询业务字段列表 + * + * @param tableId 业务字段编号 + * @return 业务字段集合 + */ + @Override + public List selectGenTableColumnListByTableId(Long tableId) { + return genTableColumnMapper.selectList(new LambdaQueryWrapper() + .eq(GenTableColumn::getTableId, tableId) + .orderByAsc(GenTableColumn::getSort)); + } + /** * 查询业务信息 * @@ -69,38 +87,27 @@ public class GenTableServiceImpl implements IGenTableService { @Override public TableDataInfo selectPageGenTableList(GenTable genTable, PageQuery pageQuery) { - Page page = baseMapper.selectPageGenTableList(pageQuery.build(), genTable); + Page page = baseMapper.selectPage(pageQuery.build(), this.buildGenTableQueryWrapper(genTable)); return TableDataInfo.build(page); } + private QueryWrapper buildGenTableQueryWrapper(GenTable genTable) { + Map params = genTable.getParams(); + QueryWrapper wrapper = Wrappers.query(); + wrapper.like(StringUtils.isNotBlank(genTable.getTableName()), "lower(table_name)", StringUtils.lowerCase(genTable.getTableName())) + .like(StringUtils.isNotBlank(genTable.getTableComment()), "lower(table_comment)", StringUtils.lowerCase(genTable.getTableComment())) + .between(params.get("beginTime") != null && params.get("endTime") != null, + "create_time", params.get("beginTime"), params.get("endTime")); + return wrapper; + } + + @Override public TableDataInfo selectPageDbTableList(GenTable genTable, PageQuery pageQuery) { Page page = baseMapper.selectPageDbTableList(pageQuery.build(), genTable); return TableDataInfo.build(page); } - /** - * 查询业务列表 - * - * @param genTable 业务信息 - * @return 业务集合 - */ - @Override - public List selectGenTableList(GenTable genTable) { - return baseMapper.selectGenTableList(genTable); - } - - /** - * 查询据库列表 - * - * @param genTable 业务信息 - * @return 数据库表集合 - */ - @Override - public List selectDbTableList(GenTable genTable) { - return baseMapper.selectDbTableList(genTable); - } - /** * 查询据库列表 * @@ -129,7 +136,6 @@ public class GenTableServiceImpl implements IGenTableService { * @return 结果 */ @Override - @Transactional(rollbackFor = Exception.class) public void updateGenTable(GenTable genTable) { String options = JsonUtils.toJsonString(genTable.getParams()); genTable.setOptions(options); @@ -148,7 +154,6 @@ public class GenTableServiceImpl implements IGenTableService { * @return 结果 */ @Override - @Transactional(rollbackFor = Exception.class) public void deleteGenTableByIds(Long[] tableIds) { List ids = Arrays.asList(tableIds); baseMapper.deleteBatchIds(ids); @@ -161,7 +166,6 @@ public class GenTableServiceImpl implements IGenTableService { * @param tableList 导入表列表 */ @Override - @Transactional(rollbackFor = Exception.class) public void importGenTable(List tableList) { String operName = LoginHelper.getUsername(); try { @@ -198,6 +202,12 @@ public class GenTableServiceImpl implements IGenTableService { Map dataMap = new LinkedHashMap<>(); // 查询表信息 GenTable table = baseMapper.selectGenTableById(tableId); + Snowflake snowflake = IdUtil.getSnowflake(); + List menuIds = new ArrayList<>(); + for (int i = 0; i < 6; i++) { + menuIds.add(snowflake.nextId()); + } + table.setMenuIds(menuIds); // 设置主子表信息 setSubTable(table); // 设置主键列信息 @@ -275,7 +285,6 @@ public class GenTableServiceImpl implements IGenTableService { * @param tableName 表名称 */ @Override - @Transactional(rollbackFor = Exception.class) public void synchDb(String tableName) { GenTable table = baseMapper.selectGenTableByName(tableName); List tableColumns = table.getColumns(); @@ -299,9 +308,8 @@ public class GenTableServiceImpl implements IGenTableService { column.setQueryType(prevColumn.getQueryType()); } if (StringUtils.isNotEmpty(prevColumn.getIsRequired()) && !column.isPk() - && (column.isInsert() || column.isEdit()) - && ((column.isUsableColumn()) || (!column.isSuperColumn()))) - { + && (column.isInsert() || column.isEdit()) + && ((column.isUsableColumn()) || (!column.isSuperColumn()))) { // 如果是(新增/修改&非主键/非忽略及父属性),继续保留必填/显示类型选项 column.setIsRequired(prevColumn.getIsRequired()); column.setHtmlType(prevColumn.getHtmlType()); @@ -345,6 +353,12 @@ public class GenTableServiceImpl implements IGenTableService { private void generatorCode(String tableName, ZipOutputStream zip) { // 查询表信息 GenTable table = baseMapper.selectGenTableByName(tableName); + Snowflake snowflake = IdUtil.getSnowflake(); + List menuIds = new ArrayList<>(); + for (int i = 0; i < 6; i++) { + menuIds.add(snowflake.nextId()); + } + table.setMenuIds(menuIds); // 设置主子表信息 setSubTable(table); // 设置主键列信息 @@ -477,3 +491,4 @@ public class GenTableServiceImpl implements IGenTableService { return genPath + File.separator + VelocityUtils.getFileName(template, table); } } + diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java deleted file mode 100644 index f14f36a53..000000000 --- a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.ruoyi.generator.service; - -import com.ruoyi.generator.domain.GenTableColumn; - -import java.util.List; - -/** - * 业务字段 服务层 - * - * @author Lion Li - */ -public interface IGenTableColumnService { - /** - * 查询业务字段列表 - * - * @param tableId 业务字段编号 - * @return 业务字段集合 - */ - List selectGenTableColumnListByTableId(Long tableId); - - /** - * 新增业务字段 - * - * @param genTableColumn 业务字段信息 - * @return 结果 - */ - int insertGenTableColumn(GenTableColumn genTableColumn); - - /** - * 修改业务字段 - * - * @param genTableColumn 业务字段信息 - * @return 结果 - */ - int updateGenTableColumn(GenTableColumn genTableColumn); - - /** - * 删除业务字段信息 - * - * @param ids 需要删除的数据ID - * @return 结果 - */ - int deleteGenTableColumnByIds(String ids); -} diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java index 27fac79e3..c432d067a 100644 --- a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java @@ -3,6 +3,7 @@ package com.ruoyi.generator.service; import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.generator.domain.GenTable; +import com.ruoyi.generator.domain.GenTableColumn; import java.util.List; import java.util.Map; @@ -14,11 +15,13 @@ import java.util.Map; */ public interface IGenTableService { - - TableDataInfo selectPageGenTableList(GenTable genTable, PageQuery pageQuery); - - - TableDataInfo selectPageDbTableList(GenTable genTable, PageQuery pageQuery); + /** + * 查询业务字段列表 + * + * @param tableId 业务字段编号 + * @return 业务字段集合 + */ + List selectGenTableColumnListByTableId(Long tableId); /** * 查询业务列表 @@ -26,7 +29,7 @@ public interface IGenTableService { * @param genTable 业务信息 * @return 业务集合 */ - List selectGenTableList(GenTable genTable); + TableDataInfo selectPageGenTableList(GenTable genTable, PageQuery pageQuery); /** * 查询据库列表 @@ -34,7 +37,7 @@ public interface IGenTableService { * @param genTable 业务信息 * @return 数据库表集合 */ - List selectDbTableList(GenTable genTable); + TableDataInfo selectPageDbTableList(GenTable genTable, PageQuery pageQuery); /** * 查询据库列表 diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java index 1a1d04ac3..b6c2248e6 100644 --- a/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java @@ -5,6 +5,8 @@ import com.ruoyi.common.utils.StringUtils; import com.ruoyi.generator.config.GenConfig; import com.ruoyi.generator.domain.GenTable; import com.ruoyi.generator.domain.GenTableColumn; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; import org.apache.commons.lang3.RegExUtils; import java.util.Arrays; @@ -14,6 +16,7 @@ import java.util.Arrays; * * @author ruoyi */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) public class GenUtils { /** diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java index a81bd51df..67769a8dd 100644 --- a/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java @@ -1,6 +1,8 @@ package com.ruoyi.generator.util; import com.ruoyi.common.constant.Constants; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; import org.apache.velocity.app.Velocity; import java.util.Properties; @@ -10,6 +12,7 @@ import java.util.Properties; * * @author ruoyi */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) public class VelocityInitializer { /** diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java index 9cc1c34f3..d8eeb6dd7 100644 --- a/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java @@ -5,11 +5,14 @@ import cn.hutool.core.convert.Convert; import cn.hutool.core.lang.Dict; import cn.hutool.core.util.ObjectUtil; import com.ruoyi.common.constant.GenConstants; +import com.ruoyi.common.helper.DataBaseHelper; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.JsonUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.generator.domain.GenTable; import com.ruoyi.generator.domain.GenTableColumn; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; import org.apache.velocity.VelocityContext; import java.util.*; @@ -19,6 +22,7 @@ import java.util.*; * * @author ruoyi */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) public class VelocityUtils { /** @@ -135,7 +139,15 @@ public class VelocityUtils { templates.add("vm/java/serviceImpl.java.vm"); templates.add("vm/java/controller.java.vm"); templates.add("vm/xml/mapper.xml.vm"); - templates.add("vm/sql/sql.vm"); + if (DataBaseHelper.isOracle()) { + templates.add("vm/sql/oracle/sql.vm"); + } else if (DataBaseHelper.isPostgerSql()) { + templates.add("vm/sql/postgres/sql.vm"); + } else if (DataBaseHelper.isSqlServer()) { + templates.add("vm/sql/sqlserver/sql.vm"); + } else { + templates.add("vm/sql/sql.vm"); + } templates.add("vm/js/api.js.vm"); if (GenConstants.TPL_CRUD.equals(tplCategory)) { templates.add("vm/vue/index.vue.vm"); diff --git a/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml b/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml index 7ef974458..fc44d8cbc 100644 --- a/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml +++ b/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml @@ -30,9 +30,85 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" diff --git a/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml b/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml index 8f0c2690e..2f17694b4 100644 --- a/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml +++ b/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml @@ -53,100 +53,183 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - - select table_id, table_name, table_comment, sub_table_name, sub_table_fk_name, class_name, tpl_category, package_name, module_name, business_name, function_name, function_author, gen_type, gen_path, options, create_by, create_time, update_by, update_time, remark from gen_table - - - + + select table_name, table_comment, create_time, update_time + from information_schema.tables + where table_schema = (select database()) + AND table_name NOT LIKE 'xxl_job_%' AND table_name NOT LIKE 'gen_%' + AND table_name NOT IN (select table_name from gen_table) AND lower(table_name) like lower(concat('%', #{genTable.tableName}, '%')) AND lower(table_comment) like lower(concat('%', #{genTable.tableComment}, '%')) - - AND date_format(create_time,'%y%m%d') >= date_format(#{genTable.params.beginTime},'%y%m%d') + order by create_time desc + + + select lower(dt.table_name) as table_name, dtc.comments as table_comment, uo.created as create_time, uo.last_ddl_time as update_time + from user_tables dt, user_tab_comments dtc, user_objects uo + where dt.table_name = dtc.table_name + and dt.table_name = uo.object_name + and uo.object_type = 'TABLE' + AND dt.table_name NOT LIKE 'XXL_JOB_%' AND dt.table_name NOT LIKE 'GEN_%' + AND lower(dt.table_name) NOT IN (select table_name from gen_table) + + AND lower(dt.table_name) like lower(concat(concat('%', #{genTable.tableName}), '%')) - - AND date_format(create_time,'%y%m%d') <= date_format(#{genTable.params.endTime},'%y%m%d') + + AND lower(dtc.comments) like lower(concat(concat('%', #{genTable.tableComment}), '%')) - - - - - - - - -