From 3fd2d9681d0c2d4582ae71db6fa275c2b5da5971 Mon Sep 17 00:00:00 2001 From: konbai <1527468660@qq.com> Date: Sat, 7 Jan 2023 16:51:51 +0800 Subject: [PATCH] =?UTF-8?q?sync:=20=E5=90=8C=E6=AD=A5=20RuoYi-Vue-Plus?= =?UTF-8?q?=EF=BC=88v4.4.0=EF=BC=89=20=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 重大更新 [重大更新] 优化支持 oss 私有库功能(数据库字段改动) #cd9c3c3f [重大更新] 连接池由 druid 修改为 hikari 更新相关配置(原因可看文档) #1f42bd3d [重大更新] 移除 tlog(不支持UI界面 使用的人太少)建议使用 skywalking [重大更新] 增加 skywalking 集成 默认注释不开启(使用看文档) 依赖升级 update springboot 2.7.5 => 2.7.6 update springboot-admin 2.7.6 => 2.7.7 update satoken 1.31.0 => 1.33.0 update spring-doc 1.6.12 => 1.6.13 update easyexcel 3.1.1 => 3.1.3 update hutool 5.8.8 => 5.8.10 update redisson 3.17.7 => 3.18.0 update lock4j 2.2.2 => 2.2.3 update s3-adk 1.12.324 => 1.12.349 update mysql-docker 8.0.29 => 8.0.31 功能更新 update 优化 oss 云厂商增加 华为obs关键字 update 优化 冗余的三元表达式 update 优化 重置时取消部门选中 update 优化 新增返回警告消息提示 update 优化 hikari 参数顺序 最常用的放上面 删除无用 druid 监控页面 update 优化 p6spy 排除健康检查 sql 执行记录 update 优化 Dockerfile 创建目录命令 update 优化 将空‘catch’块形参重命名为‘ignored’ update 优化 使用本地缓存优化 excel 导出 数据量大字典转换慢问题 update 优化 字典转换实现去除字符串查找拼接优化效率 update 优化 减小腾讯短信引入jar包的体积 update 消除Vue3控制台出现的警告信息 update 忽略不必要的属性数据返回 update 替换 mysql-jdbc 最新坐标 新增功能 add 新增 junit5 单元测试案例 #6e8ef308 add 增加 sys_oss_config access_policy 桶权限类型字段 add 增加 4.3-4.4 更新 sql 文件 add 新增 字典数据映射注解 #da94e898 add 增加 RedisUtils 获取缓存Map的key列表 问题修复 fix 修复 上传png透明图片 生成头像透明部分变成黑色 fix 修复 sqlserver sql文件 重复主键数据问题 fix 修复 sqlserver 特定情况下报 ssl 证书问题 默认关闭 ssl 认证 fix 修复 table中更多按钮切换主题色未生效修复问题 fix 修复 菜单激活无法修改其填充颜色去除某些svg图标的fill="#bfbfbf"属性 fix 修复 使用缓冲流 导致上传异常问题 fix 修复 过滤器链使用IoUtil.read方法导致request流关闭 fix 修复 Log注解GET请求记录不到参数问题 fix 修复 某些特性的环境生成代码变乱码TXT文件问题 fix 修复 开启TopNav没有子菜单隐藏侧边栏 fix 修复 回显数据字典数组异常问题 移除功能 remove 移除过期 Anonymous 注解与其实现代码 remove 移除 tlog(不支持UI界面 使用的人太少) 建议使用 skywalking --- pom.xml | 79 +++---- ruoyi-admin/Dockerfile | 14 +- ruoyi-admin/pom.xml | 22 +- .../monitor/SysUserOnlineController.java | 4 +- .../controller/system/SysDeptController.java | 4 +- .../controller/system/SysMenuController.java | 4 +- .../system/SysOssConfigController.java | 6 +- .../controller/system/SysOssController.java | 24 +- .../system/SysProfileController.java | 3 +- .../controller/system/SysUserController.java | 10 - .../src/main/resources/application-dev.yml | 71 ++---- .../src/main/resources/application-prod.yml | 71 ++---- .../src/main/resources/application.yml | 4 - ruoyi-admin/src/main/resources/logback.xml | 33 ++- ruoyi-admin/src/main/resources/spy.properties | 2 + .../java/com/ruoyi/test/AssertUnitTest.java | 45 ++++ .../java/com/ruoyi/test/DemoUnitTest.java | 70 ++++++ .../java/com/ruoyi/test/ParamUnitTest.java | 72 ++++++ .../test/java/com/ruoyi/test/TagUnitTest.java | 54 +++++ .../ruoyi/common/annotation/Anonymous.java | 22 -- .../common/annotation/DictDataMapper.java | 27 +++ .../com/ruoyi/common/constant/HttpStatus.java | 93 ++++++++ .../ruoyi/common/core/domain/BaseEntity.java | 4 + .../java/com/ruoyi/common/core/domain/R.java | 22 ++ .../filter/RepeatedlyRequestWrapper.java | 3 +- .../filter/XssHttpServletRequestWrapper.java | 4 +- .../com/ruoyi/common/helper/LoginHelper.java | 15 +- .../jackson/DictDataJsonSerializer.java | 56 +++++ .../com/ruoyi/common/utils/ServletUtils.java | 29 +++ .../ruoyi/common/utils/redis/RedisUtils.java | 11 + ruoyi-demo/pom.xml | 2 +- .../demo/controller/TestBatchController.java | 4 +- .../demo/controller/TestDemoController.java | 6 +- .../demo/controller/TestTreeController.java | 6 +- ruoyi-extend/ruoyi-monitor-admin/Dockerfile | 1 - ruoyi-extend/ruoyi-xxl-job-admin/Dockerfile | 3 +- ruoyi-extend/ruoyi-xxl-job-admin/pom.xml | 4 +- ruoyi-framework/pom.xml | 16 +- .../ruoyi/framework/aspectj/LogAspect.java | 7 +- .../ruoyi/framework/config/DruidConfig.java | 63 ------ .../framework/config/ResourcesConfig.java | 3 - .../ruoyi/framework/config/SaTokenConfig.java | 6 - .../ruoyi/framework/config/TLogConfig.java | 18 -- .../properties/ExcludeUrlProperties.java | 69 ------ .../listener/UserActionListener.java | 14 ++ .../web/exception/GlobalExceptionHandler.java | 2 +- .../main/resources/vm/java/controller.java.vm | 6 +- .../resources/vm/vue/v3/index-tree.vue.vm | 21 +- .../src/main/resources/vm/vue/v3/index.vue.vm | 14 +- ruoyi-job/pom.xml | 5 - .../com/ruoyi/job/service/SampleService.java | 2 - .../com/ruoyi/oss/constant/OssConstant.java | 2 +- .../java/com/ruoyi/oss/core/OssClient.java | 46 +++- .../com/ruoyi/oss/enumd/AccessPolicyType.java | 55 +++++ .../ruoyi/oss/properties/OssProperties.java | 5 + ruoyi-sms/pom.xml | 2 +- .../com/ruoyi/system/domain/SysOssConfig.java | 4 + .../system/domain/bo/SysOssConfigBo.java | 6 + .../system/domain/vo/SysOssConfigVo.java | 5 + .../ruoyi/system/service/ISysOssService.java | 7 +- .../ruoyi/system/service/SysLoginService.java | 2 +- .../service/impl/SysDictTypeServiceImpl.java | 71 +++--- .../service/impl/SysMenuServiceImpl.java | 9 +- .../service/impl/SysOssServiceImpl.java | 50 ++++- ruoyi-ui/bin/package.bat | 2 +- ruoyi-ui/bin/run-web.bat | 4 +- ruoyi-ui/src/assets/icons/svg/code.svg | 2 +- ruoyi-ui/src/assets/icons/svg/server.svg | 2 +- ruoyi-ui/src/assets/icons/svg/system.svg | 2 +- ruoyi-ui/src/assets/icons/svg/tool.svg | 2 +- ruoyi-ui/src/assets/styles/ruoyi.scss | 7 +- ruoyi-ui/src/components/Crontab/hour.vue | 208 +++++++++--------- ruoyi-ui/src/components/TopNav/index.vue | 6 +- ruoyi-ui/src/utils/request.js | 39 ++-- ruoyi-ui/src/utils/ruoyi.js | 7 +- ruoyi-ui/src/views/index.vue | 4 +- ruoyi-ui/src/views/monitor/druid/index.vue | 15 -- ruoyi-ui/src/views/system/oss/config.vue | 18 ++ ruoyi-ui/src/views/system/role/index.vue | 4 +- ruoyi-ui/src/views/system/user/index.vue | 7 +- .../views/system/user/profile/userAvatar.vue | 2 + ruoyi-ui/src/views/tool/gen/index.vue | 2 +- script/docker/docker-compose.yml | 6 +- script/sql/tables_xxl_job.sql | 119 ++++++++++ script/sql/test.sql | 171 ++++++++++++++ 85 files changed, 1352 insertions(+), 691 deletions(-) create mode 100644 ruoyi-admin/src/test/java/com/ruoyi/test/AssertUnitTest.java create mode 100644 ruoyi-admin/src/test/java/com/ruoyi/test/DemoUnitTest.java create mode 100644 ruoyi-admin/src/test/java/com/ruoyi/test/ParamUnitTest.java create mode 100644 ruoyi-admin/src/test/java/com/ruoyi/test/TagUnitTest.java delete mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/annotation/DictDataMapper.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/jackson/DictDataJsonSerializer.java delete mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java delete mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/TLogConfig.java delete mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/ExcludeUrlProperties.java create mode 100644 ruoyi-oss/src/main/java/com/ruoyi/oss/enumd/AccessPolicyType.java delete mode 100644 ruoyi-ui/src/views/monitor/druid/index.vue create mode 100644 script/sql/tables_xxl_job.sql create mode 100644 script/sql/test.sql diff --git a/pom.xml b/pom.xml index eb11dd3d..4b39a3d6 100644 --- a/pom.xml +++ b/pom.xml @@ -14,27 +14,26 @@ 0.7.2 - 2.7.5 + 2.7.6 UTF-8 UTF-8 1.8 3.2.2 2.2.2 - 1.2.12 - 1.6.12 + 1.6.13 5.2.3 - 3.1.1 + 3.1.3 2.3 - 1.31.0 + 1.33.0 3.5.2 3.9.1 - 5.8.8 + 5.8.10 4.10.0 - 2.7.6 - 3.17.7 - 2.2.2 + 2.7.7 + 3.18.0 + 2.2.3 3.5.2 - 1.5.0 + 2.14.2 2.3.1 1.18.24 6.7.2 @@ -45,10 +44,10 @@ 1.32 - 1.12.324 + 1.12.349 2.0.22 - 3.1.611 + 3.1.635 @@ -73,13 +72,6 @@ import - - - com.alibaba - druid-spring-boot-starter - ${druid.version} - - org.springdoc springdoc-openapi-webmvc-core @@ -190,7 +182,7 @@ com.tencentcloudapi - tencentcloud-sdk-java + tencentcloud-sdk-java-sms ${tencent.sms.version} @@ -225,29 +217,9 @@ - com.yomahub - tlog-web-spring-boot-starter - ${tlog.version} - - - log4j - log4j - - - dom4j - dom4j - - - commons-beanutils - commons-beanutils - - - - - - com.yomahub - tlog-xxljob-spring-boot-starter - ${tlog.version} + com.alibaba + transmittable-thread-local + ${alibaba-ttl.version} @@ -381,6 +353,19 @@ + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 + + -Dfile.encoding=UTF-8 + + ${profiles.active} + + exclude + + @@ -405,8 +390,8 @@ public - aliyun nexus - https://maven.aliyun.com/repository/public/ + huawei nexus + https://mirrors.huaweicloud.com/repository/maven/ true @@ -416,8 +401,8 @@ public - aliyun nexus - https://maven.aliyun.com/repository/public/ + huawei nexus + https://mirrors.huaweicloud.com/repository/maven/ true diff --git a/ruoyi-admin/Dockerfile b/ruoyi-admin/Dockerfile index 7bb2b0d0..6033f7e8 100644 --- a/ruoyi-admin/Dockerfile +++ b/ruoyi-admin/Dockerfile @@ -2,9 +2,9 @@ FROM anapsix/alpine-java:8_server-jre_unlimited MAINTAINER Lion Li -RUN mkdir -p /ruoyi/server -RUN mkdir -p /ruoyi/server/logs -RUN mkdir -p /ruoyi/server/temp +RUN mkdir -p /ruoyi/server/logs \ + /ruoyi/server/temp \ + /ruoyi/skywalking/agent WORKDIR /ruoyi/server @@ -14,4 +14,10 @@ EXPOSE ${SERVER_PORT} ADD ./target/ruoyi-admin.jar ./app.jar -ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-Dserver.port=${SERVER_PORT}","-jar", "app.jar"] +ENTRYPOINT ["java", \ + "-Djava.security.egd=file:/dev/./urandom", \ + "-Dserver.port=${SERVER_PORT}", \ + # 应用名称 如果想区分集群节点监控 改成不同的名称即可 +# "-Dskywalking.agent.service_name=ruoyi-server", \ +# "-javaagent:/ruoyi/skywalking/agent/skywalking-agent.jar", \ + "-jar", "app.jar"] diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml index ec98c454..77447e20 100644 --- a/ruoyi-admin/pom.xml +++ b/ruoyi-admin/pom.xml @@ -26,8 +26,8 @@ - mysql - mysql-connector-java + com.mysql + mysql-connector-j @@ -84,6 +84,24 @@ ruoyi-flowable + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + + + + + + + + diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java index 01a4a82c..b0b574c3 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java @@ -42,7 +42,7 @@ public class SysUserOnlineController extends BaseController { @GetMapping("/list") public TableDataInfo list(String ipaddr, String userName) { // 获取所有未过期的 token - List keys = StpUtil.searchTokenValue("", -1, 0, false); + List keys = StpUtil.searchTokenValue("", 0, -1, false); List userOnlineDTOList = new ArrayList<>(); for (String key : keys) { String token = key.replace(CacheConstants.LOGIN_TOKEN_KEY, ""); @@ -83,7 +83,7 @@ public class SysUserOnlineController extends BaseController { public R forceLogout(@PathVariable String tokenId) { try { StpUtil.kickoutByTokenValue(tokenId); - } catch (NotLoginException e) { + } catch (NotLoginException ignored) { } return R.ok(); } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java index 411eee9e..fa763df3 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java @@ -108,10 +108,10 @@ public class SysDeptController extends BaseController { @DeleteMapping("/{deptId}") public R remove(@PathVariable Long deptId) { if (deptService.hasChildByDeptId(deptId)) { - return R.fail("存在下级部门,不允许删除"); + return R.warn("存在下级部门,不允许删除"); } if (deptService.checkDeptExistUser(deptId)) { - return R.fail("部门存在用户,不允许删除"); + return R.warn("部门存在用户,不允许删除"); } deptService.checkDeptDataScope(deptId); return toAjax(deptService.deleteDeptById(deptId)); diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java index 2000fd03..e80f0ee7 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java @@ -117,10 +117,10 @@ public class SysMenuController extends BaseController { @DeleteMapping("/{menuId}") public R remove(@PathVariable("menuId") Long menuId) { if (menuService.hasChildByMenuId(menuId)) { - return R.fail("存在子菜单,不允许删除"); + return R.warn("存在子菜单,不允许删除"); } if (menuService.checkMenuExistRole(menuId)) { - return R.fail("菜单已分配,不允许删除"); + return R.warn("菜单已分配,不允许删除"); } return toAjax(menuService.deleteMenuById(menuId)); } 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 cdba39cc..8dc4876e 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 @@ -66,7 +66,7 @@ public class SysOssConfigController extends BaseController { @RepeatSubmit() @PostMapping() public R add(@Validated(AddGroup.class) @RequestBody SysOssConfigBo bo) { - return toAjax(iSysOssConfigService.insertByBo(bo) ? 1 : 0); + return toAjax(iSysOssConfigService.insertByBo(bo)); } /** @@ -77,7 +77,7 @@ public class SysOssConfigController extends BaseController { @RepeatSubmit() @PutMapping() public R edit(@Validated(EditGroup.class) @RequestBody SysOssConfigBo bo) { - return toAjax(iSysOssConfigService.updateByBo(bo) ? 1 : 0); + return toAjax(iSysOssConfigService.updateByBo(bo)); } /** @@ -90,7 +90,7 @@ public class SysOssConfigController extends BaseController { @DeleteMapping("/{ossConfigIds}") public R remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ossConfigIds) { - return toAjax(iSysOssConfigService.deleteWithValidByIds(Arrays.asList(ossConfigIds), true) ? 1 : 0); + return toAjax(iSysOssConfigService.deleteWithValidByIds(Arrays.asList(ossConfigIds), true)); } /** 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 fac5ddef..606895a7 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 @@ -15,6 +15,8 @@ import com.ruoyi.common.core.validate.QueryGroup; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.file.FileUtils; +import com.ruoyi.oss.core.OssClient; +import com.ruoyi.oss.factory.OssFactory; import com.ruoyi.system.domain.SysOss; import com.ruoyi.system.domain.bo.SysOssBo; import com.ruoyi.system.domain.vo.SysOssVo; @@ -80,7 +82,7 @@ public class SysOssController extends BaseController { if (ObjectUtil.isNull(file)) { throw new ServiceException("上传文件不能为空"); } - SysOss oss = iSysOssService.upload(file); + SysOssVo oss = iSysOssService.upload(file); Map map = new HashMap<>(2); map.put("url", oss.getUrl()); map.put("fileName", oss.getOriginalName()); @@ -96,23 +98,7 @@ public class SysOssController extends BaseController { @SaCheckPermission("system:oss:download") @GetMapping("/download/{ossId}") public void download(@PathVariable Long ossId, HttpServletResponse response) throws IOException { - SysOssVo sysOss = iSysOssService.getById(ossId); - if (ObjectUtil.isNull(sysOss)) { - throw new ServiceException("文件数据不存在!"); - } - FileUtils.setAttachmentResponseHeader(response, sysOss.getOriginalName()); - response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8"); - long data; - try { - data = HttpUtil.download(sysOss.getUrl(), response.getOutputStream(), false); - } catch (HttpException e) { - if (e.getMessage().contains("403")) { - throw new ServiceException("无读取权限, 请在对应的OSS开启'公有读'权限!"); - } else { - throw new ServiceException(e.getMessage()); - } - } - response.setContentLength(Convert.toInt(data)); + iSysOssService.download(ossId,response); } /** @@ -125,7 +111,7 @@ public class SysOssController extends BaseController { @DeleteMapping("/{ossIds}") public R remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ossIds) { - return toAjax(iSysOssService.deleteWithValidByIds(Arrays.asList(ossIds), true) ? 1 : 0); + return toAjax(iSysOssService.deleteWithValidByIds(Arrays.asList(ossIds), true)); } } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java index 5c331681..77a8767d 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java @@ -12,6 +12,7 @@ import com.ruoyi.common.helper.LoginHelper; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.file.MimeTypeUtils; import com.ruoyi.system.domain.SysOss; +import com.ruoyi.system.domain.vo.SysOssVo; import com.ruoyi.system.service.ISysOssService; import com.ruoyi.system.service.ISysUserService; import lombok.RequiredArgsConstructor; @@ -115,7 +116,7 @@ public class SysProfileController extends BaseController { if (!StringUtils.equalsAnyIgnoreCase(extension, MimeTypeUtils.IMAGE_EXTENSION)) { return R.fail("文件格式不正确,请上传" + Arrays.toString(MimeTypeUtils.IMAGE_EXTENSION) + "格式"); } - SysOss oss = iSysOssService.upload(avatarfile); + SysOssVo oss = iSysOssService.upload(avatarfile); String avatar = oss.getUrl(); if (userService.updateUserAvatar(getUsername(), avatar)) { ajax.put("imgUrl", avatar); diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java index 215b53c9..7e358d51 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java @@ -1,6 +1,5 @@ package com.ruoyi.web.controller.system; -import cn.dev33.satoken.annotation.SaCheckLogin; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.dev33.satoken.secure.BCrypt; import cn.hutool.core.bean.BeanUtil; @@ -66,15 +65,6 @@ public class SysUserController extends BaseController { return userService.selectPageUserList(user, pageQuery); } - /** - * 查询用户列表,用于用户选择场景 - */ - @SaCheckLogin - @GetMapping("/selectUser") - public TableDataInfo selectUser(SysUser user, PageQuery pageQuery) { - return userService.selectPageUserList(user, pageQuery); - } - /** * 导出用户列表 */ diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml index 5844a242..98041c09 100644 --- a/ruoyi-admin/src/main/resources/application-dev.yml +++ b/ruoyi-admin/src/main/resources/application-dev.yml @@ -33,7 +33,7 @@ xxl.job: --- # 数据源配置 spring: datasource: - type: com.alibaba.druid.pool.DruidDataSource + type: com.zaxxer.hikari.HikariDataSource # 动态数据源文档 https://www.kancloud.cn/tracy5546/dynamic-datasource/content dynamic: # 性能分析插件(有性能损耗 不建议生产环境使用) @@ -45,6 +45,7 @@ spring: datasource: # 主库数据源 master: + type: ${spring.datasource.type} driverClassName: com.mysql.cj.jdbc.Driver # jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562 # rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题) @@ -54,72 +55,46 @@ spring: # 从库数据源 slave: lazy: true + type: ${spring.datasource.type} driverClassName: com.mysql.cj.jdbc.Driver - url: + url: jdbc:mysql://localhost:3306/ry-flowable-plus?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&nullCatalogMeansCurrent=true username: password: # oracle: +# type: ${spring.datasource.type} # driverClassName: oracle.jdbc.OracleDriver # url: jdbc:oracle:thin:@//localhost:1521/XE # username: ROOT # password: root -# druid: -# validationQuery: SELECT 1 FROM DUAL +# hikari: +# connectionTestQuery: SELECT 1 FROM DUAL # postgres: +# type: ${spring.datasource.type} # 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: +# type: ${spring.datasource.type} # driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver -# url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;rewriteBatchedStatements=true +# url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true # username: SA # password: root - druid: - # 初始连接数 - initialSize: 5 - # 最小连接池数量 - minIdle: 10 + hikari: # 最大连接池数量 - maxActive: 20 + maxPoolSize: 20 + # 最小空闲线程数量 + minIdle: 10 # 配置获取连接等待超时的时间 - maxWait: 60000 - # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 - timeBetweenEvictionRunsMillis: 60000 - # 配置一个连接在池中最小生存的时间,单位是毫秒 - minEvictableIdleTimeMillis: 300000 - # 配置一个连接在池中最大生存的时间,单位是毫秒 - maxEvictableIdleTimeMillis: 900000 - # 配置检测连接是否有效 - validationQuery: SELECT 1 - testWhileIdle: true - testOnBorrow: false - testOnReturn: false - # 注意这个值和druid原生不一致,默认启动了stat - 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 + connectionTimeout: 10000 + # 校验超时时间 + validationTimeout: 5000 + # 空闲连接存活最大时间,默认10分钟 + idleTimeout: 60000 + # 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认30分钟 + maxLifetime: 900000 + # 连接测试query(配置检测连接是否有效) + connectionTestQuery: SELECT 1 --- # redis 单机配置(单机与集群只能开启一个另一个需要注释掉) spring: diff --git a/ruoyi-admin/src/main/resources/application-prod.yml b/ruoyi-admin/src/main/resources/application-prod.yml index 0987874f..970fe4c5 100644 --- a/ruoyi-admin/src/main/resources/application-prod.yml +++ b/ruoyi-admin/src/main/resources/application-prod.yml @@ -36,7 +36,7 @@ xxl.job: --- # 数据源配置 spring: datasource: - type: com.alibaba.druid.pool.DruidDataSource + type: com.zaxxer.hikari.HikariDataSource # 动态数据源文档 https://www.kancloud.cn/tracy5546/dynamic-datasource/content dynamic: # 性能分析插件(有性能损耗 不建议生产环境使用) @@ -48,6 +48,7 @@ spring: datasource: # 主库数据源 master: + type: ${spring.datasource.type} driverClassName: com.mysql.cj.jdbc.Driver # jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562 # rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题) @@ -57,72 +58,46 @@ spring: # 从库数据源 slave: lazy: true + type: ${spring.datasource.type} driverClassName: com.mysql.cj.jdbc.Driver - url: + url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true username: password: # oracle: +# type: ${spring.datasource.type} # driverClassName: oracle.jdbc.OracleDriver # url: jdbc:oracle:thin:@//localhost:1521/XE # username: ROOT # password: root -# druid: -# validationQuery: SELECT 1 FROM DUAL +# hikari: +# connectionTestQuery: SELECT 1 FROM DUAL # postgres: +# type: ${spring.datasource.type} # 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: +# type: ${spring.datasource.type} # driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver -# url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;rewriteBatchedStatements=true +# url: jdbc:sqlserver://localhost:1433;DatabaseName=tempdb;SelectMethod=cursor;encrypt=false;rewriteBatchedStatements=true # username: SA # password: root - druid: - # 初始连接数 - initialSize: 5 - # 最小连接池数量 - minIdle: 10 + hikari: # 最大连接池数量 - maxActive: 20 + maxPoolSize: 20 + # 最小空闲线程数量 + minIdle: 10 # 配置获取连接等待超时的时间 - maxWait: 60000 - # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 - timeBetweenEvictionRunsMillis: 60000 - # 配置一个连接在池中最小生存的时间,单位是毫秒 - minEvictableIdleTimeMillis: 300000 - # 配置一个连接在池中最大生存的时间,单位是毫秒 - maxEvictableIdleTimeMillis: 900000 - # 配置检测连接是否有效 - validationQuery: SELECT 1 - testWhileIdle: true - testOnBorrow: false - testOnReturn: false - # 注意这个值和druid原生不一致,默认启动了stat - 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 + connectionTimeout: 10000 + # 校验超时时间 + validationTimeout: 5000 + # 空闲连接存活最大时间,默认10分钟 + idleTimeout: 60000 + # 此属性控制池中连接的最长生命周期,值0表示无限生命周期,默认30分钟 + maxLifetime: 900000 + # 连接测试query(配置检测连接是否有效) + connectionTestQuery: SELECT 1 --- # redis 单机配置(单机与集群只能开启一个另一个需要注释掉) spring: diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index ab78e332..176cb938 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -115,8 +115,6 @@ sa-token: token-prefix: "Bearer" # jwt秘钥 jwt-secret-key: abcdefghijklmnopqrstuvwxyz - # 是否输出操作日志 - is-log: true # security配置 security: @@ -131,8 +129,6 @@ security: - /favicon.ico - /*/api-docs - /*/api-docs/** - # druid 监控配置 - - /druid/** # actuator 监控配置 - /actuator - /actuator/** diff --git a/ruoyi-admin/src/main/resources/logback.xml b/ruoyi-admin/src/main/resources/logback.xml index b78044b3..40fa33b7 100644 --- a/ruoyi-admin/src/main/resources/logback.xml +++ b/ruoyi-admin/src/main/resources/logback.xml @@ -7,7 +7,7 @@ - + ${console.log.pattern} utf-8 @@ -22,7 +22,7 @@ 1 - + ${log.pattern} utf-8 @@ -42,7 +42,7 @@ 60 - + ${log.pattern} @@ -64,7 +64,7 @@ 60 - + ${log.pattern} @@ -78,7 +78,7 @@ - + 0 @@ -88,7 +88,7 @@ - + 0 @@ -97,12 +97,33 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/ruoyi-admin/src/main/resources/spy.properties b/ruoyi-admin/src/main/resources/spy.properties index bee2392d..abbd8931 100644 --- a/ruoyi-admin/src/main/resources/spy.properties +++ b/ruoyi-admin/src/main/resources/spy.properties @@ -24,3 +24,5 @@ outagedetection=true outagedetectioninterval=2 # 是否过滤 Log filter=true +# 过滤 Log 时所排除的 sql 关键字,以逗号分隔 +exclude=SELECT 1 diff --git a/ruoyi-admin/src/test/java/com/ruoyi/test/AssertUnitTest.java b/ruoyi-admin/src/test/java/com/ruoyi/test/AssertUnitTest.java new file mode 100644 index 00000000..5b9c9f84 --- /dev/null +++ b/ruoyi-admin/src/test/java/com/ruoyi/test/AssertUnitTest.java @@ -0,0 +1,45 @@ +package com.ruoyi.test; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +/** + * 断言单元测试案例 + * + * @author Lion Li + */ +@DisplayName("断言单元测试案例") +public class AssertUnitTest { + + @DisplayName("测试 assertEquals 方法") + @Test + public void testAssertEquals() { + Assertions.assertEquals("666", new String("666")); + Assertions.assertNotEquals("666", new String("666")); + } + + @DisplayName("测试 assertSame 方法") + @Test + public void testAssertSame() { + Object obj = new Object(); + Object obj1 = obj; + Assertions.assertSame(obj, obj1); + Assertions.assertNotSame(obj, obj1); + } + + @DisplayName("测试 assertTrue 方法") + @Test + public void testAssertTrue() { + Assertions.assertTrue(true); + Assertions.assertFalse(true); + } + + @DisplayName("测试 assertNull 方法") + @Test + public void testAssertNull() { + Assertions.assertNull(null); + Assertions.assertNotNull(null); + } + +} diff --git a/ruoyi-admin/src/test/java/com/ruoyi/test/DemoUnitTest.java b/ruoyi-admin/src/test/java/com/ruoyi/test/DemoUnitTest.java new file mode 100644 index 00000000..a40fd827 --- /dev/null +++ b/ruoyi-admin/src/test/java/com/ruoyi/test/DemoUnitTest.java @@ -0,0 +1,70 @@ +package com.ruoyi.test; + +import com.ruoyi.common.config.RuoYiConfig; +import org.junit.jupiter.api.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import java.util.concurrent.TimeUnit; + +/** + * 单元测试案例 + * + * @author Lion Li + */ +@SpringBootTest // 此注解只能在 springboot 主包下使用 需包含 main 方法与 yml 配置文件 +@DisplayName("单元测试案例") +public class DemoUnitTest { + + @Autowired + private RuoYiConfig ruoYiConfig; + + @DisplayName("测试 @SpringBootTest @Test @DisplayName 注解") + @Test + public void testTest() { + System.out.println(ruoYiConfig); + } + + @Disabled + @DisplayName("测试 @Disabled 注解") + @Test + public void testDisabled() { + System.out.println(ruoYiConfig); + } + + @Timeout(value = 2L, unit = TimeUnit.SECONDS) + @DisplayName("测试 @Timeout 注解") + @Test + public void testTimeout() throws InterruptedException { + Thread.sleep(3000); + System.out.println(ruoYiConfig); + } + + + @DisplayName("测试 @RepeatedTest 注解") + @RepeatedTest(3) + public void testRepeatedTest() { + System.out.println(666); + } + + @BeforeAll + public static void testBeforeAll() { + System.out.println("@BeforeAll =================="); + } + + @BeforeEach + public void testBeforeEach() { + System.out.println("@BeforeEach =================="); + } + + @AfterEach + public void testAfterEach() { + System.out.println("@AfterEach =================="); + } + + @AfterAll + public static void testAfterAll() { + System.out.println("@AfterAll =================="); + } + +} diff --git a/ruoyi-admin/src/test/java/com/ruoyi/test/ParamUnitTest.java b/ruoyi-admin/src/test/java/com/ruoyi/test/ParamUnitTest.java new file mode 100644 index 00000000..04bf1b5c --- /dev/null +++ b/ruoyi-admin/src/test/java/com/ruoyi/test/ParamUnitTest.java @@ -0,0 +1,72 @@ +package com.ruoyi.test; + +import com.ruoyi.common.enums.UserType; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.NullSource; +import org.junit.jupiter.params.provider.ValueSource; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; + +/** + * 带参数单元测试案例 + * + * @author Lion Li + */ +@DisplayName("带参数单元测试案例") +public class ParamUnitTest { + + @DisplayName("测试 @ValueSource 注解") + @ParameterizedTest + @ValueSource(strings = {"t1", "t2", "t3"}) + public void testValueSource(String str) { + System.out.println(str); + } + + @DisplayName("测试 @NullSource 注解") + @ParameterizedTest + @NullSource + public void testNullSource(String str) { + System.out.println(str); + } + + @DisplayName("测试 @EnumSource 注解") + @ParameterizedTest + @EnumSource(UserType.class) + public void testEnumSource(UserType type) { + System.out.println(type.getUserType()); + } + + @DisplayName("测试 @MethodSource 注解") + @ParameterizedTest + @MethodSource("getParam") + public void testMethodSource(String str) { + System.out.println(str); + } + + public static Stream getParam() { + List list = new ArrayList<>(); + list.add("t1"); + list.add("t2"); + list.add("t3"); + return list.stream(); + } + + @BeforeEach + public void testBeforeEach() { + System.out.println("@BeforeEach =================="); + } + + @AfterEach + public void testAfterEach() { + System.out.println("@AfterEach =================="); + } + + +} diff --git a/ruoyi-admin/src/test/java/com/ruoyi/test/TagUnitTest.java b/ruoyi-admin/src/test/java/com/ruoyi/test/TagUnitTest.java new file mode 100644 index 00000000..04240a07 --- /dev/null +++ b/ruoyi-admin/src/test/java/com/ruoyi/test/TagUnitTest.java @@ -0,0 +1,54 @@ +package com.ruoyi.test; + +import org.junit.jupiter.api.*; +import org.springframework.boot.test.context.SpringBootTest; + +/** + * 标签单元测试案例 + * + * @author Lion Li + */ +@SpringBootTest +@DisplayName("标签单元测试案例") +public class TagUnitTest { + + @Tag("dev") + @DisplayName("测试 @Tag dev") + @Test + public void testTagDev() { + System.out.println("dev"); + } + + @Tag("prod") + @DisplayName("测试 @Tag prod") + @Test + public void testTagProd() { + System.out.println("prod"); + } + + @Tag("local") + @DisplayName("测试 @Tag local") + @Test + public void testTagLocal() { + System.out.println("local"); + } + + @Tag("exclude") + @DisplayName("测试 @Tag exclude") + @Test + public void testTagExclude() { + System.out.println("exclude"); + } + + @BeforeEach + public void testBeforeEach() { + System.out.println("@BeforeEach =================="); + } + + @AfterEach + public void testAfterEach() { + System.out.println("@AfterEach =================="); + } + + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java deleted file mode 100644 index 51eaf082..00000000 --- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.ruoyi.common.annotation; - -import cn.dev33.satoken.annotation.SaIgnore; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * 匿名访问不鉴权注解 - * - * @author ruoyi - * @deprecated 将在后续版本使用Sa-Token注解 {@link SaIgnore} 代替 - */ -@Deprecated -@Target({ElementType.METHOD, ElementType.TYPE}) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface Anonymous { -} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DictDataMapper.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DictDataMapper.java new file mode 100644 index 00000000..5c14a552 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DictDataMapper.java @@ -0,0 +1,27 @@ +package com.ruoyi.common.annotation; + +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.ruoyi.common.jackson.DictDataJsonSerializer; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 字典数据映射注解 + * + * @author itino + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD, ElementType.METHOD}) +@JacksonAnnotationsInside +@JsonSerialize(using = DictDataJsonSerializer.class) +public @interface DictDataMapper { + + /** + * 设置字典的type值 (如: sys_user_sex) + */ + String dictType() default ""; +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java new file mode 100644 index 00000000..f007b8c8 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java @@ -0,0 +1,93 @@ +package com.ruoyi.common.constant; + +/** + * 返回状态码 + * + * @author Lion Li + */ +public interface HttpStatus { + /** + * 操作成功 + */ + int SUCCESS = 200; + + /** + * 对象创建成功 + */ + int CREATED = 201; + + /** + * 请求已经被接受 + */ + int ACCEPTED = 202; + + /** + * 操作已经执行成功,但是没有返回数据 + */ + int NO_CONTENT = 204; + + /** + * 资源已被移除 + */ + int MOVED_PERM = 301; + + /** + * 重定向 + */ + int SEE_OTHER = 303; + + /** + * 资源没有被修改 + */ + int NOT_MODIFIED = 304; + + /** + * 参数列表错误(缺少,格式不匹配) + */ + int BAD_REQUEST = 400; + + /** + * 未授权 + */ + int UNAUTHORIZED = 401; + + /** + * 访问受限,授权过期 + */ + int FORBIDDEN = 403; + + /** + * 资源,服务未找到 + */ + int NOT_FOUND = 404; + + /** + * 不允许的http方法 + */ + int BAD_METHOD = 405; + + /** + * 资源冲突,或者资源被锁 + */ + int CONFLICT = 409; + + /** + * 不支持的数据,媒体类型 + */ + int UNSUPPORTED_TYPE = 415; + + /** + * 系统内部错误 + */ + int ERROR = 500; + + /** + * 接口未实现 + */ + int NOT_IMPLEMENTED = 501; + + /** + * 系统警告消息 + */ + int WARN = 601; +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java index 5a20f9d0..bd316079 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java @@ -2,6 +2,8 @@ package com.ruoyi.common.core.domain; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.TableField; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; import lombok.Data; import java.io.Serializable; @@ -23,6 +25,7 @@ public class BaseEntity implements Serializable { /** * 搜索值 */ + @JsonIgnore @TableField(exist = false) private String searchValue; @@ -53,6 +56,7 @@ public class BaseEntity implements Serializable { /** * 请求参数 */ + @JsonInclude(JsonInclude.Include.NON_EMPTY) @TableField(exist = false) private Map params = new HashMap<>(); diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java index 1c7b1d86..381a6f60 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/R.java @@ -1,5 +1,6 @@ package com.ruoyi.common.core.domain; +import com.ruoyi.common.constant.HttpStatus; import lombok.Data; import lombok.NoArgsConstructor; @@ -67,6 +68,27 @@ public class R implements Serializable { return restResult(null, code, msg); } + /** + * 返回警告消息 + * + * @param msg 返回内容 + * @return 警告消息 + */ + public static R warn(String msg) { + return restResult(null, HttpStatus.WARN, msg); + } + + /** + * 返回警告消息 + * + * @param msg 返回内容 + * @param data 数据对象 + * @return 警告消息 + */ + public static R warn(String msg, T data) { + return restResult(data, HttpStatus.WARN, msg); + } + private static R restResult(T data, int code, String msg) { R r = new R<>(); r.setCode(code); diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java index ca76e76c..c1cbe3f2 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java @@ -12,7 +12,6 @@ import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; /** * 构建可重复读取inputStream的request @@ -27,7 +26,7 @@ public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper { request.setCharacterEncoding(Constants.UTF8); response.setCharacterEncoding(Constants.UTF8); - body = IoUtil.readUtf8(request.getInputStream()).getBytes(StandardCharsets.UTF_8); + body = IoUtil.readBytes(request.getInputStream(), false); } @Override diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java index f1b51315..3646f1fe 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java @@ -1,6 +1,7 @@ package com.ruoyi.common.filter; import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.StrUtil; import cn.hutool.http.HtmlUtil; import com.ruoyi.common.utils.StringUtils; import org.springframework.http.HttpHeaders; @@ -50,7 +51,7 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { } // 为空,直接返回 - String json = IoUtil.read(super.getInputStream(), StandardCharsets.UTF_8); + String json = StrUtil.str(IoUtil.readBytes(super.getInputStream(), false), StandardCharsets.UTF_8); if (StringUtils.isEmpty(json)) { return super.getInputStream(); } @@ -88,7 +89,6 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { /** * 是否是Json请求 - * */ public boolean isJsonRequest() { String header = super.getHeader(HttpHeaders.CONTENT_TYPE); diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/helper/LoginHelper.java b/ruoyi-common/src/main/java/com/ruoyi/common/helper/LoginHelper.java index f1216662..a82f4195 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/helper/LoginHelper.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/helper/LoginHelper.java @@ -2,6 +2,7 @@ package com.ruoyi.common.helper; import cn.dev33.satoken.context.SaHolder; import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ObjectUtil; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.domain.model.LoginUser; @@ -80,18 +81,12 @@ public class LoginHelper { LoginUser loginUser = getLoginUser(); if (ObjectUtil.isNull(loginUser)) { String loginId = StpUtil.getLoginIdAsString(); - String userId = null; - for (UserType value : UserType.values()) { - if (StringUtils.contains(loginId, value.getUserType())) { - String[] strs = StringUtils.split(loginId, JOIN_CODE); - // 用户id在总是在最后 - userId = strs[strs.length - 1]; - } - } - if (StringUtils.isBlank(userId)) { + String[] strs = StringUtils.split(loginId, JOIN_CODE); + if (!ArrayUtil.containsAny(strs, UserType.values())) { throw new UtilException("登录用户: LoginId异常 => " + loginId); } - return Long.parseLong(userId); + // 用户id在总是在最后 + return Long.parseLong(strs[strs.length - 1]); } return loginUser.getUserId(); } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/jackson/DictDataJsonSerializer.java b/ruoyi-common/src/main/java/com/ruoyi/common/jackson/DictDataJsonSerializer.java new file mode 100644 index 00000000..caa059b9 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/jackson/DictDataJsonSerializer.java @@ -0,0 +1,56 @@ +package com.ruoyi.common.jackson; + +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.BeanProperty; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.ContextualSerializer; +import com.ruoyi.common.annotation.DictDataMapper; +import com.ruoyi.common.core.service.DictService; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.spring.SpringUtils; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeansException; + +import java.io.IOException; +import java.util.Objects; + +/** + * 字典数据json序列化工具 + * + * @author itino + */ +@Slf4j +public class DictDataJsonSerializer extends JsonSerializer implements ContextualSerializer { + + private String dictType; + + @Override + public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + try { + DictService dictService = SpringUtils.getBean(DictService.class); + if (ObjectUtil.isNotNull(dictService)) { + String label = dictService.getDictLabel(dictType, value); + gen.writeString(StringUtils.isNotBlank(label) ? label : value); + } else { + gen.writeString(value); + } + } catch (BeansException e) { + log.error("字典数据未查到, 采用默认处理 => {}", e.getMessage()); + gen.writeString(value); + } + } + + @Override + public JsonSerializer createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException { + DictDataMapper anno = property.getAnnotation(DictDataMapper.class); + if (Objects.nonNull(anno) && StrUtil.isNotBlank(anno.dictType())) { + this.dictType = anno.dictType(); + return this; + } + return prov.findValueSerializer(property.getType(), property); + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java index 7012a01f..91ddd3f6 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java @@ -11,6 +11,7 @@ import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; +import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; @@ -19,6 +20,9 @@ import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; /** * 客户端工具类 @@ -70,6 +74,31 @@ public class ServletUtils extends ServletUtil { return Convert.toBool(getRequest().getParameter(name), defaultValue); } + /** + * 获得所有请求参数 + * + * @param request 请求对象{@link ServletRequest} + * @return Map + */ + public static Map getParams(ServletRequest request) { + final Map map = request.getParameterMap(); + return Collections.unmodifiableMap(map); + } + + /** + * 获得所有请求参数 + * + * @param request 请求对象{@link ServletRequest} + * @return Map + */ + public static Map getParamMap(ServletRequest request) { + Map params = new HashMap<>(); + for (Map.Entry entry : getParams(request).entrySet()) { + params.put(entry.getKey(), StringUtils.join(entry.getValue(), ",")); + } + return params; + } + /** * 获取request */ diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/RedisUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/RedisUtils.java index c14b3938..80f5f528 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/RedisUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/RedisUtils.java @@ -327,6 +327,17 @@ public class RedisUtils { return rMap.getAll(rMap.keySet()); } + /** + * 获得缓存Map的key列表 + * + * @param key 缓存的键值 + * @return key列表 + */ + public static Set getCacheMapKeySet(final String key) { + RMap rMap = CLIENT.getMap(key); + return rMap.keySet(); + } + /** * 往Hash中存入数据 * diff --git a/ruoyi-demo/pom.xml b/ruoyi-demo/pom.xml index 2a0335cd..1331fc62 100644 --- a/ruoyi-demo/pom.xml +++ b/ruoyi-demo/pom.xml @@ -36,7 +36,7 @@ - + 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 caed9756..3bd2867e 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 @@ -46,7 +46,7 @@ public class TestBatchController extends BaseController { testDemo.setValue("测试新增"); list.add(testDemo); } - return toAjax(testDemoMapper.insertBatch(list) ? 1 : 0); + return toAjax(testDemoMapper.insertBatch(list)); } /** @@ -74,7 +74,7 @@ public class TestBatchController extends BaseController { testDemo.setId(null); } } - return toAjax(testDemoMapper.insertOrUpdateBatch(list) ? 1 : 0); + return toAjax(testDemoMapper.insertOrUpdateBatch(list)); } /** 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 33b34128..873facc3 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 @@ -119,7 +119,7 @@ public class TestDemoController extends BaseController { // 使用校验工具对标 @Validated(AddGroup.class) 注解 // 用于在非 Controller 的地方校验对象 ValidatorUtils.validate(bo, AddGroup.class); - return toAjax(iTestDemoService.insertByBo(bo) ? 1 : 0); + return toAjax(iTestDemoService.insertByBo(bo)); } /** @@ -130,7 +130,7 @@ public class TestDemoController extends BaseController { @RepeatSubmit @PutMapping() public R edit(@Validated(EditGroup.class) @RequestBody TestDemoBo bo) { - return toAjax(iTestDemoService.updateByBo(bo) ? 1 : 0); + return toAjax(iTestDemoService.updateByBo(bo)); } /** @@ -143,6 +143,6 @@ public class TestDemoController extends BaseController { @DeleteMapping("/{ids}") public R remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) { - return toAjax(iTestDemoService.deleteWithValidByIds(Arrays.asList(ids), true) ? 1 : 0); + return toAjax(iTestDemoService.deleteWithValidByIds(Arrays.asList(ids), true)); } } diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestTreeController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestTreeController.java index 52d881ed..db54230c 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestTreeController.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestTreeController.java @@ -78,7 +78,7 @@ public class TestTreeController extends BaseController { @RepeatSubmit @PostMapping() public R add(@Validated(AddGroup.class) @RequestBody TestTreeBo bo) { - return toAjax(iTestTreeService.insertByBo(bo) ? 1 : 0); + return toAjax(iTestTreeService.insertByBo(bo)); } /** @@ -89,7 +89,7 @@ public class TestTreeController extends BaseController { @RepeatSubmit @PutMapping() public R edit(@Validated(EditGroup.class) @RequestBody TestTreeBo bo) { - return toAjax(iTestTreeService.updateByBo(bo) ? 1 : 0); + return toAjax(iTestTreeService.updateByBo(bo)); } /** @@ -102,6 +102,6 @@ public class TestTreeController extends BaseController { @DeleteMapping("/{ids}") public R remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] ids) { - return toAjax(iTestTreeService.deleteWithValidByIds(Arrays.asList(ids), true) ? 1 : 0); + return toAjax(iTestTreeService.deleteWithValidByIds(Arrays.asList(ids), true)); } } diff --git a/ruoyi-extend/ruoyi-monitor-admin/Dockerfile b/ruoyi-extend/ruoyi-monitor-admin/Dockerfile index b506a2dd..02b741f4 100644 --- a/ruoyi-extend/ruoyi-monitor-admin/Dockerfile +++ b/ruoyi-extend/ruoyi-monitor-admin/Dockerfile @@ -2,7 +2,6 @@ FROM anapsix/alpine-java:8_server-jre_unlimited MAINTAINER Lion Li -RUN mkdir -p /ruoyi/monitor RUN mkdir -p /ruoyi/monitor/logs WORKDIR /ruoyi/monitor diff --git a/ruoyi-extend/ruoyi-xxl-job-admin/Dockerfile b/ruoyi-extend/ruoyi-xxl-job-admin/Dockerfile index f7221bdf..bd61580a 100644 --- a/ruoyi-extend/ruoyi-xxl-job-admin/Dockerfile +++ b/ruoyi-extend/ruoyi-xxl-job-admin/Dockerfile @@ -2,7 +2,6 @@ FROM anapsix/alpine-java:8_server-jre_unlimited MAINTAINER Lion Li -RUN mkdir -p /ruoyi/xxljob RUN mkdir -p /ruoyi/xxljob/logs WORKDIR /ruoyi/xxljob @@ -14,4 +13,4 @@ EXPOSE 9100 ADD ./target/ruoyi-xxl-job-admin.jar ./app.jar -ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"] \ No newline at end of file +ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "app.jar"] diff --git a/ruoyi-extend/ruoyi-xxl-job-admin/pom.xml b/ruoyi-extend/ruoyi-xxl-job-admin/pom.xml index d68066da..936a1ab0 100644 --- a/ruoyi-extend/ruoyi-xxl-job-admin/pom.xml +++ b/ruoyi-extend/ruoyi-xxl-job-admin/pom.xml @@ -64,8 +64,8 @@ - mysql - mysql-connector-java + com.mysql + mysql-connector-j diff --git a/ruoyi-framework/pom.xml b/ruoyi-framework/pom.xml index f139717e..274fa0c4 100644 --- a/ruoyi-framework/pom.xml +++ b/ruoyi-framework/pom.xml @@ -40,12 +40,6 @@ spring-boot-starter-aop - - - com.alibaba - druid-spring-boot-starter - - p6spy @@ -62,17 +56,17 @@ spring-boot-admin-starter-client + + com.alibaba + transmittable-thread-local + + com.ruoyi ruoyi-common - - com.yomahub - tlog-web-spring-boot-starter - - diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java index 0159bc3c..3b6a858a 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java @@ -21,7 +21,6 @@ import org.aspectj.lang.annotation.Aspect; import org.springframework.stereotype.Component; import org.springframework.validation.BindingResult; import org.springframework.web.multipart.MultipartFile; -import org.springframework.web.servlet.HandlerMapping; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -92,7 +91,6 @@ public class LogAspect { SpringUtils.getBean(OperLogService.class).recordOper(operLog); } catch (Exception exp) { // 记录本地异常日志 - log.error("==前置通知异常=="); log.error("异常信息:{}", exp.getMessage()); exp.printStackTrace(); } @@ -135,8 +133,9 @@ public class LogAspect { String params = argsArrayToString(joinPoint.getArgs()); operLog.setOperParam(StringUtils.substring(params, 0, 2000)); } else { - Map paramsMap = (Map) ServletUtils.getRequest().getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE); - operLog.setOperParam(StringUtils.substring(paramsMap.toString(), 0, 2000)); + Map paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest()); + MapUtil.removeAny(paramsMap, EXCLUDE_PROPERTIES); + operLog.setOperParam(StringUtils.substring(JsonUtils.toJsonString(paramsMap), 0, 2000)); } } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java deleted file mode 100644 index 6f7a82ec..00000000 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.ruoyi.framework.config; - -import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties; -import com.alibaba.druid.util.Utils; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.boot.web.servlet.FilterRegistrationBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -import javax.servlet.*; -import java.io.IOException; - -/** - * druid 配置多数据源 - * - * @author ruoyi - */ -@Configuration -public class DruidConfig { - - /** - * 去除监控页面底部的广告 - */ - @SuppressWarnings({"rawtypes", "unchecked"}) - @Bean - @ConditionalOnProperty(name = "spring.datasource.druid.statViewServlet.enabled", havingValue = "true") - public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties) { - // 获取web监控页面的参数 - DruidStatProperties.StatViewServlet config = properties.getStatViewServlet(); - // 提取common.js的配置路径 - String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*"; - String commonJsPattern = pattern.replaceAll("\\*", "js/common.js"); - final String filePath = "support/http/resources/js/common.js"; - // 创建filter进行过滤 - Filter filter = new Filter() { - @Override - public void init(javax.servlet.FilterConfig filterConfig) throws ServletException { - } - - @Override - public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) - throws IOException, ServletException { - chain.doFilter(request, response); - // 重置缓冲区,响应头不会被重置 -// response.resetBuffer(); - // 获取common.js - String text = Utils.readFromResource(filePath); - // 正则替换banner, 除去底部的广告信息 - text = text.replaceAll("
", ""); - text = text.replaceAll("powered.*?shrek.wang", ""); - response.getWriter().write(text); - } - - @Override - public void destroy() { - } - }; - FilterRegistrationBean registrationBean = new FilterRegistrationBean(); - registrationBean.setFilter(filter); - registrationBean.addUrlPatterns(commonJsPattern); - return registrationBean; - } -} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java index f43ecab7..ea83338b 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java @@ -1,7 +1,6 @@ package com.ruoyi.framework.config; import com.ruoyi.framework.interceptor.PlusWebInvokeTimeInterceptor; -import com.yomahub.tlog.web.interceptor.TLogWebInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.cors.CorsConfiguration; @@ -21,8 +20,6 @@ public class ResourcesConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { - // 全局链路跟踪拦截器 - registry.addInterceptor(new TLogWebInterceptor()); // 全局访问性能拦截 registry.addInterceptor(new PlusWebInvokeTimeInterceptor()); } 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 a7c51fa6..29122866 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,8 +5,6 @@ import cn.dev33.satoken.jwt.StpLogicJwtForSimple; import cn.dev33.satoken.router.SaRouter; import cn.dev33.satoken.stp.StpLogic; import cn.dev33.satoken.stp.StpUtil; -import com.ruoyi.common.utils.spring.SpringUtils; -import com.ruoyi.framework.config.properties.ExcludeUrlProperties; import com.ruoyi.framework.config.properties.SecurityProperties; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -34,14 +32,10 @@ public class SaTokenConfig implements WebMvcConfigurer { public void addInterceptors(InterceptorRegistry registry) { // 注册路由拦截器,自定义验证规则 registry.addInterceptor(new SaInterceptor(handler -> { - // 自定义注解 @Anonymous 匿名访问配置,后续版本将删除 - ExcludeUrlProperties excludeUrlProperties = SpringUtils.getBean(ExcludeUrlProperties.class); // 登录验证 -- 排除多个路径 SaRouter // 获取所有的 .match("/**") - // 排除下不需要拦截的(每次匹配) - .notMatch(excludeUrlProperties.getExcludes()) // 对未排除的路径进行检查 .check(() -> { // 检查是否登录 是否有token diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/TLogConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/TLogConfig.java deleted file mode 100644 index 5ae55add..00000000 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/TLogConfig.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.ruoyi.framework.config; - -import com.yomahub.tlog.springboot.TLogWebAutoConfiguration; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.context.annotation.Configuration; - -/** - * 整合 TLog 框架配置 - * - * @author Lion Li - * @since 3.3.0 - */ -@Configuration -// 排除 web 自动配置 自定义实现 -@EnableAutoConfiguration(exclude = TLogWebAutoConfiguration.class) -public class TLogConfig { - -} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/ExcludeUrlProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/ExcludeUrlProperties.java deleted file mode 100644 index 99d2eae8..00000000 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/ExcludeUrlProperties.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.ruoyi.framework.config.properties; - -import cn.dev33.satoken.annotation.SaIgnore; -import cn.dev33.satoken.interceptor.SaInterceptor; -import cn.hutool.core.util.ReUtil; -import com.ruoyi.common.annotation.Anonymous; -import com.ruoyi.common.utils.spring.SpringUtils; -import lombok.Getter; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.context.annotation.Lazy; -import org.springframework.core.annotation.AnnotationUtils; -import org.springframework.stereotype.Component; -import org.springframework.web.method.HandlerMethod; -import org.springframework.web.servlet.mvc.method.RequestMappingInfo; -import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; -import org.springframework.web.util.pattern.PathPattern; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.util.*; -import java.util.regex.Pattern; - -/** - * 设置注解允许匿名访问的url - * - * @author Lion Li - * @deprecated 将在后续版本使用Sa-Token注解 {@link SaIgnore} 代替, - * 底层过滤方法详见 {@link SaInterceptor#preHandle(HttpServletRequest, HttpServletResponse, Object)} - */ -@Deprecated -@Lazy -@Component -public class ExcludeUrlProperties implements InitializingBean { - - private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}"); - - @Getter - private final List excludes = new ArrayList<>(); - - @Override - public void afterPropertiesSet() { - String asterisk = "*"; - RequestMappingHandlerMapping mapping = SpringUtils.getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping.class); - Map map = mapping.getHandlerMethods(); - - map.keySet().forEach(info -> { - HandlerMethod handlerMethod = map.get(info); - - // 获取方法上边的注解 替代path variable 为 * - Anonymous method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Anonymous.class); - Optional.ofNullable(method).ifPresent(anonymous -> { - Set patterns = info.getPathPatternsCondition().getPatterns(); - patterns.forEach(url -> { - excludes.add(ReUtil.replaceAll(url.getPatternString(), PATTERN, asterisk)); - }); - }); - - // 获取类上边的注解, 替代path variable 为 * - Anonymous controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Anonymous.class); - Optional.ofNullable(controller).ifPresent(anonymous -> { - Set patterns = info.getPathPatternsCondition().getPatterns(); - patterns.forEach(url -> { - excludes.add(ReUtil.replaceAll(url.getPatternString(), PATTERN, asterisk)); - }); - }); - }); - } - -} 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 9c48c135..a9de17e6 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 @@ -102,6 +102,20 @@ public class UserActionListener implements SaTokenListener { public void doUntieDisable(String loginType, Object loginId, String service) { } + /** + * 每次打开二级认证时触发 + */ + @Override + public void doOpenSafe(String loginType, String tokenValue, String service, long safeTime) { + } + + /** + * 每次创建Session时触发 + */ + @Override + public void doCloseSafe(String loginType, String tokenValue, String service) { + } + /** * 每次创建Session时触发 */ 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 e04d528a..40f2d27c 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 @@ -105,7 +105,7 @@ public class GlobalExceptionHandler { public R handleServiceException(ServiceException e, HttpServletRequest request) { log.error(e.getMessage(), e); Integer code = e.getCode(); - return ObjectUtil.isNotNull(code) ? R.fail(code.intValue(), e.getMessage()) : R.fail(e.getMessage()); + return ObjectUtil.isNotNull(code) ? R.fail(code, e.getMessage()) : R.fail(e.getMessage()); } /** diff --git a/ruoyi-generator/src/main/resources/vm/java/controller.java.vm b/ruoyi-generator/src/main/resources/vm/java/controller.java.vm index 1b2bc136..3edbc338 100644 --- a/ruoyi-generator/src/main/resources/vm/java/controller.java.vm +++ b/ruoyi-generator/src/main/resources/vm/java/controller.java.vm @@ -89,7 +89,7 @@ public class ${ClassName}Controller extends BaseController { @RepeatSubmit() @PostMapping() public R add(@Validated(AddGroup.class) @RequestBody ${ClassName}Bo bo) { - return toAjax(i${ClassName}Service.insertByBo(bo) ? 1 : 0); + return toAjax(i${ClassName}Service.insertByBo(bo)); } /** @@ -100,7 +100,7 @@ public class ${ClassName}Controller extends BaseController { @RepeatSubmit() @PutMapping() public R edit(@Validated(EditGroup.class) @RequestBody ${ClassName}Bo bo) { - return toAjax(i${ClassName}Service.updateByBo(bo) ? 1 : 0); + return toAjax(i${ClassName}Service.updateByBo(bo)); } /** @@ -113,6 +113,6 @@ public class ${ClassName}Controller extends BaseController { @DeleteMapping("/{${pkColumn.javaField}s}") public R remove(@NotEmpty(message = "主键不能为空") @PathVariable ${pkColumn.javaType}[] ${pkColumn.javaField}s) { - return toAjax(i${ClassName}Service.deleteWithValidByIds(Arrays.asList(${pkColumn.javaField}s), true) ? 1 : 0); + return toAjax(i${ClassName}Service.deleteWithValidByIds(Arrays.asList(${pkColumn.javaField}s), true)); } } diff --git a/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm index d44e082f..01a7367f 100644 --- a/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm +++ b/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm @@ -136,24 +136,9 @@ #end diff --git a/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm index f7c1bd02..d0f4f8bc 100644 --- a/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm +++ b/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm @@ -148,18 +148,8 @@ #end diff --git a/ruoyi-job/pom.xml b/ruoyi-job/pom.xml index 632faf96..a53b53bb 100644 --- a/ruoyi-job/pom.xml +++ b/ruoyi-job/pom.xml @@ -29,11 +29,6 @@ xxl-job-core - - com.yomahub - tlog-xxljob-spring-boot-starter - - diff --git a/ruoyi-job/src/main/java/com/ruoyi/job/service/SampleService.java b/ruoyi-job/src/main/java/com/ruoyi/job/service/SampleService.java index 20afa2e6..4ca170be 100644 --- a/ruoyi-job/src/main/java/com/ruoyi/job/service/SampleService.java +++ b/ruoyi-job/src/main/java/com/ruoyi/job/service/SampleService.java @@ -12,7 +12,6 @@ import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.util.Arrays; -import java.util.concurrent.TimeUnit; /** * XxlJob开发示例(Bean模式) @@ -39,7 +38,6 @@ public class SampleService { for (int i = 0; i < 5; i++) { XxlJobHelper.log("beat at:" + i); - TimeUnit.SECONDS.sleep(2); } // default success } diff --git a/ruoyi-oss/src/main/java/com/ruoyi/oss/constant/OssConstant.java b/ruoyi-oss/src/main/java/com/ruoyi/oss/constant/OssConstant.java index ff88c117..06202d0f 100644 --- a/ruoyi-oss/src/main/java/com/ruoyi/oss/constant/OssConstant.java +++ b/ruoyi-oss/src/main/java/com/ruoyi/oss/constant/OssConstant.java @@ -28,7 +28,7 @@ public interface OssConstant { /** * 云服务商 */ - String[] CLOUD_SERVICE = new String[] {"aliyun", "qcloud", "qiniu"}; + String[] CLOUD_SERVICE = new String[] {"aliyun", "qcloud", "qiniu", "obs"}; /** * https 状态 diff --git a/ruoyi-oss/src/main/java/com/ruoyi/oss/core/OssClient.java b/ruoyi-oss/src/main/java/com/ruoyi/oss/core/OssClient.java index 15833d3c..fe409ce7 100644 --- a/ruoyi-oss/src/main/java/com/ruoyi/oss/core/OssClient.java +++ b/ruoyi-oss/src/main/java/com/ruoyi/oss/core/OssClient.java @@ -1,7 +1,9 @@ package com.ruoyi.oss.core; +import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.IdUtil; import com.amazonaws.ClientConfiguration; +import com.amazonaws.HttpMethod; import com.amazonaws.Protocol; import com.amazonaws.auth.AWSCredentials; import com.amazonaws.auth.AWSCredentialsProvider; @@ -16,12 +18,15 @@ import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.oss.constant.OssConstant; import com.ruoyi.oss.entity.UploadResult; +import com.ruoyi.oss.enumd.AccessPolicyType; import com.ruoyi.oss.enumd.PolicyType; import com.ruoyi.oss.exception.OssException; import com.ruoyi.oss.properties.OssProperties; import java.io.ByteArrayInputStream; import java.io.InputStream; +import java.net.URL; +import java.util.Date; /** * S3 存储协议 所有兼容S3协议的云厂商均支持 @@ -57,7 +62,7 @@ public class OssClient { .withClientConfiguration(clientConfig) .withCredentials(credentialsProvider) .disableChunkedEncoding(); - if (!StringUtils.containsAny(properties.getEndpoint(), OssConstant.CLOUD_SERVICE)){ + if (!StringUtils.containsAny(properties.getEndpoint(), OssConstant.CLOUD_SERVICE)) { // minio 使用https限制使用域名访问 需要此配置 站点填域名 build.enablePathStyleAccess(); } @@ -79,9 +84,10 @@ public class OssClient { return; } CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName); - createBucketRequest.setCannedAcl(CannedAccessControlList.PublicRead); + AccessPolicyType accessPolicy = getAccessPolicy(); + createBucketRequest.setCannedAcl(accessPolicy.getAcl()); client.createBucket(createBucketRequest); - client.setBucketPolicy(bucketName, getPolicy(bucketName, PolicyType.READ)); + client.setBucketPolicy(bucketName, getPolicy(bucketName, accessPolicy.getPolicyType())); } catch (Exception e) { throw new OssException("创建Bucket失败, 请核对配置信息:[" + e.getMessage() + "]"); } @@ -92,13 +98,16 @@ public class OssClient { } public UploadResult upload(InputStream inputStream, String path, String contentType) { + if (!(inputStream instanceof ByteArrayInputStream)) { + inputStream = new ByteArrayInputStream(IoUtil.readBytes(inputStream)); + } try { ObjectMetadata metadata = new ObjectMetadata(); metadata.setContentType(contentType); metadata.setContentLength(inputStream.available()); PutObjectRequest putObjectRequest = new PutObjectRequest(properties.getBucketName(), path, inputStream, metadata); // 设置上传对象的 Acl 为公共读 - putObjectRequest.setCannedAcl(CannedAccessControlList.PublicRead); + putObjectRequest.setCannedAcl(getAccessPolicy().getAcl()); client.putObject(putObjectRequest); } catch (Exception e) { throw new OssException("上传文件失败,请检查配置信息:[" + e.getMessage() + "]"); @@ -111,7 +120,7 @@ public class OssClient { try { client.deleteObject(properties.getBucketName(), path); } catch (Exception e) { - throw new OssException("上传文件失败,请检查配置信息:[" + e.getMessage() + "]"); + throw new OssException("删除文件失败,请检查配置信息:[" + e.getMessage() + "]"); } } @@ -129,16 +138,23 @@ public class OssClient { * @param path 完整文件路径 */ public ObjectMetadata getObjectMetadata(String path) { + path = path.replace(getUrl() + "/", ""); S3Object object = client.getObject(properties.getBucketName(), path); return object.getObjectMetadata(); } + public InputStream getObjectContent(String path) { + path = path.replace(getUrl() + "/", ""); + S3Object object = client.getObject(properties.getBucketName(), path); + return object.getObjectContent(); + } + public String getUrl() { String domain = properties.getDomain(); String endpoint = properties.getEndpoint(); String header = OssConstant.IS_HTTPS.equals(properties.getIsHttps()) ? "https://" : "http://"; // 云服务商直接返回 - if (StringUtils.containsAny(endpoint, OssConstant.CLOUD_SERVICE)){ + if (StringUtils.containsAny(endpoint, OssConstant.CLOUD_SERVICE)) { if (StringUtils.isNotBlank(domain)) { return header + domain; } @@ -167,6 +183,24 @@ public class OssClient { return configKey; } + public String getPrivateUrl(String objectKey, Integer second) { + GeneratePresignedUrlRequest generatePresignedUrlRequest = + new GeneratePresignedUrlRequest(properties.getBucketName(), objectKey) + .withMethod(HttpMethod.GET) + .withExpiration(new Date(System.currentTimeMillis() + 1000L * second)); + URL url = client.generatePresignedUrl(generatePresignedUrlRequest); + return url.toString(); + } + + /** + * 获取当前桶权限类型 + * + * @return 当前桶权限类型code + */ + public AccessPolicyType getAccessPolicy() { + return AccessPolicyType.getByType(properties.getAccessPolicy()); + } + private static String getPolicy(String bucketName, PolicyType policyType) { StringBuilder builder = new StringBuilder(); builder.append("{\n\"Statement\": [\n{\n\"Action\": [\n"); diff --git a/ruoyi-oss/src/main/java/com/ruoyi/oss/enumd/AccessPolicyType.java b/ruoyi-oss/src/main/java/com/ruoyi/oss/enumd/AccessPolicyType.java new file mode 100644 index 00000000..1cae6709 --- /dev/null +++ b/ruoyi-oss/src/main/java/com/ruoyi/oss/enumd/AccessPolicyType.java @@ -0,0 +1,55 @@ +package com.ruoyi.oss.enumd; + +import com.amazonaws.services.s3.model.CannedAccessControlList; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 桶访问策略配置 + * + * @author 陈賝 + */ +@Getter +@AllArgsConstructor +public enum AccessPolicyType { + + /** + * private + */ + PRIVATE("0", CannedAccessControlList.Private, PolicyType.WRITE), + + /** + * public + */ + PUBLIC("1", CannedAccessControlList.PublicRead, PolicyType.READ), + + /** + * custom + */ + CUSTOM("2",CannedAccessControlList.PublicRead, PolicyType.READ); + + /** + * 桶 权限类型 + */ + private final String type; + + /** + * 文件对象 权限类型 + */ + private final CannedAccessControlList acl; + + /** + * 桶策略类型 + */ + private final PolicyType policyType; + + public static AccessPolicyType getByType(String type) { + for (AccessPolicyType value : values()) { + if (value.getType().equals(type)) { + return value; + } + } + throw new RuntimeException("'type' not found By " + type); + } + +} diff --git a/ruoyi-oss/src/main/java/com/ruoyi/oss/properties/OssProperties.java b/ruoyi-oss/src/main/java/com/ruoyi/oss/properties/OssProperties.java index a0177790..781a1700 100644 --- a/ruoyi-oss/src/main/java/com/ruoyi/oss/properties/OssProperties.java +++ b/ruoyi-oss/src/main/java/com/ruoyi/oss/properties/OssProperties.java @@ -50,4 +50,9 @@ public class OssProperties { */ private String isHttps; + /** + * 桶权限类型(0private 1public 2custom) + */ + private String accessPolicy; + } diff --git a/ruoyi-sms/pom.xml b/ruoyi-sms/pom.xml index 342a8c5f..ba7703e9 100644 --- a/ruoyi-sms/pom.xml +++ b/ruoyi-sms/pom.xml @@ -31,7 +31,7 @@ com.tencentcloudapi - tencentcloud-sdk-java + tencentcloud-sdk-java-sms true diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOssConfig.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOssConfig.java index 577f17fb..7f2b05f6 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOssConfig.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOssConfig.java @@ -82,4 +82,8 @@ public class SysOssConfig extends BaseEntity { */ private String remark; + /** + * 桶权限类型(0private 1public 2custom) + */ + private String accessPolicy; } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssConfigBo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssConfigBo.java index e9f481d5..af289376 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssConfigBo.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssConfigBo.java @@ -98,4 +98,10 @@ public class SysOssConfigBo extends BaseEntity { */ private String remark; + /** + * 桶权限类型(0private 1public 2custom) + */ + @NotBlank(message = "桶权限类型不能为空", groups = {AddGroup.class, EditGroup.class}) + private String accessPolicy; + } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOssConfigVo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOssConfigVo.java index f8b31d6b..616e4e82 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOssConfigVo.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOssConfigVo.java @@ -82,4 +82,9 @@ public class SysOssConfigVo { */ private String remark; + /** + * 桶权限类型(0private 1public 2custom) + */ + private String accessPolicy; + } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssService.java index f02ea3d9..7f5c090e 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOssService.java @@ -2,11 +2,12 @@ package com.ruoyi.system.service; import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.page.TableDataInfo; -import com.ruoyi.system.domain.SysOss; import com.ruoyi.system.domain.bo.SysOssBo; import com.ruoyi.system.domain.vo.SysOssVo; import org.springframework.web.multipart.MultipartFile; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; import java.util.Collection; import java.util.List; @@ -23,7 +24,9 @@ public interface ISysOssService { SysOssVo getById(Long ossId); - SysOss upload(MultipartFile file); + SysOssVo upload(MultipartFile file); + + void download(Long ossId, HttpServletResponse response) throws IOException; Boolean deleteWithValidByIds(Collection ids, Boolean isValid); diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/SysLoginService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/SysLoginService.java index d18ceac5..6ea4a883 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/SysLoginService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/SysLoginService.java @@ -128,7 +128,7 @@ public class SysLoginService { LoginUser loginUser = LoginHelper.getLoginUser(); StpUtil.logout(); asyncService.recordLogininfor(loginUser.getUsername(), Constants.LOGOUT, MessageUtils.message("user.logout.success"), ServletUtils.getRequest()); - } catch (NotLoginException e) { + } catch (NotLoginException ignored) { } } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java index c7dc8d62..d7244116 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java @@ -1,10 +1,12 @@ package com.ruoyi.system.service.impl; +import cn.dev33.satoken.context.SaHolder; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.constant.CacheNames; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.domain.PageQuery; @@ -27,6 +29,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.*; +import java.util.stream.Collectors; /** * 字典 业务层处理 @@ -231,28 +234,24 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService * @param separator 分隔符 * @return 字典标签 */ + @SuppressWarnings("unchecked cast") @Override public String getDictLabel(String dictType, String dictValue, String separator) { - StringBuilder propertyString = new StringBuilder(); - List datas = SpringUtils.getAopProxy(this).selectDictDataByType(dictType); - - if (StringUtils.containsAny(dictValue, separator) && CollUtil.isNotEmpty(datas)) { - for (SysDictData dict : datas) { - for (String value : dictValue.split(separator)) { - if (value.equals(dict.getDictValue())) { - propertyString.append(dict.getDictLabel() + separator); - break; - } - } - } - } else { - for (SysDictData dict : datas) { - if (dictValue.equals(dict.getDictValue())) { - return dict.getDictLabel(); - } - } + // 优先从本地缓存获取 + List datas = (List) SaHolder.getStorage().get(CacheConstants.SYS_DICT_KEY + dictType); + if (ObjectUtil.isNull(datas)) { + datas = SpringUtils.getAopProxy(this).selectDictDataByType(dictType); + SaHolder.getStorage().set(CacheConstants.SYS_DICT_KEY + dictType, datas); + } + + Map map = StreamUtils.toMap(datas, SysDictData::getDictValue, SysDictData::getDictLabel); + if (StringUtils.containsAny(dictValue, separator)) { + return Arrays.stream(dictValue.split(separator)) + .map(v -> map.getOrDefault(v, StringUtils.EMPTY)) + .collect(Collectors.joining(separator)); + } else { + return map.getOrDefault(dictValue, StringUtils.EMPTY); } - return StringUtils.stripEnd(propertyString.toString(), separator); } /** @@ -263,28 +262,24 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService * @param separator 分隔符 * @return 字典值 */ + @SuppressWarnings("unchecked cast") @Override public String getDictValue(String dictType, String dictLabel, String separator) { - StringBuilder propertyString = new StringBuilder(); - List datas = SpringUtils.getAopProxy(this).selectDictDataByType(dictType); - - if (StringUtils.containsAny(dictLabel, separator) && CollUtil.isNotEmpty(datas)) { - for (SysDictData dict : datas) { - for (String label : dictLabel.split(separator)) { - if (label.equals(dict.getDictLabel())) { - propertyString.append(dict.getDictValue() + separator); - break; - } - } - } - } else { - for (SysDictData dict : datas) { - if (dictLabel.equals(dict.getDictLabel())) { - return dict.getDictValue(); - } - } + // 优先从本地缓存获取 + List datas = (List) SaHolder.getStorage().get(CacheConstants.SYS_DICT_KEY + dictType); + if (ObjectUtil.isNull(datas)) { + datas = SpringUtils.getAopProxy(this).selectDictDataByType(dictType); + SaHolder.getStorage().set(CacheConstants.SYS_DICT_KEY + dictType, datas); + } + + Map map = StreamUtils.toMap(datas, SysDictData::getDictLabel, SysDictData::getDictValue); + if (StringUtils.containsAny(dictLabel, separator)) { + return Arrays.stream(dictLabel.split(separator)) + .map(l -> map.getOrDefault(l, StringUtils.EMPTY)) + .collect(Collectors.joining(separator)); + } else { + return map.getOrDefault(dictLabel, StringUtils.EMPTY); } - return StringUtils.stripEnd(propertyString.toString(), separator); } } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java index ea6c604a..4d340675 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java @@ -11,6 +11,7 @@ import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.domain.entity.SysMenu; import com.ruoyi.common.core.domain.entity.SysRole; import com.ruoyi.common.helper.LoginHelper; +import com.ruoyi.common.utils.StreamUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.TreeBuildUtils; import com.ruoyi.system.domain.SysRoleMenu; @@ -425,13 +426,7 @@ public class SysMenuServiceImpl implements ISysMenuService { * 得到子节点列表 */ private List getChildList(List list, SysMenu t) { - List tlist = new ArrayList(); - for (SysMenu n : list) { - if (n.getParentId().longValue() == t.getMenuId().longValue()) { - tlist.add(n); - } - } - return tlist; + return StreamUtils.filter(list, n -> n.getParentId().equals(t.getMenuId())); } /** diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssServiceImpl.java index 6c63821f..cd9bffb1 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssServiceImpl.java @@ -1,5 +1,6 @@ package com.ruoyi.system.service.impl; +import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; @@ -8,10 +9,13 @@ import com.ruoyi.common.constant.CacheNames; import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.BeanCopyUtils; import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.file.FileUtils; import com.ruoyi.common.utils.spring.SpringUtils; import com.ruoyi.oss.core.OssClient; import com.ruoyi.oss.entity.UploadResult; +import com.ruoyi.oss.enumd.AccessPolicyType; import com.ruoyi.oss.factory.OssFactory; import com.ruoyi.system.domain.SysOss; import com.ruoyi.system.domain.bo.SysOssBo; @@ -20,14 +24,18 @@ import com.ruoyi.system.mapper.SysOssMapper; import com.ruoyi.system.service.ISysOssService; import lombok.RequiredArgsConstructor; import org.springframework.cache.annotation.Cacheable; +import org.springframework.http.MediaType; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; /** * 文件上传 服务层实现 @@ -44,6 +52,8 @@ public class SysOssServiceImpl implements ISysOssService { public TableDataInfo queryPageList(SysOssBo bo, PageQuery pageQuery) { LambdaQueryWrapper lqw = buildQueryWrapper(bo); Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + List filterResult = result.getRecords().stream().map(this::matchingUrl).collect(Collectors.toList()); + result.setRecords(filterResult); return TableDataInfo.build(result); } @@ -53,7 +63,7 @@ public class SysOssServiceImpl implements ISysOssService { for (Long id : ossIds) { SysOssVo vo = SpringUtils.getAopProxy(this).getById(id); if (ObjectUtil.isNotNull(vo)) { - list.add(vo); + list.add(this.matchingUrl(vo)); } } return list; @@ -80,7 +90,25 @@ public class SysOssServiceImpl implements ISysOssService { } @Override - public SysOss upload(MultipartFile file) { + public void download(Long ossId, HttpServletResponse response) throws IOException { + SysOssVo sysOss = SpringUtils.getAopProxy(this).getById(ossId); + if (ObjectUtil.isNull(sysOss)) { + throw new ServiceException("文件数据不存在!"); + } + FileUtils.setAttachmentResponseHeader(response, sysOss.getOriginalName()); + response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8"); + OssClient storage = OssFactory.instance(); + try(InputStream inputStream = storage.getObjectContent(sysOss.getUrl())) { + int available = inputStream.available(); + IoUtil.copy(inputStream, response.getOutputStream(), available); + response.setContentLength(available); + } catch (Exception e) { + throw new ServiceException(e.getMessage()); + } + } + + @Override + public SysOssVo upload(MultipartFile file) { String originalfileName = file.getOriginalFilename(); String suffix = StringUtils.substring(originalfileName, originalfileName.lastIndexOf("."), originalfileName.length()); OssClient storage = OssFactory.instance(); @@ -98,7 +126,9 @@ public class SysOssServiceImpl implements ISysOssService { oss.setOriginalName(originalfileName); oss.setService(storage.getConfigKey()); baseMapper.insert(oss); - return oss; + SysOssVo sysOssVo = new SysOssVo(); + BeanCopyUtils.copy(oss, sysOssVo); + return this.matchingUrl(sysOssVo); } @Override @@ -114,4 +144,18 @@ public class SysOssServiceImpl implements ISysOssService { return baseMapper.deleteBatchIds(ids) > 0; } + /** + * 匹配Url + * + * @param oss OSS对象 + * @return oss 匹配Url的OSS对象 + */ + private SysOssVo matchingUrl(SysOssVo oss) { + OssClient storage = OssFactory.instance(oss.getService()); + // 仅修改桶类型为 private 的URL,临时URL时长为120s + if (AccessPolicyType.PRIVATE == storage.getAccessPolicy()) { + oss.setUrl(storage.getPrivateUrl(oss.getFileName(), 120)); + } + return oss; + } } diff --git a/ruoyi-ui/bin/package.bat b/ruoyi-ui/bin/package.bat index 9f6e5f4d..2f22a4ad 100644 --- a/ruoyi-ui/bin/package.bat +++ b/ruoyi-ui/bin/package.bat @@ -1,6 +1,6 @@ @echo off echo. -echo [��Ϣ] ��װWeb���̣�����node_modules�ļ��� +echo [信息] 安装Web工程,生成node_modules文件。 echo. %~d0 diff --git a/ruoyi-ui/bin/run-web.bat b/ruoyi-ui/bin/run-web.bat index 3e209d77..0318c525 100644 --- a/ruoyi-ui/bin/run-web.bat +++ b/ruoyi-ui/bin/run-web.bat @@ -1,6 +1,6 @@ @echo off echo. -echo [��Ϣ] ʹ�� Vue CLI �������� Web ���̡� +echo [信息] 使用 Vue CLI 命令运行 Web 工程。 echo. %~d0 @@ -9,4 +9,4 @@ cd %~dp0 cd .. npm run dev -pause +pause \ No newline at end of file diff --git a/ruoyi-ui/src/assets/icons/svg/code.svg b/ruoyi-ui/src/assets/icons/svg/code.svg index ed4d23cf..5f9c5abd 100644 --- a/ruoyi-ui/src/assets/icons/svg/code.svg +++ b/ruoyi-ui/src/assets/icons/svg/code.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/ruoyi-ui/src/assets/icons/svg/server.svg b/ruoyi-ui/src/assets/icons/svg/server.svg index ca37b001..eb287e36 100644 --- a/ruoyi-ui/src/assets/icons/svg/server.svg +++ b/ruoyi-ui/src/assets/icons/svg/server.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/ruoyi-ui/src/assets/icons/svg/system.svg b/ruoyi-ui/src/assets/icons/svg/system.svg index dba28cf6..5992593e 100644 --- a/ruoyi-ui/src/assets/icons/svg/system.svg +++ b/ruoyi-ui/src/assets/icons/svg/system.svg @@ -1,2 +1,2 @@ \ No newline at end of file + \ No newline at end of file diff --git a/ruoyi-ui/src/assets/icons/svg/tool.svg b/ruoyi-ui/src/assets/icons/svg/tool.svg index c813067e..48e0e357 100644 --- a/ruoyi-ui/src/assets/icons/svg/tool.svg +++ b/ruoyi-ui/src/assets/icons/svg/tool.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/ruoyi-ui/src/assets/styles/ruoyi.scss b/ruoyi-ui/src/assets/styles/ruoyi.scss index ca7c6f96..16a4740f 100644 --- a/ruoyi-ui/src/assets/styles/ruoyi.scss +++ b/ruoyi-ui/src/assets/styles/ruoyi.scss @@ -149,10 +149,9 @@ } /** 表格更多操作下拉样式 */ -.el-table .el-dropdown-link { - cursor: pointer; - color: #409EFF; - margin-left: 5px; +.el-table .el-dropdown-link,.el-table .el-dropdown-selfdefine { + cursor: pointer; + margin-left: 5px; } .el-table .el-dropdown, .el-icon-arrow-down { diff --git a/ruoyi-ui/src/components/Crontab/hour.vue b/ruoyi-ui/src/components/Crontab/hour.vue index abee0bfe..4b1f1fcd 100644 --- a/ruoyi-ui/src/components/Crontab/hour.vue +++ b/ruoyi-ui/src/components/Crontab/hour.vue @@ -1,114 +1,114 @@ diff --git a/ruoyi-ui/src/components/TopNav/index.vue b/ruoyi-ui/src/components/TopNav/index.vue index 0cc24dba..5f0edbef 100644 --- a/ruoyi-ui/src/components/TopNav/index.vue +++ b/ruoyi-ui/src/components/TopNav/index.vue @@ -92,7 +92,9 @@ export default { if (path !== undefined && path.lastIndexOf("/") > 0 && hideList.indexOf(path) === -1) { const tmpPath = path.substring(1, path.length); activePath = "/" + tmpPath.substring(0, tmpPath.indexOf("/")); - this.$store.dispatch('app/toggleSideBarHide', false); + if (!this.$route.meta.link) { + this.$store.dispatch('app/toggleSideBarHide', false); + } } else if(!this.$route.children) { activePath = path; this.$store.dispatch('app/toggleSideBarHide', true); @@ -145,6 +147,8 @@ export default { } if(routes.length > 0) { this.$store.commit("SET_SIDEBAR_ROUTERS", routes); + } else { + this.$store.dispatch('app/toggleSideBarHide', true); } }, ishttp(url) { diff --git a/ruoyi-ui/src/utils/request.js b/ruoyi-ui/src/utils/request.js index 2473bc13..f94fa0e5 100644 --- a/ruoyi-ui/src/utils/request.js +++ b/ruoyi-ui/src/utils/request.js @@ -80,31 +80,24 @@ service.interceptors.response.use(res => { if (code === 401) { if (!isRelogin.show) { isRelogin.show = true; - MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { - confirmButtonText: '重新登录', - cancelButtonText: '取消', - type: 'warning' - } - ).then(() => { - isRelogin.show = false; - store.dispatch('LogOut').then(() => { - location.href = process.env.VUE_APP_CONTEXT_PATH + "index"; - }) + MessageBox.confirm('登录状态已过期,您可以继续留在该页面,或者重新登录', '系统提示', { confirmButtonText: '重新登录', cancelButtonText: '取消', type: 'warning' }).then(() => { + isRelogin.show = false; + store.dispatch('LogOut').then(() => { + location.href = process.env.VUE_APP_CONTEXT_PATH + "index"; + }) }).catch(() => { isRelogin.show = false; }); } return Promise.reject('无效的会话,或者会话已过期,请重新登录。') } else if (code === 500) { - Message({ - message: msg, - type: 'error' - }) + Message({ message: msg, type: 'error' }) return Promise.reject(new Error(msg)) + } else if (code === 601) { + Message({ message: msg, type: 'warning' }) + return Promise.reject('error') } else if (code !== 200) { - Notification.error({ - title: msg - }) + Notification.error({ title: msg }) return Promise.reject('error') } else { return res.data @@ -115,18 +108,12 @@ service.interceptors.response.use(res => { let { message } = error; if (message == "Network Error") { message = "后端接口连接异常"; - } - else if (message.includes("timeout")) { + } else if (message.includes("timeout")) { message = "系统接口请求超时"; - } - else if (message.includes("Request failed with status code")) { + } else if (message.includes("Request failed with status code")) { message = "系统接口" + message.substr(message.length - 3) + "异常"; } - Message({ - message: message, - type: 'error', - duration: 5 * 1000 - }) + Message({ message: message, type: 'error', duration: 5 * 1000 }) return Promise.reject(error) } ) diff --git a/ruoyi-ui/src/utils/ruoyi.js b/ruoyi-ui/src/utils/ruoyi.js index d2cd2a06..243c4c7b 100644 --- a/ruoyi-ui/src/utils/ruoyi.js +++ b/ruoyi-ui/src/utils/ruoyi.js @@ -86,11 +86,14 @@ export function selectDictLabel(datas, value) { return actions.join(''); } -// 回显数据字典(字符串数组) +// 回显数据字典(字符串、数组) export function selectDictLabels(datas, value, separator) { - if (value === undefined) { + if (value === undefined || value.length ===0) { return ""; } + if (Array.isArray(value)) { + value = value.join(","); + } var actions = []; var currentSeparator = undefined === separator ? "," : separator; var temp = value.split(currentSeparator); diff --git a/ruoyi-ui/src/views/index.vue b/ruoyi-ui/src/views/index.vue index d59814cc..6207f3bf 100644 --- a/ruoyi-ui/src/views/index.vue +++ b/ruoyi-ui/src/views/index.vue @@ -23,7 +23,7 @@ * 分布式限流 Redisson 全局、请求IP、集群ID 多种限流
* 分布式锁 Lock4j 注解锁、工具锁 多种多样
* 分布式幂等 Redisson 拦截重复提交
- * 分布式日志 TLog 支持跟踪链路日志记录、性能分析、链路排查
+ * 分布式链路追踪 SkyWalking 支持链路追踪、网格分析、度量聚合、可视化
* 分布式任务调度 Xxl-Job 高性能 高可靠 易扩展
* 分布式文件存储 Minio 本地存储
* 分布式云存储 七牛、阿里、腾讯 云存储
@@ -32,7 +32,7 @@ * Excel框架 Alibaba EasyExcel 性能优异 扩展性强
* 文档框架 SpringDoc、javadoc 无注解零入侵基于java注释
* 工具类框架 Hutool、Lombok 减少代码冗余 增加安全性
- * 代码生成器 适配MP、Knife4j规范化代码 一键生成前后端代码
+ * 代码生成器 适配MP、SpringDoc规范化代码 一键生成前后端代码
* 部署方式 Docker 容器编排 一键部署业务集群
* 国际化 SpringMessage Spring标准国际化方案

diff --git a/ruoyi-ui/src/views/monitor/druid/index.vue b/ruoyi-ui/src/views/monitor/druid/index.vue deleted file mode 100644 index c6ad585c..00000000 --- a/ruoyi-ui/src/views/monitor/druid/index.vue +++ /dev/null @@ -1,15 +0,0 @@ - - diff --git a/ruoyi-ui/src/views/system/oss/config.vue b/ruoyi-ui/src/views/system/oss/config.vue index 54ad98cb..0120641d 100644 --- a/ruoyi-ui/src/views/system/oss/config.vue +++ b/ruoyi-ui/src/views/system/oss/config.vue @@ -80,6 +80,13 @@ + + +