diff --git a/.editorconfig b/.editorconfig index 672defc11..25b312ef3 100644 --- a/.editorconfig +++ b/.editorconfig @@ -10,7 +10,7 @@ end_of_line = lf trim_trailing_whitespace = true insert_final_newline = true -[*.{json,yml}] +[*.{json,yml,yaml}] indent_size = 2 [*.md] diff --git a/.run/ruoyi-monitor-admin.run.xml b/.run/ruoyi-monitor-admin.run.xml new file mode 100644 index 000000000..0eb44eec6 --- /dev/null +++ b/.run/ruoyi-monitor-admin.run.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/.run/ruoyi-server.run.xml b/.run/ruoyi-server.run.xml new file mode 100644 index 000000000..c75e92af0 --- /dev/null +++ b/.run/ruoyi-server.run.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/.run/ruoyi-xxl-job-admin.run.xml b/.run/ruoyi-xxl-job-admin.run.xml new file mode 100644 index 000000000..2a30437f1 --- /dev/null +++ b/.run/ruoyi-xxl-job-admin.run.xml @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/README.md b/README.md index d2e514751..1fd86c0c4 100644 --- a/README.md +++ b/README.md @@ -4,14 +4,17 @@ [![License](https://img.shields.io/badge/License-MIT-blue.svg)](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/blob/master/LICENSE) [![使用IntelliJ IDEA开发维护](https://img.shields.io/badge/IntelliJ%20IDEA-提供支持-blue.svg)](https://www.jetbrains.com/?from=RuoYi-Vue-Plus)
-[![RuoYi-Vue-Plus](https://img.shields.io/badge/RuoYi_Vue_Plus-4.2.0-success.svg)](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus) -[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-2.6-blue.svg)]() +[![RuoYi-Vue-Plus](https://img.shields.io/badge/RuoYi_Vue_Plus-4.4.0-success.svg)](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus) +[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-2.7-blue.svg)]() [![JDK-8+](https://img.shields.io/badge/JDK-8-green.svg)]() [![JDK-11](https://img.shields.io/badge/JDK-11-green.svg)]() > RuoYi-Vue-Plus 是重写 RuoYi-Vue 针对 `分布式集群` 场景全方位升级(不兼容原框架) -> 系统演示: [传送门](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/系统演示?sort_id=4836388) +> 项目代码、文档 均开源免费可商用 遵循开源协议在项目中保留开源协议文件即可
+活到老写到老 为兴趣而开源 为学习而开源 为让大家真正可以学到技术而开源 + +> 系统演示: [传送门](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=4836388&doc_id=1469725) | 功能介绍 | 使用技术 | 文档地址 | 特性注意事项 | |----------|---------------------|---------------------------------------------------------------------------------------------------|----------------------------| @@ -38,7 +41,7 @@ | 分布式队列 | Redisson | [Redisson文档](https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95) | 普通队列、延迟队列、优先队列 等 | | 分布式锁 | Lock4j | [Lock4j官网](https://gitee.com/baomidou/lock4j) | 注解锁、工具锁 多种多样 | | 分布式幂等 | Redisson | [Lock4j文档](https://gitee.com/baomidou/lock4j) | 拦截重复提交 | -| 分布式日志 | TLog | [TLog文档](https://yomahub.com/tlog/docs) | 支持跟踪链路日志记录、性能分析、链路排查 | +| 分布式链路追踪 | Apache SkyWalking | [Apache SkyWalking文档](https://skywalking.apache.org/docs/) | 链路追踪、网格分析、度量聚合、可视化 | | 分布式任务调度 | Xxl-Job | [Xxl-Job官网](https://www.xuxueli.com/xxl-job/) | 高性能 高可靠 易扩展 | | 文件存储 | Minio | [Minio文档](https://docs.min.io/) | 本地存储 | | 文件存储 | 七牛、阿里、腾讯 | [OSS使用文档](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=4359146&doc_id=1469725) | 云存储 | @@ -46,9 +49,9 @@ | 监控框架 | SpringBoot-Admin | [SpringBoot-Admin文档](https://codecentric.github.io/spring-boot-admin/current/) | 全方位服务监控 | | 校验框架 | Validation | [Validation文档](https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/) | 增强接口安全性、严谨性 支持国际化 | | Excel框架 | Alibaba EasyExcel | [EasyExcel文档](https://www.yuque.com/easyexcel/doc/easyexcel) | 性能优异 扩展性强 | -| 文档框架 | Knife4j | [Knife4j文档](https://doc.xiaominfo.com/knife4j/documentation/) | 美化接口文档 | +| 文档框架 | SpringDoc、javadoc | [接口文档](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=5805266&doc_id=1469725) | 无注解零入侵基于java注释 | | 工具类框架 | Hutool、Lombok | [Hutool文档](https://www.hutool.cn/docs/) | 减少代码冗余 增加安全性 | -| 代码生成器 | 适配MP、Knife4j规范化代码 | [Hutool文档](https://www.hutool.cn/docs/) | 一键生成前后端代码 | +| 代码生成器 | 适配MP、SpringDoc规范化代码 | [代码生成文档](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=5522329&doc_id=1469725) | 一键生成前后端代码 | | 部署方式 | Docker | [Docker文档](https://docs.docker.com/) | 容器编排 一键部署业务集群 | | 国际化 | SpringMessage | [SpringMVC文档](https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc) | Spring标准国际化方案 | @@ -56,11 +59,14 @@ 使用框架前请仔细阅读文档重点注意事项
->[初始化项目 必看](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/关于初始化项目?sort_id=4164117) ->>[https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/关于初始化项目?sort_id=4164117](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/关于初始化项目?sort_id=4164117) -> ->[部署项目 必看](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/关于应用部署?sort_id=4219382) ->>[https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/关于应用部署?sort_id=4219382](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/关于应用部署?sort_id=4219382) +>[初始化项目 必看](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=4164117&doc_id=1469725) +>>[https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=4164117&doc_id=1469725](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=4164117&doc_id=1469725) +> +>[专栏与视频 入门必看](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=5473272&doc_id=1469725) +>>[https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=5473272&doc_id=1469725](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=5473272&doc_id=1469725) +> +>[部署项目 必看](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=4219382&doc_id=1469725) +>>[https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=4219382&doc_id=1469725](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages?sort_id=4219382&doc_id=1469725) > >[参考文档 Wiki](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages) >>[https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus/wikis/pages) diff --git a/pom.xml b/pom.xml index 9f1963baf..3de969cfd 100644 --- a/pom.xml +++ b/pom.xml @@ -6,53 +6,47 @@ com.ruoyi ruoyi-vue-plus - 4.2.0 + 4.4.0 RuoYi-Vue-Plus https://gitee.com/JavaLionLi/RuoYi-Vue-Plus RuoYi-Vue-Plus后台管理系统 - 4.2.0 - 2.6.9 + 4.4.0 + 2.7.6 UTF-8 UTF-8 1.8 3.2.2 2.2.2 - 1.2.11 - 3.0.3 - 1.5.22 - 5.2.2 - 3.1.1 + 1.6.13 + 5.2.3 + 3.1.3 2.3 - 1.30.0 + 1.33.0 3.5.2 3.9.1 - 5.8.3 - 4.9.3 - 2.6.7 - 3.17.4 - 2.2.1 - 3.5.1 - 1.4.3 + 5.8.10 + 4.10.0 + 2.7.7 + 3.18.0 + 2.2.3 + 3.5.2 + 2.14.2 2.3.1 + 1.18.24 - 30.0-jre + 31.1-jre + + 1.32 - 1.12.248 + 1.12.349 - 2.0.9 - 3.1.537 - - - localhost - http://${docker.registry.url}:2375 - ruoyi - 1.2.2 - + 2.0.22 + 3.1.635 @@ -77,29 +71,22 @@ import - - com.alibaba - druid-spring-boot-starter - ${druid.version} + org.springdoc + springdoc-openapi-webmvc-core + ${springdoc.version} - com.github.xiaoymin - knife4j-spring-boot-starter - ${knife4j.version} - - - swagger-annotations - io.swagger - - + org.springdoc + springdoc-openapi-javadoc + ${springdoc.version} - io.swagger - swagger-annotations - ${swagger-annotations.version} + org.projectlombok + lombok + ${lombok.version} @@ -142,6 +129,12 @@ cn.dev33 sa-token-jwt ${satoken.version} + + + cn.hutool + hutool-all + + @@ -188,7 +181,7 @@ com.tencentcloudapi - tencentcloud-sdk-java + tencentcloud-sdk-java-sms ${tencent.sms.version} @@ -223,29 +216,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} @@ -255,6 +228,13 @@ ${guava.version} + + + org.yaml + snakeyaml + ${snakeyaml.version} + + com.ruoyi @@ -338,6 +318,36 @@ ${java.version} ${java.version} ${project.build.sourceEncoding} + + + com.github.therapi + therapi-runtime-javadoc-scribe + 0.15.0 + + + org.projectlombok + lombok + ${lombok.version} + + + org.springframework.boot + spring-boot-configuration-processor + ${spring-boot.version} + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.22.2 + + -Dfile.encoding=UTF-8 + + ${profiles.active} + + exclude @@ -364,8 +374,8 @@ public - aliyun nexus - https://maven.aliyun.com/repository/public/ + huawei nexus + https://mirrors.huaweicloud.com/repository/maven/ true @@ -375,8 +385,8 @@ public - aliyun nexus - https://maven.aliyun.com/repository/public/ + huawei nexus + https://mirrors.huaweicloud.com/repository/maven/ true @@ -393,8 +403,6 @@ local debug - false - '*' @@ -403,8 +411,6 @@ dev debug - false - '*' @@ -416,10 +422,10 @@ prod warn - true - health, info, logfile + + diff --git a/ruoyi-admin/Dockerfile b/ruoyi-admin/Dockerfile index 1bbd2ccf6..6033f7e8c 100644 --- a/ruoyi-admin/Dockerfile +++ b/ruoyi-admin/Dockerfile @@ -2,14 +2,22 @@ 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 -EXPOSE 8080 +ENV SERVER_PORT=8080 + +EXPOSE ${SERVER_PORT} ADD ./target/ruoyi-admin.jar ./app.jar -ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-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 a3d2da6f1..a588f62da 100644 --- a/ruoyi-admin/pom.xml +++ b/ruoyi-admin/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.2.0 + 4.4.0 4.0.0 jar @@ -26,8 +26,8 @@ - mysql - mysql-connector-java + com.mysql + mysql-connector-j @@ -78,6 +78,24 @@ ruoyi-demo + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + + + + + + + + @@ -107,25 +125,6 @@ ${project.artifactId} - - com.spotify - docker-maven-plugin - ${docker.plugin.version} - - ${docker.namespace}/ruoyi-server:${project.version} - ${project.basedir} - ${docker.registry.host} - ${docker.registry.url} - ${docker.registry.url} - - - / - ${project.build.directory} - ${project.build.finalName}.jar - - - - diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java index 0889aabc7..94630e2e9 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java @@ -1,11 +1,12 @@ package com.ruoyi.web.controller.common; +import cn.dev33.satoken.annotation.SaIgnore; import cn.hutool.captcha.AbstractCaptcha; import cn.hutool.captcha.generator.CodeGenerator; import cn.hutool.core.convert.Convert; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.RandomUtil; -import com.ruoyi.common.annotation.Anonymous; +import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.enums.CaptchaType; @@ -18,9 +19,6 @@ import com.ruoyi.sms.config.properties.SmsProperties; import com.ruoyi.sms.core.SmsTemplate; import com.ruoyi.sms.entity.SmsResult; import com.ruoyi.system.service.ISysConfigService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.validation.annotation.Validated; @@ -37,10 +35,9 @@ import java.util.Map; * * @author Lion Li */ -@Anonymous +@SaIgnore @Slf4j @Validated -@Api(value = "验证码操作处理", tags = {"验证码管理"}) @RequiredArgsConstructor @RestController public class CaptchaController { @@ -51,16 +48,16 @@ public class CaptchaController { /** * 短信验证码 + * + * @param phonenumber 用户手机号 */ - @ApiOperation("短信验证码") @GetMapping("/captchaSms") - public R smsCaptcha(@ApiParam("用户手机号") - @NotBlank(message = "{user.phonenumber.not.blank}") + public R smsCaptcha(@NotBlank(message = "{user.phonenumber.not.blank}") String phonenumber) { - if (smsProperties.getEnabled()) { - R.fail("当前系统没有开启短信功能!"); + if (!smsProperties.getEnabled()) { + return R.fail("当前系统没有开启短信功能!"); } - String key = Constants.CAPTCHA_CODE_KEY + phonenumber; + String key = CacheConstants.CAPTCHA_CODE_KEY + phonenumber; String code = RandomUtil.randomNumbers(4); RedisUtils.setCacheObject(key, code, Duration.ofMinutes(Constants.CAPTCHA_EXPIRATION)); // 验证码模板id 自行处理 (查数据库或写死均可) @@ -79,18 +76,17 @@ public class CaptchaController { /** * 生成验证码 */ - @ApiOperation("生成验证码") @GetMapping("/captchaImage") public R> getCode() { Map ajax = new HashMap<>(); - boolean captchaOnOff = configService.selectCaptchaOnOff(); - ajax.put("captchaOnOff", captchaOnOff); - if (!captchaOnOff) { + boolean captchaEnabled = configService.selectCaptchaEnabled(); + ajax.put("captchaEnabled", captchaEnabled); + if (!captchaEnabled) { return R.ok(ajax); } // 保存验证码信息 String uuid = IdUtil.simpleUUID(); - String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid; + String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid; // 生成验证码 CaptchaType captchaType = captchaProperties.getType(); boolean isMath = CaptchaType.MATH == captchaType; diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java index 21fbd201f..74585fc48 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java @@ -1,40 +1,59 @@ package com.ruoyi.web.controller.monitor; import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.collection.CollUtil; +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.constant.CacheNames; import com.ruoyi.common.core.domain.R; +import com.ruoyi.common.utils.JsonUtils; import com.ruoyi.common.utils.StringUtils; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; +import com.ruoyi.common.utils.redis.CacheUtils; +import com.ruoyi.common.utils.redis.RedisUtils; +import com.ruoyi.system.domain.SysCache; import lombok.RequiredArgsConstructor; -import org.springframework.data.redis.connection.RedisServerCommands; -import org.springframework.data.redis.core.RedisCallback; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.redisson.spring.data.connection.RedissonConnectionFactory; +import org.springframework.data.redis.connection.RedisConnection; +import org.springframework.web.bind.annotation.*; import java.util.*; +import java.util.stream.Collectors; /** * 缓存监控 * * @author Lion Li */ -@Api(value = "缓存监控", tags = {"缓存监控管理"}) @RequiredArgsConstructor @RestController @RequestMapping("/monitor/cache") public class CacheController { - private final RedisTemplate redisTemplate; + private final RedissonConnectionFactory connectionFactory; - @ApiOperation("获取缓存监控详细信息") + private final static List CACHES = new ArrayList<>(); + + static { + CACHES.add(new SysCache(CacheConstants.LOGIN_TOKEN_KEY, "用户信息")); + CACHES.add(new SysCache(CacheConstants.ONLINE_TOKEN_KEY, "在线用户")); + CACHES.add(new SysCache(CacheNames.SYS_CONFIG, "配置信息")); + CACHES.add(new SysCache(CacheNames.SYS_DICT, "数据字典")); + CACHES.add(new SysCache(CacheConstants.CAPTCHA_CODE_KEY, "验证码")); + CACHES.add(new SysCache(CacheConstants.REPEAT_SUBMIT_KEY, "防重提交")); + CACHES.add(new SysCache(CacheConstants.RATE_LIMIT_KEY, "限流处理")); + CACHES.add(new SysCache(CacheNames.SYS_OSS_CONFIG, "OSS配置")); + CACHES.add(new SysCache(CacheConstants.PWD_ERR_CNT_KEY, "密码错误次数")); + } + + /** + * 获取缓存监控列表 + */ @SaCheckPermission("monitor:cache:list") @GetMapping() public R> getInfo() throws Exception { - Properties info = (Properties) redisTemplate.execute((RedisCallback) RedisServerCommands::info); - Properties commandStats = (Properties) redisTemplate.execute((RedisCallback) connection -> connection.info("commandstats")); - Object dbSize = redisTemplate.execute((RedisCallback) RedisServerCommands::dbSize); + RedisConnection connection = connectionFactory.getConnection(); + Properties info = connection.info(); + Properties commandStats = connection.info("commandstats"); + Long dbSize = connection.dbSize(); Map result = new HashMap<>(3); result.put("info", info); @@ -53,4 +72,98 @@ public class CacheController { result.put("commandStats", pieList); return R.ok(result); } + + /** + * 获取缓存监控缓存名列表 + */ + @SaCheckPermission("monitor:cache:list") + @GetMapping("/getNames") + public R> cache() { + return R.ok(CACHES); + } + + /** + * 获取缓存监控Key列表 + * + * @param cacheName 缓存名 + */ + @SaCheckPermission("monitor:cache:list") + @GetMapping("/getKeys/{cacheName}") + public R> getCacheKeys(@PathVariable String cacheName) { + Collection cacheKeys = new HashSet<>(0); + if (isCacheNames(cacheName)) { + Set keys = CacheUtils.keys(cacheName); + if (CollUtil.isNotEmpty(keys)) { + cacheKeys = keys.stream().map(Object::toString).collect(Collectors.toList()); + } + } else { + cacheKeys = RedisUtils.keys(cacheName + "*"); + } + return R.ok(cacheKeys); + } + + /** + * 获取缓存监控缓存值详情 + * + * @param cacheName 缓存名 + * @param cacheKey 缓存key + */ + @SaCheckPermission("monitor:cache:list") + @GetMapping("/getValue/{cacheName}/{cacheKey}") + public R getCacheValue(@PathVariable String cacheName, @PathVariable String cacheKey) { + Object cacheValue; + if (isCacheNames(cacheName)) { + cacheValue = CacheUtils.get(cacheName, cacheKey); + } else { + cacheValue = RedisUtils.getCacheObject(cacheKey); + } + SysCache sysCache = new SysCache(cacheName, cacheKey, JsonUtils.toJsonString(cacheValue)); + return R.ok(sysCache); + } + + /** + * 清理缓存监控缓存名 + * + * @param cacheName 缓存名 + */ + @SaCheckPermission("monitor:cache:list") + @DeleteMapping("/clearCacheName/{cacheName}") + public R clearCacheName(@PathVariable String cacheName) { + if (isCacheNames(cacheName)) { + CacheUtils.clear(cacheName); + } else { + RedisUtils.deleteKeys(cacheName + "*"); + } + return R.ok(); + } + + /** + * 清理缓存监控Key + * + * @param cacheKey key名 + */ + @SaCheckPermission("monitor:cache:list") + @DeleteMapping("/clearCacheKey/{cacheName}/{cacheKey}") + public R clearCacheKey(@PathVariable String cacheName, @PathVariable String cacheKey) { + if (isCacheNames(cacheName)) { + CacheUtils.evict(cacheName, cacheKey); + } else { + RedisUtils.deleteObject(cacheKey); + } + return R.ok(); + } + + /** + * 清理全部缓存监控 + */ + @SaCheckPermission("monitor:cache:list") + @DeleteMapping("/clearCacheAll") + public R clearCacheAll() { + RedisUtils.deleteKeys("*"); + return R.ok(); + } + + private boolean isCacheNames(String cacheName) { + return !StringUtils.contains(cacheName, ":"); + } } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java index 5bec15169..caae8b008 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java @@ -2,16 +2,16 @@ package com.ruoyi.web.controller.monitor; import cn.dev33.satoken.annotation.SaCheckPermission; import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.PageQuery; +import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.utils.redis.RedisUtils; import com.ruoyi.system.domain.SysLogininfor; import com.ruoyi.system.service.ISysLogininforService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -25,7 +25,6 @@ import java.util.List; * @author Lion Li */ @Validated -@Api(value = "系统访问记录", tags = {"系统访问记录管理"}) @RequiredArgsConstructor @RestController @RequestMapping("/monitor/logininfor") @@ -33,14 +32,18 @@ public class SysLogininforController extends BaseController { private final ISysLogininforService logininforService; - @ApiOperation("查询系统访问记录列表") + /** + * 获取系统访问记录列表 + */ @SaCheckPermission("monitor:logininfor:list") @GetMapping("/list") public TableDataInfo list(SysLogininfor logininfor, PageQuery pageQuery) { return logininforService.selectPageLogininforList(logininfor, pageQuery); } - @ApiOperation("导出系统访问记录列表") + /** + * 导出系统访问记录列表 + */ @Log(title = "登录日志", businessType = BusinessType.EXPORT) @SaCheckPermission("monitor:logininfor:export") @PostMapping("/export") @@ -49,7 +52,10 @@ public class SysLogininforController extends BaseController { ExcelUtil.exportExcel(list, "登录日志", SysLogininfor.class, response); } - @ApiOperation("删除系统访问记录") + /** + * 批量删除登录日志 + * @param infoIds 日志ids + */ @SaCheckPermission("monitor:logininfor:remove") @Log(title = "登录日志", businessType = BusinessType.DELETE) @DeleteMapping("/{infoIds}") @@ -57,7 +63,9 @@ public class SysLogininforController extends BaseController { return toAjax(logininforService.deleteLogininforByIds(infoIds)); } - @ApiOperation("清空系统访问记录") + /** + * 清理系统访问记录 + */ @SaCheckPermission("monitor:logininfor:remove") @Log(title = "登录日志", businessType = BusinessType.CLEAN) @DeleteMapping("/clean") @@ -65,4 +73,16 @@ public class SysLogininforController extends BaseController { logininforService.cleanLogininfor(); return R.ok(); } + + @SaCheckPermission("monitor:logininfor:unlock") + @Log(title = "账户解锁", businessType = BusinessType.OTHER) + @GetMapping("/unlock/{userName}") + public R unlock(@PathVariable("userName") String userName) { + String loginName = CacheConstants.PWD_ERR_CNT_KEY + userName; + if (RedisUtils.hasKey(loginName)) { + RedisUtils.deleteObject(loginName); + } + return R.ok(); + } + } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java index 8145bc66e..468b9c4cf 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java @@ -3,15 +3,13 @@ package com.ruoyi.web.controller.monitor; import cn.dev33.satoken.annotation.SaCheckPermission; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.PageQuery; +import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.system.domain.SysOperLog; import com.ruoyi.system.service.ISysOperLogService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -25,7 +23,6 @@ import java.util.List; * @author Lion Li */ @Validated -@Api(value = "操作日志记录", tags = {"操作日志记录管理"}) @RequiredArgsConstructor @RestController @RequestMapping("/monitor/operlog") @@ -33,14 +30,18 @@ public class SysOperlogController extends BaseController { private final ISysOperLogService operLogService; - @ApiOperation("查询操作日志记录列表") + /** + * 获取操作日志记录列表 + */ @SaCheckPermission("monitor:operlog:list") @GetMapping("/list") public TableDataInfo list(SysOperLog operLog, PageQuery pageQuery) { return operLogService.selectPageOperLogList(operLog, pageQuery); } - @ApiOperation("导出操作日志记录列表") + /** + * 导出操作日志记录列表 + */ @Log(title = "操作日志", businessType = BusinessType.EXPORT) @SaCheckPermission("monitor:operlog:export") @PostMapping("/export") @@ -49,7 +50,10 @@ public class SysOperlogController extends BaseController { ExcelUtil.exportExcel(list, "操作日志", SysOperLog.class, response); } - @ApiOperation("删除操作日志记录") + /** + * 批量删除操作日志记录 + * @param operIds 日志ids + */ @Log(title = "操作日志", businessType = BusinessType.DELETE) @SaCheckPermission("monitor:operlog:remove") @DeleteMapping("/{operIds}") @@ -57,7 +61,9 @@ public class SysOperlogController extends BaseController { return toAjax(operLogService.deleteOperLogByIds(operIds)); } - @ApiOperation("清空操作日志记录") + /** + * 清理操作日志记录 + */ @Log(title = "操作日志", businessType = BusinessType.CLEAN) @SaCheckPermission("monitor:operlog:remove") @DeleteMapping("/clean") 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 2ad51e315..b0b574c37 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 @@ -5,64 +5,66 @@ import cn.dev33.satoken.exception.NotLoginException; import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.bean.BeanUtil; import com.ruoyi.common.annotation.Log; -import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.dto.UserOnlineDTO; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.StreamUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.redis.RedisUtils; import com.ruoyi.system.domain.SysUserOnline; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.*; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.stream.Collectors; /** * 在线用户监控 * * @author Lion Li */ -@Api(value = "在线用户监控", tags = {"在线用户监控管理"}) @RequiredArgsConstructor @RestController @RequestMapping("/monitor/online") public class SysUserOnlineController extends BaseController { - @ApiOperation("在线用户列表") + /** + * 获取在线用户监控列表 + * + * @param ipaddr IP地址 + * @param userName 用户名 + */ @SaCheckPermission("monitor:online:list") @GetMapping("/list") public TableDataInfo list(String ipaddr, String userName) { // 获取所有未过期的 token - List keys = StpUtil.searchTokenValue("", -1, 0); + List keys = StpUtil.searchTokenValue("", 0, -1, false); List userOnlineDTOList = new ArrayList<>(); for (String key : keys) { - String token = key.replace(Constants.LOGIN_TOKEN_KEY, ""); - // 如果已经过期则踢下线 - if (StpUtil.stpLogic.getTokenActivityTimeoutByToken(token) < 0) { + String token = key.replace(CacheConstants.LOGIN_TOKEN_KEY, ""); + // 如果已经过期则跳过 + if (StpUtil.stpLogic.getTokenActivityTimeoutByToken(token) < -1) { continue; } - userOnlineDTOList.add(RedisUtils.getCacheObject(Constants.ONLINE_TOKEN_KEY + token)); + userOnlineDTOList.add(RedisUtils.getCacheObject(CacheConstants.ONLINE_TOKEN_KEY + token)); } if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName)) { - userOnlineDTOList = userOnlineDTOList.stream().filter(userOnline -> + userOnlineDTOList = StreamUtils.filter(userOnlineDTOList, userOnline -> StringUtils.equals(ipaddr, userOnline.getIpaddr()) && StringUtils.equals(userName, userOnline.getUserName()) - ).collect(Collectors.toList()); + ); } else if (StringUtils.isNotEmpty(ipaddr)) { - userOnlineDTOList = userOnlineDTOList.stream().filter(userOnline -> - StringUtils.equals(ipaddr, userOnline.getIpaddr())) - .collect(Collectors.toList()); + userOnlineDTOList = StreamUtils.filter(userOnlineDTOList, userOnline -> + StringUtils.equals(ipaddr, userOnline.getIpaddr()) + ); } else if (StringUtils.isNotEmpty(userName)) { - userOnlineDTOList = userOnlineDTOList.stream().filter(userOnline -> + userOnlineDTOList = StreamUtils.filter(userOnlineDTOList, userOnline -> StringUtils.equals(userName, userOnline.getUserName()) - ).collect(Collectors.toList()); + ); } Collections.reverse(userOnlineDTOList); userOnlineDTOList.removeAll(Collections.singleton(null)); @@ -72,15 +74,16 @@ public class SysUserOnlineController extends BaseController { /** * 强退用户 + * + * @param tokenId token值 */ - @ApiOperation("强退用户") @SaCheckPermission("monitor:online:forceLogout") @Log(title = "在线用户", businessType = BusinessType.FORCE) @DeleteMapping("/{tokenId}") 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/SysConfigController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java index 2dcb84375..c1b3acd86 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java @@ -4,16 +4,13 @@ import cn.dev33.satoken.annotation.SaCheckPermission; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.PageQuery; +import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.system.domain.SysConfig; import com.ruoyi.system.service.ISysConfigService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -27,7 +24,6 @@ import java.util.List; * @author Lion Li */ @Validated -@Api(value = "参数配置控制器", tags = {"参数配置管理"}) @RequiredArgsConstructor @RestController @RequestMapping("/system/config") @@ -38,14 +34,15 @@ public class SysConfigController extends BaseController { /** * 获取参数配置列表 */ - @ApiOperation("获取参数配置列表") @SaCheckPermission("system:config:list") @GetMapping("/list") public TableDataInfo list(SysConfig config, PageQuery pageQuery) { return configService.selectPageConfigList(config, pageQuery); } - @ApiOperation("导出参数配置列表") + /** + * 导出参数配置列表 + */ @Log(title = "参数管理", businessType = BusinessType.EXPORT) @SaCheckPermission("system:config:export") @PostMapping("/export") @@ -56,27 +53,28 @@ public class SysConfigController extends BaseController { /** * 根据参数编号获取详细信息 + * + * @param configId 参数ID */ - @ApiOperation("根据参数编号获取详细信息") @SaCheckPermission("system:config:query") @GetMapping(value = "/{configId}") - public R getInfo(@ApiParam("参数ID") @PathVariable Long configId) { + public R getInfo(@PathVariable Long configId) { return R.ok(configService.selectConfigById(configId)); } /** * 根据参数键名查询参数值 + * + * @param configKey 参数Key */ - @ApiOperation("根据参数键名查询参数值") @GetMapping(value = "/configKey/{configKey}") - public R getConfigKey(@ApiParam("参数Key") @PathVariable String configKey) { + public R getConfigKey(@PathVariable String configKey) { return R.ok(configService.selectConfigByKey(configKey)); } /** * 新增参数配置 */ - @ApiOperation("新增参数配置") @SaCheckPermission("system:config:add") @Log(title = "参数管理", businessType = BusinessType.INSERT) @PostMapping @@ -84,13 +82,13 @@ public class SysConfigController extends BaseController { if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) { return R.fail("新增参数'" + config.getConfigName() + "'失败,参数键名已存在"); } - return toAjax(configService.insertConfig(config)); + configService.insertConfig(config); + return R.ok(); } /** * 修改参数配置 */ - @ApiOperation("修改参数配置") @SaCheckPermission("system:config:edit") @Log(title = "参数管理", businessType = BusinessType.UPDATE) @PutMapping @@ -98,28 +96,30 @@ public class SysConfigController extends BaseController { if (UserConstants.NOT_UNIQUE.equals(configService.checkConfigKeyUnique(config))) { return R.fail("修改参数'" + config.getConfigName() + "'失败,参数键名已存在"); } - return toAjax(configService.updateConfig(config)); + configService.updateConfig(config); + return R.ok(); } /** * 根据参数键名修改参数配置 */ - @ApiOperation("根据参数键名修改参数配置") @SaCheckPermission("system:config:edit") @Log(title = "参数管理", businessType = BusinessType.UPDATE) @PutMapping("/updateByKey") public R updateByKey(@RequestBody SysConfig config) { - return toAjax(configService.updateConfig(config)); + configService.updateConfig(config); + return R.ok(); } /** * 删除参数配置 + * + * @param configIds 参数ID串 */ - @ApiOperation("删除参数配置") @SaCheckPermission("system:config:remove") @Log(title = "参数管理", businessType = BusinessType.DELETE) @DeleteMapping("/{configIds}") - public R remove(@ApiParam("参数ID串") @PathVariable Long[] configIds) { + public R remove(@PathVariable Long[] configIds) { configService.deleteConfigByIds(configIds); return R.ok(); } @@ -127,7 +127,6 @@ public class SysConfigController extends BaseController { /** * 刷新参数缓存 */ - @ApiOperation("刷新参数缓存") @SaCheckPermission("system:config:remove") @Log(title = "参数管理", businessType = BusinessType.CLEAN) @DeleteMapping("/refreshCache") 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 475cdb7e4..fa763df33 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 @@ -1,7 +1,6 @@ package com.ruoyi.web.controller.system; import cn.dev33.satoken.annotation.SaCheckPermission; -import cn.hutool.core.lang.tree.Tree; import cn.hutool.core.util.ArrayUtil; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.constant.UserConstants; @@ -11,16 +10,11 @@ import com.ruoyi.common.core.domain.entity.SysDept; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.system.service.ISysDeptService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import java.util.HashMap; import java.util.List; -import java.util.Map; /** * 部门信息 @@ -28,7 +22,6 @@ import java.util.Map; * @author Lion Li */ @Validated -@Api(value = "部门控制器", tags = {"部门管理"}) @RequiredArgsConstructor @RestController @RequestMapping("/system/dept") @@ -39,7 +32,6 @@ public class SysDeptController extends BaseController { /** * 获取部门列表 */ - @ApiOperation("获取部门列表") @SaCheckPermission("system:dept:list") @GetMapping("/list") public R> list(SysDept dept) { @@ -49,11 +41,12 @@ public class SysDeptController extends BaseController { /** * 查询部门列表(排除节点) + * + * @param deptId 部门ID */ - @ApiOperation("查询部门列表(排除节点)") @SaCheckPermission("system:dept:list") @GetMapping("/list/exclude/{deptId}") - public R> excludeChild(@ApiParam("部门ID") @PathVariable(value = "deptId", required = false) Long deptId) { + public R> excludeChild(@PathVariable(value = "deptId", required = false) Long deptId) { List depts = deptService.selectDeptList(new SysDept()); depts.removeIf(d -> d.getDeptId().equals(deptId) || ArrayUtil.contains(StringUtils.split(d.getAncestors(), ","), deptId + "")); @@ -62,42 +55,19 @@ public class SysDeptController extends BaseController { /** * 根据部门编号获取详细信息 + * + * @param deptId 部门ID */ - @ApiOperation("根据部门编号获取详细信息") @SaCheckPermission("system:dept:query") @GetMapping(value = "/{deptId}") - public R getInfo(@ApiParam("部门ID") @PathVariable Long deptId) { + public R getInfo(@PathVariable Long deptId) { deptService.checkDeptDataScope(deptId); return R.ok(deptService.selectDeptById(deptId)); } - /** - * 获取部门下拉树列表 - */ - @ApiOperation("获取部门下拉树列表") - @GetMapping("/treeselect") - public R>> treeselect(SysDept dept) { - List depts = deptService.selectDeptList(dept); - return R.ok(deptService.buildDeptTreeSelect(depts)); - } - - /** - * 加载对应角色部门列表树 - */ - @ApiOperation("加载对应角色部门列表树") - @GetMapping(value = "/roleDeptTreeselect/{roleId}") - public R> roleDeptTreeselect(@ApiParam("角色ID") @PathVariable("roleId") Long roleId) { - List depts = deptService.selectDeptList(new SysDept()); - Map ajax = new HashMap<>(); - ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId)); - ajax.put("depts", deptService.buildDeptTreeSelect(depts)); - return R.ok(ajax); - } - /** * 新增部门 */ - @ApiOperation("新增部门") @SaCheckPermission("system:dept:add") @Log(title = "部门管理", businessType = BusinessType.INSERT) @PostMapping @@ -111,7 +81,6 @@ public class SysDeptController extends BaseController { /** * 修改部门 */ - @ApiOperation("修改部门") @SaCheckPermission("system:dept:edit") @Log(title = "部门管理", businessType = BusinessType.UPDATE) @PutMapping @@ -131,17 +100,18 @@ public class SysDeptController extends BaseController { /** * 删除部门 + * + * @param deptId 部门ID */ - @ApiOperation("删除部门") @SaCheckPermission("system:dept:remove") @Log(title = "部门管理", businessType = BusinessType.DELETE) @DeleteMapping("/{deptId}") - public R remove(@ApiParam("部门ID串") @PathVariable Long 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/SysDictDataController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java index 060e980e4..01613db8b 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java @@ -4,17 +4,14 @@ import cn.dev33.satoken.annotation.SaCheckPermission; import cn.hutool.core.util.ObjectUtil; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.PageQuery; +import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.entity.SysDictData; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.system.service.ISysDictDataService; import com.ruoyi.system.service.ISysDictTypeService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -29,7 +26,6 @@ import java.util.List; * @author Lion Li */ @Validated -@Api(value = "数据字典信息控制器", tags = {"数据字典信息管理"}) @RequiredArgsConstructor @RestController @RequestMapping("/system/dict/data") @@ -38,14 +34,18 @@ public class SysDictDataController extends BaseController { private final ISysDictDataService dictDataService; private final ISysDictTypeService dictTypeService; - @ApiOperation("查询字典数据列表") + /** + * 查询字典数据列表 + */ @SaCheckPermission("system:dict:list") @GetMapping("/list") public TableDataInfo list(SysDictData dictData, PageQuery pageQuery) { return dictDataService.selectPageDictDataList(dictData, pageQuery); } - @ApiOperation("导出字典数据列表") + /** + * 导出字典数据列表 + */ @Log(title = "字典数据", businessType = BusinessType.EXPORT) @SaCheckPermission("system:dict:export") @PostMapping("/export") @@ -56,20 +56,22 @@ public class SysDictDataController extends BaseController { /** * 查询字典数据详细 + * + * @param dictCode 字典code */ - @ApiOperation("查询字典数据详细") @SaCheckPermission("system:dict:query") @GetMapping(value = "/{dictCode}") - public R getInfo(@ApiParam("字典code") @PathVariable Long dictCode) { + public R getInfo(@PathVariable Long dictCode) { return R.ok(dictDataService.selectDictDataById(dictCode)); } /** * 根据字典类型查询字典数据信息 + * + * @param dictType 字典类型 */ - @ApiOperation("根据字典类型查询字典数据信息") @GetMapping(value = "/type/{dictType}") - public R> dictType(@ApiParam("字典类型") @PathVariable String dictType) { + public R> dictType(@PathVariable String dictType) { List data = dictTypeService.selectDictDataByType(dictType); if (ObjectUtil.isNull(data)) { data = new ArrayList<>(); @@ -80,33 +82,34 @@ public class SysDictDataController extends BaseController { /** * 新增字典类型 */ - @ApiOperation("新增字典类型") @SaCheckPermission("system:dict:add") @Log(title = "字典数据", businessType = BusinessType.INSERT) @PostMapping public R add(@Validated @RequestBody SysDictData dict) { - return toAjax(dictDataService.insertDictData(dict)); + dictDataService.insertDictData(dict); + return R.ok(); } /** * 修改保存字典类型 */ - @ApiOperation("修改保存字典类型") @SaCheckPermission("system:dict:edit") @Log(title = "字典数据", businessType = BusinessType.UPDATE) @PutMapping public R edit(@Validated @RequestBody SysDictData dict) { - return toAjax(dictDataService.updateDictData(dict)); + dictDataService.updateDictData(dict); + return R.ok(); } /** * 删除字典类型 + * + * @param dictCodes 字典code串 */ - @ApiOperation("删除字典类型") @SaCheckPermission("system:dict:remove") @Log(title = "字典类型", businessType = BusinessType.DELETE) @DeleteMapping("/{dictCodes}") - public R remove(@ApiParam("字典code串") @PathVariable Long[] dictCodes) { + public R remove(@PathVariable Long[] dictCodes) { dictDataService.deleteDictDataByIds(dictCodes); return R.ok(); } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java index c8ebd49be..86840b7a5 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java @@ -4,16 +4,13 @@ import cn.dev33.satoken.annotation.SaCheckPermission; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.PageQuery; +import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.entity.SysDictType; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.system.service.ISysDictTypeService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -27,7 +24,6 @@ import java.util.List; * @author Lion Li */ @Validated -@Api(value = "数据字典信息控制器", tags = {"数据字典信息管理"}) @RequiredArgsConstructor @RestController @RequestMapping("/system/dict/type") @@ -35,14 +31,18 @@ public class SysDictTypeController extends BaseController { private final ISysDictTypeService dictTypeService; - @ApiOperation("查询字典类型列表") + /** + * 查询字典类型列表 + */ @SaCheckPermission("system:dict:list") @GetMapping("/list") public TableDataInfo list(SysDictType dictType, PageQuery pageQuery) { return dictTypeService.selectPageDictTypeList(dictType, pageQuery); } - @ApiOperation("导出字典类型列表") + /** + * 导出字典类型列表 + */ @Log(title = "字典类型", businessType = BusinessType.EXPORT) @SaCheckPermission("system:dict:export") @PostMapping("/export") @@ -53,18 +53,18 @@ public class SysDictTypeController extends BaseController { /** * 查询字典类型详细 + * + * @param dictId 字典ID */ - @ApiOperation("查询字典类型详细") @SaCheckPermission("system:dict:query") @GetMapping(value = "/{dictId}") - public R getInfo(@ApiParam("字典ID") @PathVariable Long dictId) { + public R getInfo(@PathVariable Long dictId) { return R.ok(dictTypeService.selectDictTypeById(dictId)); } /** * 新增字典类型 */ - @ApiOperation("新增字典类型") @SaCheckPermission("system:dict:add") @Log(title = "字典类型", businessType = BusinessType.INSERT) @PostMapping @@ -72,13 +72,13 @@ public class SysDictTypeController extends BaseController { if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict))) { return R.fail("新增字典'" + dict.getDictName() + "'失败,字典类型已存在"); } - return toAjax(dictTypeService.insertDictType(dict)); + dictTypeService.insertDictType(dict); + return R.ok(); } /** * 修改字典类型 */ - @ApiOperation("修改字典类型") @SaCheckPermission("system:dict:edit") @Log(title = "字典类型", businessType = BusinessType.UPDATE) @PutMapping @@ -86,17 +86,19 @@ public class SysDictTypeController extends BaseController { if (UserConstants.NOT_UNIQUE.equals(dictTypeService.checkDictTypeUnique(dict))) { return R.fail("修改字典'" + dict.getDictName() + "'失败,字典类型已存在"); } - return toAjax(dictTypeService.updateDictType(dict)); + dictTypeService.updateDictType(dict); + return R.ok(); } /** * 删除字典类型 + * + * @param dictIds 字典ID串 */ - @ApiOperation("删除字典类型") @SaCheckPermission("system:dict:remove") @Log(title = "字典类型", businessType = BusinessType.DELETE) @DeleteMapping("/{dictIds}") - public R remove(@ApiParam("字典ID串") @PathVariable Long[] dictIds) { + public R remove(@PathVariable Long[] dictIds) { dictTypeService.deleteDictTypeByIds(dictIds); return R.ok(); } @@ -104,7 +106,6 @@ public class SysDictTypeController extends BaseController { /** * 刷新字典缓存 */ - @ApiOperation("刷新字典缓存") @SaCheckPermission("system:dict:remove") @Log(title = "字典类型", businessType = BusinessType.CLEAN) @DeleteMapping("/refreshCache") @@ -116,7 +117,6 @@ public class SysDictTypeController extends BaseController { /** * 获取字典选择框列表 */ - @ApiOperation("获取字典选择框列表") @GetMapping("/optionselect") public R> optionselect() { List dictTypes = dictTypeService.selectDictTypeAll(); diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java index c68891997..698257406 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java @@ -1,9 +1,8 @@ package com.ruoyi.web.controller.system; +import cn.dev33.satoken.annotation.SaIgnore; import com.ruoyi.common.config.RuoYiConfig; import com.ruoyi.common.utils.StringUtils; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @@ -13,7 +12,6 @@ import org.springframework.web.bind.annotation.RestController; * * @author Lion Li */ -@Api(value = "首页控制器", tags = {"首页管理"}) @RequiredArgsConstructor @RestController public class SysIndexController { @@ -26,7 +24,7 @@ public class SysIndexController { /** * 访问首页,提示语 */ - @ApiOperation("访问首页,提示语") + @SaIgnore @GetMapping("/") public String index() { return StringUtils.format("欢迎使用{}后台管理框架,当前版本:v{},请通过前端地址访问。", ruoyiConfig.getName(), ruoyiConfig.getVersion()); diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java index cdb1d6cd6..a65cb6252 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java @@ -1,13 +1,12 @@ package com.ruoyi.web.controller.system; -import cn.dev33.satoken.exception.NotLoginException; -import cn.dev33.satoken.stp.StpUtil; -import com.ruoyi.common.annotation.Anonymous; +import cn.dev33.satoken.annotation.SaIgnore; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.entity.SysMenu; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.model.LoginBody; +import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.core.domain.model.SmsLoginBody; import com.ruoyi.common.helper.LoginHelper; import com.ruoyi.system.domain.vo.RouterVo; @@ -15,8 +14,6 @@ import com.ruoyi.system.service.ISysMenuService; import com.ruoyi.system.service.ISysUserService; import com.ruoyi.system.service.SysLoginService; import com.ruoyi.system.service.SysPermissionService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -28,7 +25,6 @@ import javax.validation.constraints.NotBlank; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; /** * 登录验证 @@ -36,7 +32,6 @@ import java.util.Set; * @author Lion Li */ @Validated -@Api(value = "登录验证控制器", tags = {"登录验证管理"}) @RequiredArgsConstructor @RestController public class SysLoginController { @@ -52,8 +47,7 @@ public class SysLoginController { * @param loginBody 登录信息 * @return 结果 */ - @Anonymous - @ApiOperation("登录方法") + @SaIgnore @PostMapping("/login") public R> login(@Validated @RequestBody LoginBody loginBody) { Map ajax = new HashMap<>(); @@ -70,8 +64,7 @@ public class SysLoginController { * @param smsLoginBody 登录信息 * @return 结果 */ - @Anonymous - @ApiOperation("短信登录(示例)") + @SaIgnore @PostMapping("/smsLogin") public R> smsLogin(@Validated @RequestBody SmsLoginBody smsLoginBody) { Map ajax = new HashMap<>(); @@ -87,8 +80,7 @@ public class SysLoginController { * @param xcxCode 小程序code * @return 结果 */ - @Anonymous - @ApiOperation("小程序登录(示例)") + @SaIgnore @PostMapping("/xcxLogin") public R> xcxLogin(@NotBlank(message = "{xcx.code.not.blank}") String xcxCode) { Map ajax = new HashMap<>(); @@ -98,16 +90,13 @@ public class SysLoginController { return R.ok(ajax); } - @Anonymous - @ApiOperation("登出方法") + /** + * 退出登录 + */ + @SaIgnore @PostMapping("/logout") public R logout() { - try { - String username = LoginHelper.getUsername(); - StpUtil.logout(); - loginService.logout(username); - } catch (NotLoginException e) { - } + loginService.logout(); return R.ok("退出成功"); } @@ -116,18 +105,14 @@ public class SysLoginController { * * @return 用户信息 */ - @ApiOperation("获取用户信息") @GetMapping("getInfo") public R> getInfo() { - SysUser user = userService.selectUserById(LoginHelper.getUserId()); - // 角色集合 - Set roles = permissionService.getRolePermission(user); - // 权限集合 - Set permissions = permissionService.getMenuPermission(user); + LoginUser loginUser = LoginHelper.getLoginUser(); + SysUser user = userService.selectUserById(loginUser.getUserId()); Map ajax = new HashMap<>(); ajax.put("user", user); - ajax.put("roles", roles); - ajax.put("permissions", permissions); + ajax.put("roles", loginUser.getRolePermission()); + ajax.put("permissions", loginUser.getMenuPermission()); return R.ok(ajax); } @@ -136,7 +121,6 @@ public class SysLoginController { * * @return 路由信息 */ - @ApiOperation("获取路由信息") @GetMapping("getRouters") public R> getRouters() { Long userId = LoginHelper.getUserId(); 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 030363e00..e80f0ee7c 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 @@ -10,9 +10,6 @@ import com.ruoyi.common.core.domain.entity.SysMenu; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.system.service.ISysMenuService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -27,7 +24,6 @@ import java.util.Map; * @author Lion Li */ @Validated -@Api(value = "菜单信息控制器", tags = {"菜单信息管理"}) @RequiredArgsConstructor @RestController @RequestMapping("/system/menu") @@ -38,7 +34,6 @@ public class SysMenuController extends BaseController { /** * 获取菜单列表 */ - @ApiOperation("获取菜单列表") @SaCheckPermission("system:menu:list") @GetMapping("/list") public R> list(SysMenu menu) { @@ -48,18 +43,18 @@ public class SysMenuController extends BaseController { /** * 根据菜单编号获取详细信息 + * + * @param menuId 菜单ID */ - @ApiOperation("根据菜单编号获取详细信息") @SaCheckPermission("system:menu:query") @GetMapping(value = "/{menuId}") - public R getInfo(@ApiParam("菜单ID") @PathVariable Long menuId) { + public R getInfo(@PathVariable Long menuId) { return R.ok(menuService.selectMenuById(menuId)); } /** * 获取菜单下拉树列表 */ - @ApiOperation("获取菜单下拉树列表") @GetMapping("/treeselect") public R>> treeselect(SysMenu menu) { List menus = menuService.selectMenuList(menu, getUserId()); @@ -68,10 +63,11 @@ public class SysMenuController extends BaseController { /** * 加载对应角色菜单列表树 + * + * @param roleId 角色ID */ - @ApiOperation("加载对应角色菜单列表树") @GetMapping(value = "/roleMenuTreeselect/{roleId}") - public R> roleMenuTreeselect(@ApiParam("角色ID") @PathVariable("roleId") Long roleId) { + public R> roleMenuTreeselect(@PathVariable("roleId") Long roleId) { List menus = menuService.selectMenuList(getUserId()); Map ajax = new HashMap<>(); ajax.put("checkedKeys", menuService.selectMenuListByRoleId(roleId)); @@ -82,7 +78,6 @@ public class SysMenuController extends BaseController { /** * 新增菜单 */ - @ApiOperation("新增菜单") @SaCheckPermission("system:menu:add") @Log(title = "菜单管理", businessType = BusinessType.INSERT) @PostMapping @@ -98,7 +93,6 @@ public class SysMenuController extends BaseController { /** * 修改菜单 */ - @ApiOperation("修改菜单") @SaCheckPermission("system:menu:edit") @Log(title = "菜单管理", businessType = BusinessType.UPDATE) @PutMapping @@ -115,17 +109,18 @@ public class SysMenuController extends BaseController { /** * 删除菜单 + * + * @param menuId 菜单ID */ - @ApiOperation("删除菜单") @SaCheckPermission("system:menu:remove") @Log(title = "菜单管理", businessType = BusinessType.DELETE) @DeleteMapping("/{menuId}") - public R remove(@ApiParam("菜单ID") @PathVariable("menuId") Long 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/SysNoticeController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java index 6febd3e3f..54b30d60d 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java @@ -3,15 +3,12 @@ package com.ruoyi.web.controller.system; import cn.dev33.satoken.annotation.SaCheckPermission; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.PageQuery; +import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.system.domain.SysNotice; import com.ruoyi.system.service.ISysNoticeService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -22,7 +19,6 @@ import org.springframework.web.bind.annotation.*; * @author Lion Li */ @Validated -@Api(value = "公告信息控制器", tags = {"公告信息管理"}) @RequiredArgsConstructor @RestController @RequestMapping("/system/notice") @@ -33,7 +29,6 @@ public class SysNoticeController extends BaseController { /** * 获取通知公告列表 */ - @ApiOperation("获取通知公告列表") @SaCheckPermission("system:notice:list") @GetMapping("/list") public TableDataInfo list(SysNotice notice, PageQuery pageQuery) { @@ -42,18 +37,18 @@ public class SysNoticeController extends BaseController { /** * 根据通知公告编号获取详细信息 + * + * @param noticeId 公告ID */ - @ApiOperation("根据通知公告编号获取详细信息") @SaCheckPermission("system:notice:query") @GetMapping(value = "/{noticeId}") - public R getInfo(@ApiParam("公告ID") @PathVariable Long noticeId) { + public R getInfo(@PathVariable Long noticeId) { return R.ok(noticeService.selectNoticeById(noticeId)); } /** * 新增通知公告 */ - @ApiOperation("新增通知公告") @SaCheckPermission("system:notice:add") @Log(title = "通知公告", businessType = BusinessType.INSERT) @PostMapping @@ -64,7 +59,6 @@ public class SysNoticeController extends BaseController { /** * 修改通知公告 */ - @ApiOperation("修改通知公告") @SaCheckPermission("system:notice:edit") @Log(title = "通知公告", businessType = BusinessType.UPDATE) @PutMapping @@ -74,12 +68,13 @@ public class SysNoticeController extends BaseController { /** * 删除通知公告 + * + * @param noticeIds 公告ID串 */ - @ApiOperation("删除通知公告") @SaCheckPermission("system:notice:remove") @Log(title = "通知公告", businessType = BusinessType.DELETE) @DeleteMapping("/{noticeIds}") - public R remove(@ApiParam("公告ID串") @PathVariable Long[] noticeIds) { + public R remove(@PathVariable Long[] noticeIds) { return toAjax(noticeService.deleteNoticeByIds(noticeIds)); } } 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 cf2fd1178..8dc4876ef 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 @@ -4,8 +4,8 @@ import cn.dev33.satoken.annotation.SaCheckPermission; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.annotation.RepeatSubmit; import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.PageQuery; +import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.validate.AddGroup; import com.ruoyi.common.core.validate.EditGroup; @@ -14,9 +14,6 @@ import com.ruoyi.common.enums.BusinessType; import com.ruoyi.system.domain.bo.SysOssConfigBo; import com.ruoyi.system.domain.vo.SysOssConfigVo; import com.ruoyi.system.service.ISysOssConfigService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -26,14 +23,13 @@ import javax.validation.constraints.NotNull; import java.util.Arrays; /** - * 对象存储配置Controller + * 对象存储配置 * * @author Lion Li * @author 孤舟烟雨 * @date 2021-08-13 */ @Validated -@Api(value = "对象存储配置控制器", tags = {"对象存储配置管理"}) @RequiredArgsConstructor @RestController @RequestMapping("/system/oss/config") @@ -44,7 +40,6 @@ public class SysOssConfigController extends BaseController { /** * 查询对象存储配置列表 */ - @ApiOperation("查询对象存储配置列表") @SaCheckPermission("system:oss:list") @GetMapping("/list") public TableDataInfo list(@Validated(QueryGroup.class) SysOssConfigBo bo, PageQuery pageQuery) { @@ -53,57 +48,54 @@ public class SysOssConfigController extends BaseController { /** * 获取对象存储配置详细信息 + * + * @param ossConfigId OSS配置ID */ - @ApiOperation("获取对象存储配置详细信息") @SaCheckPermission("system:oss:query") @GetMapping("/{ossConfigId}") - public R getInfo(@ApiParam("OSS配置ID") - @NotNull(message = "主键不能为空") - @PathVariable("ossConfigId") Long ossConfigId) { + public R getInfo(@NotNull(message = "主键不能为空") + @PathVariable Long ossConfigId) { return R.ok(iSysOssConfigService.queryById(ossConfigId)); } /** * 新增对象存储配置 */ - @ApiOperation("新增对象存储配置") @SaCheckPermission("system:oss:add") @Log(title = "对象存储配置", businessType = BusinessType.INSERT) @RepeatSubmit() @PostMapping() public R add(@Validated(AddGroup.class) @RequestBody SysOssConfigBo bo) { - return toAjax(iSysOssConfigService.insertByBo(bo) ? 1 : 0); + return toAjax(iSysOssConfigService.insertByBo(bo)); } /** * 修改对象存储配置 */ - @ApiOperation("修改对象存储配置") @SaCheckPermission("system:oss:edit") @Log(title = "对象存储配置", businessType = BusinessType.UPDATE) @RepeatSubmit() @PutMapping() public R edit(@Validated(EditGroup.class) @RequestBody SysOssConfigBo bo) { - return toAjax(iSysOssConfigService.updateByBo(bo) ? 1 : 0); + return toAjax(iSysOssConfigService.updateByBo(bo)); } /** * 删除对象存储配置 + * + * @param ossConfigIds OSS配置ID串 */ - @ApiOperation("删除对象存储配置") @SaCheckPermission("system:oss:remove") @Log(title = "对象存储配置", businessType = BusinessType.DELETE) @DeleteMapping("/{ossConfigIds}") - public R remove(@ApiParam("OSS配置ID串") - @NotEmpty(message = "主键不能为空") - @PathVariable Long[] ossConfigIds) { - return toAjax(iSysOssConfigService.deleteWithValidByIds(Arrays.asList(ossConfigIds), true) ? 1 : 0); + public R remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] ossConfigIds) { + return toAjax(iSysOssConfigService.deleteWithValidByIds(Arrays.asList(ossConfigIds), true)); } /** * 状态修改 */ - @ApiOperation("状态修改") @SaCheckPermission("system:oss:edit") @Log(title = "对象存储状态修改", businessType = BusinessType.UPDATE) @PutMapping("/changeStatus") 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 d4e52acc6..606895a74 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,11 +15,12 @@ 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; import com.ruoyi.system.service.ISysOssService; -import io.swagger.annotations.*; import lombok.RequiredArgsConstructor; import org.springframework.http.MediaType; import org.springframework.validation.annotation.Validated; @@ -28,7 +29,6 @@ import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import javax.validation.constraints.NotEmpty; -import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.HashMap; @@ -41,7 +41,6 @@ import java.util.Map; * @author Lion Li */ @Validated -@Api(value = "对象存储控制器", tags = {"对象存储管理"}) @RequiredArgsConstructor @RestController @RequestMapping("/system/oss") @@ -52,7 +51,6 @@ public class SysOssController extends BaseController { /** * 查询OSS对象存储列表 */ - @ApiOperation("查询OSS对象存储列表") @SaCheckPermission("system:oss:list") @GetMapping("/list") public TableDataInfo list(@Validated(QueryGroup.class) SysOssBo bo, PageQuery pageQuery) { @@ -61,32 +59,30 @@ public class SysOssController extends BaseController { /** * 查询OSS对象基于id串 + * + * @param ossIds OSS对象ID串 */ - @ApiOperation("查询OSS对象基于ID") @SaCheckPermission("system:oss:list") @GetMapping("/listByIds/{ossIds}") - public R> listByIds(@ApiParam("OSS对象ID串") - @NotEmpty(message = "主键不能为空") - @PathVariable Long[] ossIds) { + public R> listByIds(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] ossIds) { List list = iSysOssService.listByIds(Arrays.asList(ossIds)); return R.ok(list); } /** * 上传OSS对象存储 + * + * @param file 文件 */ - @ApiOperation("上传OSS对象存储") - @ApiImplicitParams({ - @ApiImplicitParam(name = "file", value = "文件", paramType = "query", dataTypeClass = File.class, required = true) - }) @SaCheckPermission("system:oss:upload") @Log(title = "OSS对象存储", businessType = BusinessType.INSERT) - @PostMapping("/upload") + @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public R> upload(@RequestPart("file") MultipartFile file) { 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()); @@ -94,41 +90,28 @@ public class SysOssController extends BaseController { return R.ok(map); } - @ApiOperation("下载OSS对象存储") + /** + * 下载OSS对象 + * + * @param ossId OSS对象ID + */ @SaCheckPermission("system:oss:download") @GetMapping("/download/{ossId}") - public void download(@ApiParam("OSS对象ID") @PathVariable Long ossId, HttpServletResponse response) throws IOException { - SysOss sysOss = iSysOssService.getById(ossId); - if (ObjectUtil.isNull(sysOss)) { - throw new ServiceException("文件数据不存在!"); - } - response.reset(); - 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)); + public void download(@PathVariable Long ossId, HttpServletResponse response) throws IOException { + iSysOssService.download(ossId,response); } /** * 删除OSS对象存储 + * + * @param ossIds OSS对象ID串 */ - @ApiOperation("删除OSS对象存储") @SaCheckPermission("system:oss:remove") @Log(title = "OSS对象存储", businessType = BusinessType.DELETE) @DeleteMapping("/{ossIds}") - public R remove(@ApiParam("OSS对象ID串") - @NotEmpty(message = "主键不能为空") - @PathVariable Long[] ossIds) { - return toAjax(iSysOssService.deleteWithValidByIds(Arrays.asList(ossIds), true) ? 1 : 0); + public R remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] ossIds) { + return toAjax(iSysOssService.deleteWithValidByIds(Arrays.asList(ossIds), true)); } } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java index 7e08698f9..656987776 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java @@ -4,16 +4,13 @@ import cn.dev33.satoken.annotation.SaCheckPermission; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.PageQuery; +import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.system.domain.SysPost; import com.ruoyi.system.service.ISysPostService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -27,7 +24,6 @@ import java.util.List; * @author Lion Li */ @Validated -@Api(value = "岗位信息控制器", tags = {"岗位信息管理"}) @RequiredArgsConstructor @RestController @RequestMapping("/system/post") @@ -38,14 +34,15 @@ public class SysPostController extends BaseController { /** * 获取岗位列表 */ - @ApiOperation("获取岗位列表") @SaCheckPermission("system:post:list") @GetMapping("/list") public TableDataInfo list(SysPost post, PageQuery pageQuery) { return postService.selectPagePostList(post, pageQuery); } - @ApiOperation("导出岗位列表") + /** + * 导出岗位列表 + */ @Log(title = "岗位管理", businessType = BusinessType.EXPORT) @SaCheckPermission("system:post:export") @PostMapping("/export") @@ -56,18 +53,18 @@ public class SysPostController extends BaseController { /** * 根据岗位编号获取详细信息 + * + * @param postId 岗位ID */ - @ApiOperation("根据岗位编号获取详细信息") @SaCheckPermission("system:post:query") @GetMapping(value = "/{postId}") - public R getInfo(@ApiParam("岗位ID") @PathVariable Long postId) { + public R getInfo(@PathVariable Long postId) { return R.ok(postService.selectPostById(postId)); } /** * 新增岗位 */ - @ApiOperation("新增岗位") @SaCheckPermission("system:post:add") @Log(title = "岗位管理", businessType = BusinessType.INSERT) @PostMapping @@ -83,7 +80,6 @@ public class SysPostController extends BaseController { /** * 修改岗位 */ - @ApiOperation("修改岗位") @SaCheckPermission("system:post:edit") @Log(title = "岗位管理", businessType = BusinessType.UPDATE) @PutMapping @@ -98,19 +94,19 @@ public class SysPostController extends BaseController { /** * 删除岗位 + * + * @param postIds 岗位ID串 */ - @ApiOperation("删除岗位") @SaCheckPermission("system:post:remove") @Log(title = "岗位管理", businessType = BusinessType.DELETE) @DeleteMapping("/{postIds}") - public R remove(@ApiParam("岗位ID串") @PathVariable Long[] postIds) { + public R remove(@PathVariable Long[] postIds) { return toAjax(postService.deletePostByIds(postIds)); } /** * 获取岗位选择框列表 */ - @ApiOperation("获取岗位选择框列表") @GetMapping("/optionselect") public R> optionselect() { List posts = postService.selectPostAll(); 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 22b506f36..77a8767de 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,18 +12,15 @@ 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 io.swagger.annotations.Api; -import io.swagger.annotations.ApiImplicitParam; -import io.swagger.annotations.ApiImplicitParams; -import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; +import org.springframework.http.MediaType; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; -import java.io.File; import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -34,7 +31,6 @@ import java.util.Map; * @author Lion Li */ @Validated -@Api(value = "个人信息控制器", tags = {"个人信息管理"}) @RequiredArgsConstructor @RestController @RequestMapping("/system/user/profile") @@ -46,7 +42,6 @@ public class SysProfileController extends BaseController { /** * 个人信息 */ - @ApiOperation("个人信息") @GetMapping public R> profile() { SysUser user = userService.selectUserById(getUserId()); @@ -60,7 +55,6 @@ public class SysProfileController extends BaseController { /** * 修改用户 */ - @ApiOperation("修改用户") @Log(title = "个人信息", businessType = BusinessType.UPDATE) @PutMapping public R updateProfile(@RequestBody SysUser user) { @@ -75,6 +69,8 @@ public class SysProfileController extends BaseController { user.setUserId(getUserId()); user.setUserName(null); user.setPassword(null); + user.setAvatar(null); + user.setDeptId(null); if (userService.updateUserProfile(user) > 0) { return R.ok(); } @@ -83,12 +79,10 @@ public class SysProfileController extends BaseController { /** * 重置密码 + * + * @param newPassword 旧密码 + * @param oldPassword 新密码 */ - @ApiOperation("重置密码") - @ApiImplicitParams({ - @ApiImplicitParam(name = "oldPassword", value = "旧密码", paramType = "query", dataTypeClass = String.class), - @ApiImplicitParam(name = "newPassword", value = "新密码", paramType = "query", dataTypeClass = String.class) - }) @Log(title = "个人信息", businessType = BusinessType.UPDATE) @PutMapping("/updatePwd") public R updatePwd(String oldPassword, String newPassword) { @@ -110,21 +104,19 @@ public class SysProfileController extends BaseController { /** * 头像上传 + * + * @param avatarfile 用户头像 */ - @ApiOperation("头像上传") - @ApiImplicitParams({ - @ApiImplicitParam(name = "avatarfile", value = "用户头像", paramType = "query", dataTypeClass = File.class, required = true) - }) @Log(title = "用户头像", businessType = BusinessType.UPDATE) - @PostMapping("/avatar") - public R> avatar(@RequestPart("avatarfile") MultipartFile file) { + @PostMapping(value = "/avatar", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + public R> avatar(@RequestPart("avatarfile") MultipartFile avatarfile) { Map ajax = new HashMap<>(); - if (!file.isEmpty()) { - String extension = FileUtil.extName(file.getOriginalFilename()); + if (!avatarfile.isEmpty()) { + String extension = FileUtil.extName(avatarfile.getOriginalFilename()); if (!StringUtils.equalsAnyIgnoreCase(extension, MimeTypeUtils.IMAGE_EXTENSION)) { return R.fail("文件格式不正确,请上传" + Arrays.toString(MimeTypeUtils.IMAGE_EXTENSION) + "格式"); } - SysOss oss = iSysOssService.upload(file); + 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/SysRegisterController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java index b8cedd67a..26445820e 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java @@ -1,13 +1,11 @@ package com.ruoyi.web.controller.system; -import com.ruoyi.common.annotation.Anonymous; +import cn.dev33.satoken.annotation.SaIgnore; import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.model.RegisterBody; import com.ruoyi.system.service.ISysConfigService; import com.ruoyi.system.service.SysRegisterService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; @@ -20,7 +18,6 @@ import org.springframework.web.bind.annotation.RestController; * @author Lion Li */ @Validated -@Api(value = "注册验证控制器", tags = {"注册验证管理"}) @RequiredArgsConstructor @RestController public class SysRegisterController extends BaseController { @@ -28,8 +25,10 @@ public class SysRegisterController extends BaseController { private final SysRegisterService registerService; private final ISysConfigService configService; - @Anonymous - @ApiOperation("用户注册") + /** + * 用户注册 + */ + @SaIgnore @PostMapping("/register") public R register(@Validated @RequestBody RegisterBody user) { if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser")))) { diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java index 9b7cb268b..5768806c2 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java @@ -5,8 +5,9 @@ import cn.hutool.core.util.ObjectUtil; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.PageQuery; +import com.ruoyi.common.core.domain.R; +import com.ruoyi.common.core.domain.entity.SysDept; import com.ruoyi.common.core.domain.entity.SysRole; import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.model.LoginUser; @@ -15,16 +16,18 @@ import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.helper.LoginHelper; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.system.domain.SysUserRole; +import com.ruoyi.system.service.ISysDeptService; import com.ruoyi.system.service.ISysRoleService; import com.ruoyi.system.service.ISysUserService; import com.ruoyi.system.service.SysPermissionService; -import io.swagger.annotations.*; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletResponse; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * 角色信息 @@ -32,7 +35,6 @@ import java.util.List; * @author Lion Li */ @Validated -@Api(value = "角色信息控制器", tags = {"角色信息管理"}) @RequiredArgsConstructor @RestController @RequestMapping("/system/role") @@ -40,16 +42,21 @@ public class SysRoleController extends BaseController { private final ISysRoleService roleService; private final ISysUserService userService; + private final ISysDeptService deptService; private final SysPermissionService permissionService; - @ApiOperation("查询角色信息列表") + /** + * 获取角色信息列表 + */ @SaCheckPermission("system:role:list") @GetMapping("/list") public TableDataInfo list(SysRole role, PageQuery pageQuery) { return roleService.selectPageRoleList(role, pageQuery); } - @ApiOperation("导出角色信息列表") + /** + * 导出角色信息列表 + */ @Log(title = "角色管理", businessType = BusinessType.EXPORT) @SaCheckPermission("system:role:export") @PostMapping("/export") @@ -60,11 +67,12 @@ public class SysRoleController extends BaseController { /** * 根据角色编号获取详细信息 + * + * @param roleId 角色ID */ - @ApiOperation("根据角色编号获取详细信息") @SaCheckPermission("system:role:query") @GetMapping(value = "/{roleId}") - public R getInfo(@ApiParam("角色ID") @PathVariable Long roleId) { + public R getInfo(@PathVariable Long roleId) { roleService.checkRoleDataScope(roleId); return R.ok(roleService.selectRoleById(roleId)); } @@ -72,7 +80,6 @@ public class SysRoleController extends BaseController { /** * 新增角色 */ - @ApiOperation("新增角色") @SaCheckPermission("system:role:add") @Log(title = "角色管理", businessType = BusinessType.INSERT) @PostMapping @@ -89,7 +96,6 @@ public class SysRoleController extends BaseController { /** * 修改保存角色 */ - @ApiOperation("修改保存角色") @SaCheckPermission("system:role:edit") @Log(title = "角色管理", businessType = BusinessType.UPDATE) @PutMapping @@ -118,7 +124,6 @@ public class SysRoleController extends BaseController { /** * 修改保存数据权限 */ - @ApiOperation("修改保存数据权限") @SaCheckPermission("system:role:edit") @Log(title = "角色管理", businessType = BusinessType.UPDATE) @PutMapping("/dataScope") @@ -131,7 +136,6 @@ public class SysRoleController extends BaseController { /** * 状态修改 */ - @ApiOperation("状态修改") @SaCheckPermission("system:role:edit") @Log(title = "角色管理", businessType = BusinessType.UPDATE) @PutMapping("/changeStatus") @@ -143,19 +147,19 @@ public class SysRoleController extends BaseController { /** * 删除角色 + * + * @param roleIds 角色ID串 */ - @ApiOperation("删除角色") @SaCheckPermission("system:role:remove") @Log(title = "角色管理", businessType = BusinessType.DELETE) @DeleteMapping("/{roleIds}") - public R remove(@ApiParam("角色ID串") @PathVariable Long[] roleIds) { + public R remove(@PathVariable Long[] roleIds) { return toAjax(roleService.deleteRoleByIds(roleIds)); } /** * 获取角色选择框列表 */ - @ApiOperation("获取角色选择框列表") @SaCheckPermission("system:role:query") @GetMapping("/optionselect") public R> optionselect() { @@ -165,7 +169,6 @@ public class SysRoleController extends BaseController { /** * 查询已分配用户角色列表 */ - @ApiOperation("查询已分配用户角色列表") @SaCheckPermission("system:role:list") @GetMapping("/authUser/allocatedList") public TableDataInfo allocatedList(SysUser user, PageQuery pageQuery) { @@ -175,7 +178,6 @@ public class SysRoleController extends BaseController { /** * 查询未分配用户角色列表 */ - @ApiOperation("查询未分配用户角色列表") @SaCheckPermission("system:role:list") @GetMapping("/authUser/unallocatedList") public TableDataInfo unallocatedList(SysUser user, PageQuery pageQuery) { @@ -185,7 +187,6 @@ public class SysRoleController extends BaseController { /** * 取消授权用户 */ - @ApiOperation("取消授权用户") @SaCheckPermission("system:role:edit") @Log(title = "角色管理", businessType = BusinessType.GRANT) @PutMapping("/authUser/cancel") @@ -195,12 +196,10 @@ public class SysRoleController extends BaseController { /** * 批量取消授权用户 + * + * @param roleId 角色ID + * @param userIds 用户ID串 */ - @ApiOperation("批量取消授权用户") - @ApiImplicitParams({ - @ApiImplicitParam(name = "roleId", value = "角色ID", paramType = "query", dataTypeClass = String.class), - @ApiImplicitParam(name = "userIds", value = "用户ID串", paramType = "query", dataTypeClass = String.class) - }) @SaCheckPermission("system:role:edit") @Log(title = "角色管理", businessType = BusinessType.GRANT) @PutMapping("/authUser/cancelAll") @@ -210,12 +209,10 @@ public class SysRoleController extends BaseController { /** * 批量选择用户授权 + * + * @param roleId 角色ID + * @param userIds 用户ID串 */ - @ApiOperation("批量选择用户授权") - @ApiImplicitParams({ - @ApiImplicitParam(name = "roleId", value = "角色ID", paramType = "query", dataTypeClass = String.class), - @ApiImplicitParam(name = "userIds", value = "用户ID串", paramType = "query", dataTypeClass = String.class) - }) @SaCheckPermission("system:role:edit") @Log(title = "角色管理", businessType = BusinessType.GRANT) @PutMapping("/authUser/selectAll") @@ -223,4 +220,18 @@ public class SysRoleController extends BaseController { roleService.checkRoleDataScope(roleId); return toAjax(roleService.insertAuthUsers(roleId, userIds)); } + + /** + * 获取对应角色部门树列表 + * + * @param roleId 角色ID + */ + @SaCheckPermission("system:role:list") + @GetMapping(value = "/deptTree/{roleId}") + public R> roleDeptTreeselect(@PathVariable("roleId") Long roleId) { + Map ajax = new HashMap<>(); + ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId)); + ajax.put("depts", deptService.selectDeptTreeList(new SysDept())); + return R.ok(ajax); + } } 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 07553d7aa..7e358d511 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 @@ -3,6 +3,7 @@ package com.ruoyi.web.controller.system; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.dev33.satoken.secure.BCrypt; import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.lang.tree.Tree; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ObjectUtil; import com.ruoyi.common.annotation.Log; @@ -17,16 +18,18 @@ import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.common.excel.ExcelResult; import com.ruoyi.common.helper.LoginHelper; +import com.ruoyi.common.utils.StreamUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.system.domain.vo.SysUserExportVo; import com.ruoyi.system.domain.vo.SysUserImportVo; import com.ruoyi.system.listener.SysUserImportListener; +import com.ruoyi.system.service.ISysDeptService; import com.ruoyi.system.service.ISysPostService; import com.ruoyi.system.service.ISysRoleService; import com.ruoyi.system.service.ISysUserService; -import io.swagger.annotations.*; import lombok.RequiredArgsConstructor; +import org.springframework.http.MediaType; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -36,7 +39,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; /** * 用户信息 @@ -44,7 +46,6 @@ import java.util.stream.Collectors; * @author Lion Li */ @Validated -@Api(value = "用户信息控制器", tags = {"用户信息管理"}) @RequiredArgsConstructor @RestController @RequestMapping("/system/user") @@ -53,18 +54,20 @@ public class SysUserController extends BaseController { private final ISysUserService userService; private final ISysRoleService roleService; private final ISysPostService postService; + private final ISysDeptService deptService; /** * 获取用户列表 */ - @ApiOperation("获取用户列表") @SaCheckPermission("system:user:list") @GetMapping("/list") public TableDataInfo list(SysUser user, PageQuery pageQuery) { return userService.selectPageUserList(user, pageQuery); } - @ApiOperation("导出用户列表") + /** + * 导出用户列表 + */ @Log(title = "用户管理", businessType = BusinessType.EXPORT) @SaCheckPermission("system:user:export") @PostMapping("/export") @@ -82,19 +85,23 @@ public class SysUserController extends BaseController { ExcelUtil.exportExcel(listVo, "用户数据", SysUserExportVo.class, response); } - @ApiOperation("导入用户列表") - @ApiImplicitParams({ - @ApiImplicitParam(name = "file", value = "导入文件", dataType = "java.io.File", required = true), - }) + /** + * 导入数据 + * + * @param file 导入文件 + * @param updateSupport 是否更新已存在数据 + */ @Log(title = "用户管理", businessType = BusinessType.IMPORT) @SaCheckPermission("system:user:import") - @PostMapping("/importData") + @PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public R importData(@RequestPart("file") MultipartFile file, boolean updateSupport) throws Exception { ExcelResult result = ExcelUtil.importExcel(file.getInputStream(), SysUserImportVo.class, new SysUserImportListener(updateSupport)); return R.ok(result.getAnalysis()); } - @ApiOperation("下载导入模板") + /** + * 获取导入模板 + */ @PostMapping("/importTemplate") public void importTemplate(HttpServletResponse response) { ExcelUtil.exportExcel(new ArrayList<>(), "用户数据", SysUserImportVo.class, response); @@ -102,21 +109,22 @@ public class SysUserController extends BaseController { /** * 根据用户编号获取详细信息 + * + * @param userId 用户ID */ - @ApiOperation("根据用户编号获取详细信息") @SaCheckPermission("system:user:query") @GetMapping(value = {"/", "/{userId}"}) - public R> getInfo(@ApiParam("用户ID") @PathVariable(value = "userId", required = false) Long userId) { + public R> getInfo(@PathVariable(value = "userId", required = false) Long userId) { userService.checkUserDataScope(userId); Map ajax = new HashMap<>(); List roles = roleService.selectRoleAll(); - ajax.put("roles", LoginHelper.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); + ajax.put("roles", LoginHelper.isAdmin(userId) ? roles : StreamUtils.filter(roles, r -> !r.isAdmin())); ajax.put("posts", postService.selectPostAll()); if (ObjectUtil.isNotNull(userId)) { SysUser sysUser = userService.selectUserById(userId); ajax.put("user", sysUser); ajax.put("postIds", postService.selectPostListByUserId(userId)); - ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList())); + ajax.put("roleIds", StreamUtils.toList(sysUser.getRoles(), SysRole::getRoleId)); } return R.ok(ajax); } @@ -124,12 +132,11 @@ public class SysUserController extends BaseController { /** * 新增用户 */ - @ApiOperation("新增用户") @SaCheckPermission("system:user:add") @Log(title = "用户管理", businessType = BusinessType.INSERT) @PostMapping public R add(@Validated @RequestBody SysUser user) { - if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user.getUserName()))) { + if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user))) { return R.fail("新增用户'" + user.getUserName() + "'失败,登录账号已存在"); } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) { @@ -145,14 +152,15 @@ public class SysUserController extends BaseController { /** * 修改用户 */ - @ApiOperation("修改用户") @SaCheckPermission("system:user:edit") @Log(title = "用户管理", businessType = BusinessType.UPDATE) @PutMapping public R edit(@Validated @RequestBody SysUser user) { userService.checkUserAllowed(user); userService.checkUserDataScope(user.getUserId()); - if (StringUtils.isNotEmpty(user.getPhonenumber()) + if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(user))) { + return R.fail("修改用户'" + user.getUserName() + "'失败,登录账号已存在"); + } else if (StringUtils.isNotEmpty(user.getPhonenumber()) && UserConstants.NOT_UNIQUE.equals(userService.checkPhoneUnique(user))) { return R.fail("修改用户'" + user.getUserName() + "'失败,手机号码已存在"); } else if (StringUtils.isNotEmpty(user.getEmail()) @@ -164,12 +172,13 @@ public class SysUserController extends BaseController { /** * 删除用户 + * + * @param userIds 角色ID串 */ - @ApiOperation("删除用户") @SaCheckPermission("system:user:remove") @Log(title = "用户管理", businessType = BusinessType.DELETE) @DeleteMapping("/{userIds}") - public R remove(@ApiParam("角色ID串") @PathVariable Long[] userIds) { + public R remove(@PathVariable Long[] userIds) { if (ArrayUtil.contains(userIds, getUserId())) { return R.fail("当前用户不能删除"); } @@ -179,7 +188,6 @@ public class SysUserController extends BaseController { /** * 重置密码 */ - @ApiOperation("重置密码") @SaCheckPermission("system:user:resetPwd") @Log(title = "用户管理", businessType = BusinessType.UPDATE) @PutMapping("/resetPwd") @@ -193,7 +201,6 @@ public class SysUserController extends BaseController { /** * 状态修改 */ - @ApiOperation("状态修改") @SaCheckPermission("system:user:edit") @Log(title = "用户管理", businessType = BusinessType.UPDATE) @PutMapping("/changeStatus") @@ -205,27 +212,26 @@ public class SysUserController extends BaseController { /** * 根据用户编号获取授权角色 + * + * @param userId 用户ID */ - @ApiOperation("根据用户编号获取授权角色") @SaCheckPermission("system:user:query") @GetMapping("/authRole/{userId}") - public R> authRole(@ApiParam("用户ID") @PathVariable("userId") Long userId) { + public R> authRole(@PathVariable Long userId) { SysUser user = userService.selectUserById(userId); List roles = roleService.selectRolesByUserId(userId); Map ajax = new HashMap<>(); ajax.put("user", user); - ajax.put("roles", LoginHelper.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList())); + ajax.put("roles", LoginHelper.isAdmin(userId) ? roles : StreamUtils.filter(roles, r -> !r.isAdmin())); return R.ok(ajax); } /** * 用户授权角色 + * + * @param userId 用户Id + * @param roleIds 角色ID串 */ - @ApiOperation("用户授权角色") - @ApiImplicitParams({ - @ApiImplicitParam(name = "userId", value = "用户Id", paramType = "query", dataTypeClass = String.class), - @ApiImplicitParam(name = "roleIds", value = "角色ID串", paramType = "query", dataTypeClass = String.class) - }) @SaCheckPermission("system:user:edit") @Log(title = "用户管理", businessType = BusinessType.GRANT) @PutMapping("/authRole") @@ -234,4 +240,14 @@ public class SysUserController extends BaseController { userService.insertUserAuth(userId, roleIds); return R.ok(); } + + /** + * 获取部门树列表 + */ + @SaCheckPermission("system:user:list") + @GetMapping("/deptTree") + public R>> deptTree(SysDept dept) { + return R.ok(deptService.selectDeptTreeList(dept)); + } + } diff --git a/ruoyi-admin/src/main/resources/application-dev.yml b/ruoyi-admin/src/main/resources/application-dev.yml index f9327f779..7b7380b8a 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-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: @@ -138,6 +113,8 @@ spring: ssl: false redisson: + # redis key前缀 + keyPrefix: # 线程池数量 threads: 4 # Netty线程池数量 diff --git a/ruoyi-admin/src/main/resources/application-prod.yml b/ruoyi-admin/src/main/resources/application-prod.yml index def5f1666..970fe4c5a 100644 --- a/ruoyi-admin/src/main/resources/application-prod.yml +++ b/ruoyi-admin/src/main/resources/application-prod.yml @@ -5,7 +5,7 @@ spring.servlet.multipart.location: /ruoyi/server/temp spring.boot.admin.client: # 增加客户端开关 enabled: true - url: http://172.30.0.90:9090/admin + url: http://localhost:9090/admin instance: service-host-type: IP username: ruoyi @@ -16,7 +16,7 @@ xxl.job: # 执行器开关 enabled: true # 调度中心地址:如调度中心集群部署存在多个地址则用逗号分隔。 - admin-addresses: http://172.30.0.92:9100/xxl-job-admin + admin-addresses: http://localhost:9100/xxl-job-admin # 执行器通讯TOKEN:非空时启用 access-token: xxl-job executor: @@ -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,87 +48,62 @@ spring: datasource: # 主库数据源 master: + type: ${spring.datasource.type} driverClassName: com.mysql.cj.jdbc.Driver # jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562 # rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题) - url: jdbc:mysql://172.30.0.36:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true + url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true username: root password: root # 从库数据源 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:@//172.30.0.36:1521/XE +# 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://172.30.0.36:5432/postgres?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true +# 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://172.30.0.36: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: redis: # 地址 - host: 172.30.0.48 + host: localhost # 端口,默认为6379 port: 6379 # 数据库索引 @@ -141,6 +116,8 @@ spring: ssl: false redisson: + # redis key前缀 + keyPrefix: # 线程池数量 threads: 16 # Netty线程池数量 diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index ceaaf9561..80f3bf35e 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -53,6 +53,14 @@ logging: org.springframework: warn config: classpath:logback.xml +# 用户配置 +user: + password: + # 密码最大错误次数 + maxRetryCount: 5 + # 密码锁定时间(默认10分钟) + lockTime: 10 + # Spring配置 spring: application: @@ -75,10 +83,6 @@ spring: restart: # 热部署开关 enabled: true - mvc: - pathmatch: - # 适配 boot 2.6 路由与 springfox 兼容 - matching-strategy: ANT_PATH_MATCHER jackson: # 日期格式化 date-format: yyyy-MM-dd HH:mm:ss @@ -104,15 +108,13 @@ sa-token: # 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token) is-share: false # 是否尝试从header里读取token - is-read-head: true + is-read-header: true # 是否尝试从cookie里读取token is-read-cookie: false # token前缀 token-prefix: "Bearer" # jwt秘钥 jwt-secret-key: abcdefghijklmnopqrstuvwxyz - # 是否输出操作日志 - is-log: true # security配置 security: @@ -125,12 +127,8 @@ security: - /**/*.js # swagger 文档配置 - /favicon.ico - - /doc.html - - /swagger-resources/** - - /webjars/** - /*/api-docs - # druid 监控配置 - - /druid/** + - /*/api-docs/** # actuator 监控配置 - /actuator - /actuator/** @@ -183,46 +181,35 @@ mybatis-plus: swagger: # 是否开启swagger enabled: true - # 请求前缀 - pathMapping: /dev-api - # 标题 - title: '标题:${ruoyi.name}后台管理系统_接口文档' - # 描述 - description: '描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...' - # 版本 - version: '版本号: ${ruoyi-vue-plus.version}' - # 作者信息 - contact: - name: Lion Li - email: crazylionli@163.com - url: https://gitee.com/JavaLionLi/RuoYi-Vue-Plus - groups: - - name: 1.演示案例 - basePackage: com.ruoyi.demo - - name: 2.系统模块 - basePackage: com.ruoyi.web - - name: 3.代码生成模块 - basePackage: com.ruoyi.generator + info: + # 标题 + title: '标题:${ruoyi.name}后台管理系统_接口文档' + # 描述 + description: '描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...' + # 版本 + version: '版本号: ${ruoyi-vue-plus.version}' + # 作者信息 + contact: + name: Lion Li + email: crazylionli@163.com + url: https://gitee.com/JavaLionLi/RuoYi-Vue-Plus + components: + # 鉴权方式配置 + security-schemes: + apiKey: + type: APIKEY + in: HEADER + name: ${sa-token.token-name} -knife4j: - # 是否开启Knife4j增强模式 - enable: true - # 是否开启生产环境保护策略 - production: @knife4j.production@ - basic: - enable: true - username: ruoyi - password: 123456 - # 前端Ui的个性化配置属性 - setting: - # 默认语言 - language: zh-CN - # 是否显示Footer - enableFooter: false - # 是否开启动态参数调试功能 - enableDynamicParameter: true - # 是否在每个Debug调试栏后显示刷新变量按钮 - enableReloadCacheParameter: true +springdoc: + #这里定义了两个分组,可定义多个,也可以不定义 + group-configs: + - group: 1.演示模块 + packages-to-scan: com.ruoyi.demo + - group: 2.系统模块 + packages-to-scan: com.ruoyi.web + - group: 3.代码生成模块 + packages-to-scan: com.ruoyi.generator # 防止XSS攻击 xss: @@ -242,26 +229,11 @@ thread-pool: # 线程池维护线程所允许的空闲时间 keepAliveSeconds: 300 ---- # redisson 缓存配置 -redisson: - cacheGroup: - # 用例: @Cacheable(cacheNames="groupId", key="#XXX") 方可使用缓存组配置 - - groupId: redissonCacheMap - # 组过期时间(脚本监控) - ttl: 60000 - # 组最大空闲时间(脚本监控) - maxIdleTime: 60000 - # 组最大长度 - maxSize: 0 - - groupId: testCache - ttl: 1000 - maxIdleTime: 500 - --- # 分布式锁 lock4j 全局配置 lock4j: # 获取分布式锁超时时间,默认为 3000 毫秒 acquire-timeout: 3000 - # 分布式锁的超时时间,默认为 30 毫秒 + # 分布式锁的超时时间,默认为 30 秒 expire: 30000 --- # Actuator 监控端点的配置项 @@ -269,9 +241,9 @@ management: endpoints: web: exposure: - # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。 - # 生产环境不建议放开所有 根据项目需求放开即可 - include: @endpoints.include@ + include: '*' endpoint: + health: + show-details: ALWAYS logfile: external-file: ./logs/sys-console.log diff --git a/ruoyi-admin/src/main/resources/i18n/messages.properties b/ruoyi-admin/src/main/resources/i18n/messages.properties index ac1d8c230..e1423a8fd 100644 --- a/ruoyi-admin/src/main/resources/i18n/messages.properties +++ b/ruoyi-admin/src/main/resources/i18n/messages.properties @@ -5,7 +5,7 @@ user.jcaptcha.expire=验证码已失效 user.not.exists=对不起, 您的账号:{0} 不存在. user.password.not.match=用户不存在/密码错误 user.password.retry.limit.count=密码输入错误{0}次 -user.password.retry.limit.exceed=密码错误次数过多,帐户锁定{0}分钟 +user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分钟 user.password.delete=对不起,您的账号:{0} 已被删除 user.blocked=对不起,您的账号:{0} 已禁用,请联系管理员 role.blocked=角色已封禁,请联系管理员 @@ -41,5 +41,5 @@ repeat.submit.message=不允许重复提交,请稍候再试 rate.limiter.message=访问过于频繁,请稍候再试 sms.code.not.blank=短信验证码不能为空 sms.code.retry.limit.count=短信验证码输入错误{0}次 -sms.code.retry.limit.exceed=短信验证码错误次数过多,帐户锁定{0}分钟 +sms.code.retry.limit.exceed=短信验证码输入错误{0}次,帐户锁定{0}分钟 xcx.code.not.blank=小程序code不能为空 diff --git a/ruoyi-admin/src/main/resources/i18n/messages_en_US.properties b/ruoyi-admin/src/main/resources/i18n/messages_en_US.properties index 9076f79f7..04a4aa372 100644 --- a/ruoyi-admin/src/main/resources/i18n/messages_en_US.properties +++ b/ruoyi-admin/src/main/resources/i18n/messages_en_US.properties @@ -5,7 +5,7 @@ user.jcaptcha.expire=Captcha invalid user.not.exists=Sorry, your account: {0} does not exist user.password.not.match=User does not exist/Password error user.password.retry.limit.count=Password input error {0} times -user.password.retry.limit.exceed=Too many password errors, account locked for {0} minutes +user.password.retry.limit.exceed=Password input error {0} times, account locked for {1} minutes user.password.delete=Sorry, your account:{0} has been deleted user.blocked=Sorry, your account: {0} has been disabled. Please contact the administrator role.blocked=Role disabled,please contact administrators @@ -41,5 +41,5 @@ repeat.submit.message=Repeat submit is not allowed, please try again later rate.limiter.message=Visit too frequently, please try again later sms.code.not.blank=Sms code cannot be blank sms.code.retry.limit.count=Sms code input error {0} times -sms.code.retry.limit.exceed=Too many sms code errors, account locked for {0} minutes +sms.code.retry.limit.exceed=Sms code input error {0} times, account locked for {0} minutes xcx.code.not.blank=Mini program code cannot be blank diff --git a/ruoyi-admin/src/main/resources/i18n/messages_zh_CN.properties b/ruoyi-admin/src/main/resources/i18n/messages_zh_CN.properties index ac1d8c230..e1423a8fd 100644 --- a/ruoyi-admin/src/main/resources/i18n/messages_zh_CN.properties +++ b/ruoyi-admin/src/main/resources/i18n/messages_zh_CN.properties @@ -5,7 +5,7 @@ user.jcaptcha.expire=验证码已失效 user.not.exists=对不起, 您的账号:{0} 不存在. user.password.not.match=用户不存在/密码错误 user.password.retry.limit.count=密码输入错误{0}次 -user.password.retry.limit.exceed=密码错误次数过多,帐户锁定{0}分钟 +user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分钟 user.password.delete=对不起,您的账号:{0} 已被删除 user.blocked=对不起,您的账号:{0} 已禁用,请联系管理员 role.blocked=角色已封禁,请联系管理员 @@ -41,5 +41,5 @@ repeat.submit.message=不允许重复提交,请稍候再试 rate.limiter.message=访问过于频繁,请稍候再试 sms.code.not.blank=短信验证码不能为空 sms.code.retry.limit.count=短信验证码输入错误{0}次 -sms.code.retry.limit.exceed=短信验证码错误次数过多,帐户锁定{0}分钟 +sms.code.retry.limit.exceed=短信验证码输入错误{0}次,帐户锁定{0}分钟 xcx.code.not.blank=小程序code不能为空 diff --git a/ruoyi-admin/src/main/resources/logback.xml b/ruoyi-admin/src/main/resources/logback.xml index b78044b35..40fa33b7c 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 918f1cb5e..abbd8931d 100644 --- a/ruoyi-admin/src/main/resources/spy.properties +++ b/ruoyi-admin/src/main/resources/spy.properties @@ -14,6 +14,8 @@ useprefix=true excludecategories=info,debug,result,commit,resultset # 日期格式 dateformat=yyyy-MM-dd HH:mm:ss +# SQL语句打印时间格式 +databaseDialectTimestampFormat=yyyy-MM-dd HH:mm:ss # 实际驱动可多个 #driverlist=org.h2.Driver # 是否开启慢SQL记录 @@ -22,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 000000000..5b9c9f84f --- /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 000000000..a40fd8275 --- /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 000000000..04bf1b5cc --- /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 000000000..04240a07f --- /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/pom.xml b/ruoyi-common/pom.xml index 10fec546f..90d29940b 100644 --- a/ruoyi-common/pom.xml +++ b/ruoyi-common/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.2.0 + 4.4.0 4.0.0 @@ -126,13 +126,13 @@ - com.github.xiaoymin - knife4j-spring-boot-starter + org.springdoc + springdoc-openapi-webmvc-core - io.swagger - swagger-annotations + org.springdoc + springdoc-openapi-javadoc 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 fe2810083..000000000 --- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.ruoyi.common.annotation; - -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 - */ -@Target({ElementType.METHOD, ElementType.TYPE}) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface Anonymous { -} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataColumn.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataColumn.java index bd2ddece1..df416edc8 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataColumn.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataColumn.java @@ -5,6 +5,8 @@ import java.lang.annotation.*; /** * 数据权限 * + * 一个注解只能对应一个模板 + * * @author Lion Li * @version 3.5.0 */ @@ -16,11 +18,11 @@ public @interface DataColumn { /** * 占位符关键字 */ - String key() default "deptName"; + String[] key() default "deptName"; /** * 占位符替换值 */ - String value() default "dept_id"; + String[] value() default "dept_id"; } 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 000000000..5c14a5520 --- /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/annotation/RateLimiter.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java index 90db9d776..2e3ff7a82 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java @@ -1,36 +1,36 @@ -package com.ruoyi.common.annotation; - -import com.ruoyi.common.constant.Constants; -import com.ruoyi.common.enums.LimitType; - -import java.lang.annotation.*; - -/** - * 限流注解 - * - * @author Lion Li - */ -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -@Documented -public @interface RateLimiter { - /** - * 限流key - */ - String key() default Constants.RATE_LIMIT_KEY; - - /** - * 限流时间,单位秒 - */ - int time() default 60; - - /** - * 限流次数 - */ - int count() default 100; - - /** - * 限流类型 - */ - LimitType limitType() default LimitType.DEFAULT; -} +package com.ruoyi.common.annotation; + +import com.ruoyi.common.constant.CacheConstants; +import com.ruoyi.common.enums.LimitType; + +import java.lang.annotation.*; + +/** + * 限流注解 + * + * @author Lion Li + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@Documented +public @interface RateLimiter { + /** + * 限流key + */ + String key() default CacheConstants.RATE_LIMIT_KEY; + + /** + * 限流时间,单位秒 + */ + int time() default 60; + + /** + * 限流次数 + */ + int count() default 100; + + /** + * 限流类型 + */ + LimitType limitType() default LimitType.DEFAULT; +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java new file mode 100644 index 000000000..1cdf07eec --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java @@ -0,0 +1,49 @@ +package com.ruoyi.common.constant; + +/** + * 缓存的key 常量 + * + * @author ruoyi + */ +public interface CacheConstants { + + /** + * 登录用户 redis key + */ + String LOGIN_TOKEN_KEY = "Authorization:login:token:"; + + /** + * 在线用户 redis key + */ + String ONLINE_TOKEN_KEY = "online_tokens:"; + + /** + * 验证码 redis key + */ + String CAPTCHA_CODE_KEY = "captcha_codes:"; + + /** + * 参数管理 cache key + */ + String SYS_CONFIG_KEY = "sys_config:"; + + /** + * 字典管理 cache key + */ + String SYS_DICT_KEY = "sys_dict:"; + + /** + * 防重提交 redis key + */ + String REPEAT_SUBMIT_KEY = "repeat_submit:"; + + /** + * 限流 redis key + */ + String RATE_LIMIT_KEY = "rate_limit:"; + + /** + * 登录账户密码错误次数 redis key + */ + String PWD_ERR_CNT_KEY = "pwd_err_cnt:"; +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheNames.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheNames.java new file mode 100644 index 000000000..591ca2546 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheNames.java @@ -0,0 +1,48 @@ +package com.ruoyi.common.constant; + +/** + * 缓存组名称常量 + *

+ * key 格式为 cacheNames#ttl#maxIdleTime#maxSize + *

+ * ttl 过期时间 如果设置为0则不过期 默认为0 + * maxIdleTime 最大空闲时间 根据LRU算法清理空闲数据 如果设置为0则不检测 默认为0 + * maxSize 组最大长度 根据LRU算法清理溢出数据 如果设置为0则无限长 默认为0 + *

+ * 例子: test#60s、test#0#60s、test#0#1m#1000、test#1h#0#500 + * + * @author Lion Li + */ +public interface CacheNames { + + /** + * 演示案例 + */ + String DEMO_CACHE = "demo:cache#60s#10m#20"; + + /** + * 系统配置 + */ + String SYS_CONFIG = "sys_config"; + + /** + * 数据字典 + */ + String SYS_DICT = "sys_dict"; + + /** + * OSS内容 + */ + String SYS_OSS = "sys_oss#30d"; + + /** + * OSS配置 + */ + String SYS_OSS_CONFIG = "sys_oss_config"; + + /** + * 在线用户 + */ + String ONLINE_TOKEN = "online_tokens"; + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java index e2ffebdc0..e634ed297 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java @@ -17,6 +17,11 @@ public interface Constants { */ String GBK = "GBK"; + /** + * www主域 + */ + String WWW = "www."; + /** * http请求 */ @@ -57,70 +62,15 @@ public interface Constants { */ String LOGIN_FAIL = "Error"; - /** - * 验证码 redis key - */ - String CAPTCHA_CODE_KEY = "captcha_codes:"; - - /** - * 登录用户 redis key - */ - String LOGIN_TOKEN_KEY = "Authorization:login:token:"; - - /** - * 在线用户 redis key - */ - String ONLINE_TOKEN_KEY = "online_tokens:"; - - /** - * 防重提交 redis key - */ - String REPEAT_SUBMIT_KEY = "repeat_submit:"; - - /** - * 限流 redis key - */ - String RATE_LIMIT_KEY = "rate_limit:"; - /** * 验证码有效期(分钟) */ Integer CAPTCHA_EXPIRATION = 2; - /** - * 登陆错误 redis key - */ - String LOGIN_ERROR = "login_error:"; - - /** - * 登录错误次数 - */ - Integer LOGIN_ERROR_NUMBER = 5; - - /** - * 登录错误限制时间(分钟) - */ - Integer LOGIN_ERROR_LIMIT_TIME = 10; - /** * 令牌 */ String TOKEN = "token"; - /** - * 令牌前缀 - */ - String LOGIN_USER_KEY = "login_user_key"; - - /** - * 参数管理 cache key - */ - String SYS_CONFIG_KEY = "sys_config:"; - - /** - * 字典管理 cache key - */ - String SYS_DICT_KEY = "sys_dict:"; - } 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 000000000..f007b8c83 --- /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 d1ad296f6..bd316079a 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,7 +2,8 @@ package com.ruoyi.common.core.domain; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.TableField; -import io.swagger.annotations.ApiModelProperty; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; import lombok.Data; import java.io.Serializable; @@ -24,42 +25,38 @@ public class BaseEntity implements Serializable { /** * 搜索值 */ - @ApiModelProperty(value = "搜索值") + @JsonIgnore @TableField(exist = false) private String searchValue; /** * 创建者 */ - @ApiModelProperty(value = "创建者") @TableField(fill = FieldFill.INSERT) private String createBy; /** * 创建时间 */ - @ApiModelProperty(value = "创建时间") @TableField(fill = FieldFill.INSERT) private Date createTime; /** * 更新者 */ - @ApiModelProperty(value = "更新者") @TableField(fill = FieldFill.INSERT_UPDATE) private String updateBy; /** * 更新时间 */ - @ApiModelProperty(value = "更新时间") @TableField(fill = FieldFill.INSERT_UPDATE) private Date updateTime; /** * 请求参数 */ - @ApiModelProperty(value = "请求参数") + @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/PageQuery.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/PageQuery.java index 7a61237c9..60abde623 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/PageQuery.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/PageQuery.java @@ -1,14 +1,17 @@ package com.ruoyi.common.core.domain; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.metadata.OrderItem; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.sql.SqlUtil; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; /** * 分页查询实体类 @@ -24,25 +27,21 @@ public class PageQuery implements Serializable { /** * 分页大小 */ - @ApiModelProperty("分页大小") private Integer pageSize; /** * 当前页数 */ - @ApiModelProperty("当前页数") private Integer pageNum; /** * 排序列 */ - @ApiModelProperty("排序列") private String orderByColumn; /** * 排序的方向desc或者asc */ - @ApiModelProperty(value = "排序的方向", example = "asc,desc") private String isAsc; /** @@ -62,30 +61,52 @@ public class PageQuery implements Serializable { pageNum = DEFAULT_PAGE_NUM; } Page page = new Page<>(pageNum, pageSize); - OrderItem orderItem = buildOrderItem(); - if (ObjectUtil.isNotNull(orderItem)) { - page.addOrder(orderItem); + List orderItems = buildOrderItem(); + if (CollUtil.isNotEmpty(orderItems)) { + page.addOrder(orderItems); } return page; } - private OrderItem buildOrderItem() { - // 兼容前端排序类型 - if ("ascending".equals(isAsc)) { - isAsc = "asc"; - } else if ("descending".equals(isAsc)) { - isAsc = "desc"; + /** + * 构建排序 + * + * 支持的用法如下: + * {isAsc:"asc",orderByColumn:"id"} order by id asc + * {isAsc:"asc",orderByColumn:"id,createTime"} order by id asc,create_time asc + * {isAsc:"desc",orderByColumn:"id,createTime"} order by id desc,create_time desc + * {isAsc:"asc,desc",orderByColumn:"id,createTime"} order by id asc,create_time desc + */ + private List buildOrderItem() { + if (StringUtils.isBlank(orderByColumn) || StringUtils.isBlank(isAsc)) { + return null; } - if (StringUtils.isNotBlank(orderByColumn)) { - String orderBy = SqlUtil.escapeOrderBySql(orderByColumn); - orderBy = StringUtils.toUnderScoreCase(orderBy); - if ("asc".equals(isAsc)) { - return OrderItem.asc(orderBy); - } else if ("desc".equals(isAsc)) { - return OrderItem.desc(orderBy); + String orderBy = SqlUtil.escapeOrderBySql(orderByColumn); + orderBy = StringUtils.toUnderScoreCase(orderBy); + + // 兼容前端排序类型 + isAsc = StringUtils.replaceEach(isAsc, new String[]{"ascending", "descending"}, new String[]{"asc", "desc"}); + + String[] orderByArr = orderBy.split(","); + String[] isAscArr = isAsc.split(","); + if (isAscArr.length != 1 && isAscArr.length != orderByArr.length) { + throw new ServiceException("排序参数有误"); + } + + List list = new ArrayList<>(); + // 每个字段各自排序 + for (int i = 0; i < orderByArr.length; i++) { + String orderByStr = orderByArr[i]; + String isAscStr = isAscArr.length == 1 ? isAscArr[0] : isAscArr[i]; + if ("asc".equals(isAscStr)) { + list.add(OrderItem.asc(orderByStr)); + } else if ("desc".equals(isAscStr)) { + list.add(OrderItem.desc(orderByStr)); + } else { + throw new ServiceException("排序参数有误"); } } - return null; + return list; } } 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 7a2420238..381a6f602 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,7 +1,6 @@ package com.ruoyi.common.core.domain; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; +import com.ruoyi.common.constant.HttpStatus; import lombok.Data; import lombok.NoArgsConstructor; @@ -14,7 +13,6 @@ import java.io.Serializable; */ @Data @NoArgsConstructor -@ApiModel("请求响应对象") public class R implements Serializable { private static final long serialVersionUID = 1L; @@ -28,13 +26,10 @@ public class R implements Serializable { */ public static final int FAIL = 500; - @ApiModelProperty("消息状态码") private int code; - @ApiModelProperty("消息内容") private String msg; - @ApiModelProperty("数据对象") private T data; public static R ok() { @@ -73,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); @@ -81,4 +97,11 @@ public class R implements Serializable { return r; } + public static Boolean isError(R ret) { + return !isSuccess(ret); + } + + public static Boolean isSuccess(R ret) { + return R.SUCCESS == ret.getCode(); + } } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java index f44eacd49..c7bb9b4ff 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java @@ -1,7 +1,6 @@ package com.ruoyi.common.core.domain; import com.baomidou.mybatisplus.annotation.TableField; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; @@ -24,20 +23,17 @@ public class TreeEntity extends BaseEntity { * 父菜单名称 */ @TableField(exist = false) - @ApiModelProperty(value = "父菜单名称") private String parentName; /** * 父菜单ID */ - @ApiModelProperty(value = "父菜单ID") private Long parentId; /** * 子部门 */ @TableField(exist = false) - @ApiModelProperty(value = "子部门") private List children = new ArrayList<>(); } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java index 2dc3bdc40..857f9b8db 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java @@ -4,8 +4,6 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableName; import com.ruoyi.common.core.domain.TreeEntity; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; @@ -23,21 +21,18 @@ import javax.validation.constraints.Size; @Data @EqualsAndHashCode(callSuper = true) @TableName("sys_dept") -@ApiModel("部门业务对象") public class SysDept extends TreeEntity { private static final long serialVersionUID = 1L; /** * 部门ID */ - @ApiModelProperty(value = "部门id") @TableId(value = "dept_id") private Long deptId; /** * 部门名称 */ - @ApiModelProperty(value = "部门名称") @NotBlank(message = "部门名称不能为空") @Size(min = 0, max = 30, message = "部门名称长度不能超过30个字符") private String deptName; @@ -45,27 +40,23 @@ public class SysDept extends TreeEntity { /** * 显示顺序 */ - @ApiModelProperty(value = "显示顺序") @NotNull(message = "显示顺序不能为空") private Integer orderNum; /** * 负责人 */ - @ApiModelProperty(value = "负责人") private String leader; /** * 联系电话 */ - @ApiModelProperty(value = "联系电话") @Size(min = 0, max = 11, message = "联系电话长度不能超过11个字符") private String phone; /** * 邮箱 */ - @ApiModelProperty(value = "邮箱") @Email(message = "邮箱格式不正确") @Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符") private String email; @@ -73,20 +64,17 @@ public class SysDept extends TreeEntity { /** * 部门状态:0正常,1停用 */ - @ApiModelProperty(value = "部门状态:0正常,1停用") private String status; /** * 删除标志(0代表存在 2代表删除) */ - @ApiModelProperty(value = "删除标志(0代表存在 2代表删除)") @TableLogic private String delFlag; /** * 祖级列表 */ - @ApiModelProperty(value = "祖级列表") private String ancestors; } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java index c61c91726..e20f96aa7 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java @@ -8,8 +8,6 @@ import com.ruoyi.common.annotation.ExcelDictFormat; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.convert.ExcelDictConvert; import com.ruoyi.common.core.domain.BaseEntity; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; @@ -26,13 +24,11 @@ import javax.validation.constraints.Size; @EqualsAndHashCode(callSuper = true) @TableName("sys_dict_data") @ExcelIgnoreUnannotated -@ApiModel("字典数据业务对象") public class SysDictData extends BaseEntity { /** * 字典编码 */ - @ApiModelProperty(value = "字典编码") @ExcelProperty(value = "字典编码") @TableId(value = "dict_code") private Long dictCode; @@ -40,14 +36,12 @@ public class SysDictData extends BaseEntity { /** * 字典排序 */ - @ApiModelProperty(value = "字典排序") @ExcelProperty(value = "字典排序") private Integer dictSort; /** * 字典标签 */ - @ApiModelProperty(value = "字典标签") @ExcelProperty(value = "字典标签") @NotBlank(message = "字典标签不能为空") @Size(min = 0, max = 100, message = "字典标签长度不能超过100个字符") @@ -56,7 +50,6 @@ public class SysDictData extends BaseEntity { /** * 字典键值 */ - @ApiModelProperty(value = "字典键值") @ExcelProperty(value = "字典键值") @NotBlank(message = "字典键值不能为空") @Size(min = 0, max = 100, message = "字典键值长度不能超过100个字符") @@ -65,7 +58,6 @@ public class SysDictData extends BaseEntity { /** * 字典类型 */ - @ApiModelProperty(value = "字典类型") @ExcelProperty(value = "字典类型") @NotBlank(message = "字典类型不能为空") @Size(min = 0, max = 100, message = "字典类型长度不能超过100个字符") @@ -74,20 +66,17 @@ public class SysDictData extends BaseEntity { /** * 样式属性(其他样式扩展) */ - @ApiModelProperty(value = "样式属性(其他样式扩展)") @Size(min = 0, max = 100, message = "样式属性长度不能超过100个字符") private String cssClass; /** * 表格字典样式 */ - @ApiModelProperty(value = "表格字典样式") private String listClass; /** * 是否默认(Y是 N否) */ - @ApiModelProperty(value = "是否默认(Y是 N否)") @ExcelProperty(value = "是否默认", converter = ExcelDictConvert.class) @ExcelDictFormat(dictType = "sys_yes_no") private String isDefault; @@ -95,7 +84,6 @@ public class SysDictData extends BaseEntity { /** * 状态(0正常 1停用) */ - @ApiModelProperty(value = "状态(0正常 1停用)") @ExcelProperty(value = "状态", converter = ExcelDictConvert.class) @ExcelDictFormat(dictType = "sys_normal_disable") private String status; @@ -103,7 +91,6 @@ public class SysDictData extends BaseEntity { /** * 备注 */ - @ApiModelProperty(value = "备注") private String remark; public boolean getDefault() { diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java index 942c2f97b..36e38a971 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java @@ -7,11 +7,8 @@ import com.baomidou.mybatisplus.annotation.TableName; import com.ruoyi.common.annotation.ExcelDictFormat; import com.ruoyi.common.convert.ExcelDictConvert; import com.ruoyi.common.core.domain.BaseEntity; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; -import lombok.experimental.Accessors; import javax.validation.constraints.NotBlank; import javax.validation.constraints.Pattern; @@ -27,13 +24,11 @@ import javax.validation.constraints.Size; @EqualsAndHashCode(callSuper = true) @TableName("sys_dict_type") @ExcelIgnoreUnannotated -@ApiModel("字典类型业务对象") public class SysDictType extends BaseEntity { /** * 字典主键 */ - @ApiModelProperty(value = "字典主键") @ExcelProperty(value = "字典主键") @TableId(value = "dict_id") private Long dictId; @@ -41,7 +36,6 @@ public class SysDictType extends BaseEntity { /** * 字典名称 */ - @ApiModelProperty(value = "字典名称") @ExcelProperty(value = "字典名称") @NotBlank(message = "字典名称不能为空") @Size(min = 0, max = 100, message = "字典类型名称长度不能超过100个字符") @@ -50,7 +44,6 @@ public class SysDictType extends BaseEntity { /** * 字典类型 */ - @ApiModelProperty(value = "字典类型") @ExcelProperty(value = "字典类型") @NotBlank(message = "字典类型不能为空") @Size(min = 0, max = 100, message = "字典类型类型长度不能超过100个字符") @@ -60,7 +53,6 @@ public class SysDictType extends BaseEntity { /** * 状态(0正常 1停用) */ - @ApiModelProperty(value = "状态(0正常 1停用)") @ExcelProperty(value = "状态", converter = ExcelDictConvert.class) @ExcelDictFormat(dictType = "sys_normal_disable") private String status; @@ -68,7 +60,6 @@ public class SysDictType extends BaseEntity { /** * 备注 */ - @ApiModelProperty(value = "备注") private String remark; } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java index cf337fbeb..201605f96 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java @@ -4,8 +4,6 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonInclude; import com.ruoyi.common.core.domain.TreeEntity; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; @@ -22,20 +20,17 @@ import javax.validation.constraints.Size; @Data @EqualsAndHashCode(callSuper = true) @TableName("sys_menu") -@ApiModel("菜单权限业务对象") public class SysMenu extends TreeEntity { /** * 菜单ID */ - @ApiModelProperty(value = "菜单ID") @TableId(value = "menu_id") private Long menuId; /** * 菜单名称 */ - @ApiModelProperty(value = "菜单名称") @NotBlank(message = "菜单名称不能为空") @Size(min = 0, max = 50, message = "菜单名称长度不能超过50个字符") private String menuName; @@ -43,65 +38,55 @@ public class SysMenu extends TreeEntity { /** * 显示顺序 */ - @ApiModelProperty(value = "显示顺序") @NotNull(message = "显示顺序不能为空") private Integer orderNum; /** * 路由地址 */ - @ApiModelProperty(value = "路由地址") @Size(min = 0, max = 200, message = "路由地址不能超过200个字符") private String path; /** * 组件路径 */ - @ApiModelProperty(value = "组件路径") @Size(min = 0, max = 200, message = "组件路径不能超过255个字符") private String component; /** * 路由参数 */ - @ApiModelProperty(value = "路由参数") private String queryParam; /** * 是否为外链(0是 1否) */ - @ApiModelProperty(value = "是否为外链(0是 1否)") private String isFrame; /** * 是否缓存(0缓存 1不缓存) */ - @ApiModelProperty(value = "是否缓存(0缓存 1不缓存)") private String isCache; /** * 类型(M目录 C菜单 F按钮) */ - @ApiModelProperty(value = "类型(M目录 C菜单 F按钮)") @NotBlank(message = "菜单类型不能为空") private String menuType; /** * 显示状态(0显示 1隐藏) */ - @ApiModelProperty(value = "显示状态(0显示 1隐藏)") private String visible; /** - * 菜单状态(0显示 1隐藏) + * 菜单状态(0正常 1停用) */ - @ApiModelProperty(value = "菜单状态(0显示 1隐藏)") private String status; /** * 权限字符串 */ - @ApiModelProperty(value = "权限字符串") @JsonInclude(JsonInclude.Include.NON_NULL) @Size(min = 0, max = 100, message = "权限标识长度不能超过100个字符") private String perms; @@ -109,13 +94,11 @@ public class SysMenu extends TreeEntity { /** * 菜单图标 */ - @ApiModelProperty(value = "菜单图标") private String icon; /** * 备注 */ - @ApiModelProperty(value = "备注") private String remark; } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java index 804815738..52682894a 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java @@ -10,7 +10,6 @@ import com.ruoyi.common.annotation.ExcelDictFormat; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.convert.ExcelDictConvert; import com.ruoyi.common.core.domain.BaseEntity; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; @@ -18,6 +17,7 @@ import lombok.NoArgsConstructor; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import javax.validation.constraints.Size; +import java.util.Set; /** * 角色表 sys_role @@ -35,7 +35,6 @@ public class SysRole extends BaseEntity { /** * 角色ID */ - @ApiModelProperty(value = "角色ID") @ExcelProperty(value = "角色序号") @TableId(value = "role_id") private Long roleId; @@ -43,7 +42,6 @@ public class SysRole extends BaseEntity { /** * 角色名称 */ - @ApiModelProperty(value = "角色名称") @ExcelProperty(value = "角色名称") @NotBlank(message = "角色名称不能为空") @Size(min = 0, max = 30, message = "角色名称长度不能超过30个字符") @@ -52,7 +50,6 @@ public class SysRole extends BaseEntity { /** * 角色权限 */ - @ApiModelProperty(value = "角色权限") @ExcelProperty(value = "角色权限") @NotBlank(message = "权限字符不能为空") @Size(min = 0, max = 100, message = "权限字符长度不能超过100个字符") @@ -61,7 +58,6 @@ public class SysRole extends BaseEntity { /** * 角色排序 */ - @ApiModelProperty(value = "角色排序") @ExcelProperty(value = "角色排序") @NotNull(message = "显示顺序不能为空") private Integer roleSort; @@ -69,7 +65,6 @@ public class SysRole extends BaseEntity { /** * 数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限) */ - @ApiModelProperty(value = "数据范围(1:所有数据权限;2:自定义数据权限;3:本部门数据权限;4:本部门及以下数据权限;5:仅本人数据权限)") @ExcelProperty(value = "数据范围", converter = ExcelDictConvert.class) @ExcelDictFormat(readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限,5=仅本人数据权限") private String dataScope; @@ -77,62 +72,59 @@ public class SysRole extends BaseEntity { /** * 菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示) */ - @ApiModelProperty(value = "菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示)") private Boolean menuCheckStrictly; /** * 部门树选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示 ) */ - @ApiModelProperty(value = "部门树选择项是否关联显示(0:父子不互相关联显示 1:父子互相关联显示 )") private Boolean deptCheckStrictly; /** * 角色状态(0正常 1停用) */ - @ApiModelProperty(value = "角色状态(0正常 1停用)") @ExcelProperty(value = "角色状态", converter = ExcelDictConvert.class) - @ExcelDictFormat(dictType = "sys_common_status") + @ExcelDictFormat(dictType = "sys_normal_disable") private String status; /** * 删除标志(0代表存在 2代表删除) */ - @ApiModelProperty(value = "删除标志(0代表存在 2代表删除)") @TableLogic private String delFlag; /** * 备注 */ - @ApiModelProperty(value = "备注") private String remark; /** * 用户是否存在此角色标识 默认不存在 */ - @ApiModelProperty(value = "用户是否存在此角色标识 默认不存在") @TableField(exist = false) private boolean flag = false; /** * 菜单组 */ - @ApiModelProperty(value = "菜单组") @TableField(exist = false) private Long[] menuIds; /** * 部门组(数据权限) */ - @ApiModelProperty(value = "部门组(数据权限)") @TableField(exist = false) private Long[] deptIds; + /** + * 角色菜单权限 + */ + @TableField(exist = false) + private Set permissions; + public SysRole(Long roleId) { this.roleId = roleId; } - @ApiModelProperty(value = "是否管理员") public boolean isAdmin() { return UserConstants.ADMIN_ID.equals(this.roleId); } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java index 9aa75f7a4..f2d961b7a 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java @@ -1,15 +1,11 @@ package com.ruoyi.common.core.domain.entity; import com.baomidou.mybatisplus.annotation.*; -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; import com.ruoyi.common.annotation.Sensitive; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.domain.BaseEntity; import com.ruoyi.common.enums.SensitiveStrategy; import com.ruoyi.common.xss.Xss; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; @@ -30,26 +26,22 @@ import java.util.List; @NoArgsConstructor @EqualsAndHashCode(callSuper = true) @TableName("sys_user") -@ApiModel("用户信息业务对象") public class SysUser extends BaseEntity { /** * 用户ID */ - @ApiModelProperty(value = "用户ID") @TableId(value = "user_id") private Long userId; /** * 部门ID */ - @ApiModelProperty(value = "部门ID") private Long deptId; /** * 用户账号 */ - @ApiModelProperty(value = "用户账号") @Xss(message = "用户账号不能包含脚本字符") @NotBlank(message = "用户账号不能为空") @Size(min = 0, max = 30, message = "用户账号长度不能超过30个字符") @@ -58,7 +50,6 @@ public class SysUser extends BaseEntity { /** * 用户昵称 */ - @ApiModelProperty(value = "用户昵称") @Xss(message = "用户昵称不能包含脚本字符") @Size(min = 0, max = 30, message = "用户昵称长度不能超过30个字符") private String nickName; @@ -66,14 +57,12 @@ public class SysUser extends BaseEntity { /** * 用户类型(sys_user系统用户) */ - @ApiModelProperty(value = "用户类型") private String userType; /** * 用户邮箱 */ @Sensitive(strategy = SensitiveStrategy.EMAIL) - @ApiModelProperty(value = "用户邮箱") @Email(message = "邮箱格式不正确") @Size(min = 0, max = 50, message = "邮箱长度不能超过50个字符") private String email; @@ -82,25 +71,21 @@ public class SysUser extends BaseEntity { * 手机号码 */ @Sensitive(strategy = SensitiveStrategy.PHONE) - @ApiModelProperty(value = "手机号码") private String phonenumber; /** * 用户性别 */ - @ApiModelProperty(value = "用户性别") private String sex; /** * 用户头像 */ - @ApiModelProperty(value = "用户头像") private String avatar; /** * 密码 */ - @ApiModelProperty(value = "密码") @TableField( insertStrategy = FieldStrategy.NOT_EMPTY, updateStrategy = FieldStrategy.NOT_EMPTY, @@ -111,66 +96,56 @@ public class SysUser extends BaseEntity { /** * 帐号状态(0正常 1停用) */ - @ApiModelProperty(value = "帐号状态(0正常 1停用)") private String status; /** * 删除标志(0代表存在 2代表删除) */ - @ApiModelProperty(value = "删除标志(0代表存在 2代表删除)") @TableLogic private String delFlag; /** * 最后登录IP */ - @ApiModelProperty(value = "最后登录IP") private String loginIp; /** * 最后登录时间 */ - @ApiModelProperty(value = "最后登录时间") private Date loginDate; /** * 备注 */ - @ApiModelProperty(value = "备注") private String remark; /** * 部门对象 */ - @ApiModelProperty(value = "部门对象") @TableField(exist = false) private SysDept dept; /** * 角色对象 */ - @ApiModelProperty(value = "角色对象") @TableField(exist = false) private List roles; /** * 角色组 */ - @ApiModelProperty(value = "角色组") @TableField(exist = false) private Long[] roleIds; /** * 岗位组 */ - @ApiModelProperty(value = "岗位组") @TableField(exist = false) private Long[] postIds; /** * 数据权限 当前角色ID */ - @ApiModelProperty(value = "角色ID") @TableField(exist = false) private Long roleId; @@ -178,7 +153,6 @@ public class SysUser extends BaseEntity { this.userId = userId; } - @ApiModelProperty(value = "是否管理员") public boolean isAdmin() { return UserConstants.ADMIN_ID.equals(this.userId); } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java index f13de9711..4a4cfb518 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java @@ -1,8 +1,6 @@ package com.ruoyi.common.core.domain.model; import com.ruoyi.common.constant.UserConstants; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import org.hibernate.validator.constraints.Length; @@ -15,7 +13,6 @@ import javax.validation.constraints.NotBlank; */ @Data -@ApiModel("用户登录对象") public class LoginBody { /** @@ -23,7 +20,6 @@ public class LoginBody { */ @NotBlank(message = "{user.username.not.blank}") @Length(min = UserConstants.USERNAME_MIN_LENGTH, max = UserConstants.USERNAME_MAX_LENGTH, message = "{user.username.length.valid}") - @ApiModelProperty(value = "用户名") private String username; /** @@ -31,19 +27,16 @@ public class LoginBody { */ @NotBlank(message = "{user.password.not.blank}") @Length(min = UserConstants.PASSWORD_MIN_LENGTH, max = UserConstants.PASSWORD_MAX_LENGTH, message = "{user.password.length.valid}") - @ApiModelProperty(value = "用户密码") private String password; /** * 验证码 */ - @ApiModelProperty(value = "验证码") private String code; /** * 唯一标识 */ - @ApiModelProperty(value = "唯一标识") private String uuid; } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java index 9f7186c48..c93b9efe1 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java @@ -105,6 +105,12 @@ public class LoginUser implements Serializable { * 获取登录id */ public String getLoginId() { + if (userType == null) { + throw new IllegalArgumentException("用户类型不能为空"); + } + if (userId == null) { + throw new IllegalArgumentException("用户ID不能为空"); + } return userType + LoginHelper.JOIN_CODE + userId; } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java index bd9b84cca..88367e7b0 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java @@ -1,7 +1,5 @@ package com.ruoyi.common.core.domain.model; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; @@ -12,10 +10,8 @@ import lombok.EqualsAndHashCode; */ @Data @EqualsAndHashCode(callSuper = true) -@ApiModel("用户注册对象") public class RegisterBody extends LoginBody { - @ApiModelProperty(value = "用户类型") private String userType; } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/SmsLoginBody.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/SmsLoginBody.java index f3ef445c5..ce774ac7e 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/SmsLoginBody.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/SmsLoginBody.java @@ -1,7 +1,5 @@ package com.ruoyi.common.core.domain.model; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotBlank; @@ -13,21 +11,18 @@ import javax.validation.constraints.NotBlank; */ @Data -@ApiModel("短信登录对象") public class SmsLoginBody { /** * 用户名 */ @NotBlank(message = "{user.phonenumber.not.blank}") - @ApiModelProperty(value = "用户手机号") private String phonenumber; /** * 用户密码 */ @NotBlank(message = "{sms.code.not.blank}") - @ApiModelProperty(value = "短信验证码") private String smsCode; } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/mapper/BaseMapperPlus.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/mapper/BaseMapperPlus.java index 1ff35792f..862887d16 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/mapper/BaseMapperPlus.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/mapper/BaseMapperPlus.java @@ -149,7 +149,7 @@ public interface BaseMapperPlus extends BaseMapper { return BeanCopyUtils.copy(obj, voClass); } - default List selectVoById(Collection idList) { + default List selectVoBatchIds(Collection idList) { return selectVoBatchIds(idList, this.currentVoClass()); } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java index 48353e3e7..5f3f2d1ad 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java @@ -2,11 +2,8 @@ package com.ruoyi.common.core.page; import cn.hutool.http.HttpStatus; import com.baomidou.mybatisplus.core.metadata.IPage; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.NoArgsConstructor; -import lombok.experimental.Accessors; import java.io.Serializable; import java.util.List; @@ -19,32 +16,27 @@ import java.util.List; @Data @NoArgsConstructor -@ApiModel("分页响应对象") public class TableDataInfo implements Serializable { private static final long serialVersionUID = 1L; /** * 总记录数 */ - @ApiModelProperty("总记录数") private long total; /** * 列表数据 */ - @ApiModelProperty("列表数据") private List rows; /** * 消息状态码 */ - @ApiModelProperty("消息状态码") private int code; /** * 消息内容 */ - @ApiModelProperty("消息内容") private String msg; /** diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/excel/DefaultExcelListener.java b/ruoyi-common/src/main/java/com/ruoyi/common/excel/DefaultExcelListener.java index 9936f6762..6cd6d2816 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/excel/DefaultExcelListener.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/excel/DefaultExcelListener.java @@ -6,6 +6,7 @@ import com.alibaba.excel.event.AnalysisEventListener; import com.alibaba.excel.exception.ExcelAnalysisException; import com.alibaba.excel.exception.ExcelDataConvertException; import com.ruoyi.common.utils.JsonUtils; +import com.ruoyi.common.utils.StreamUtils; import com.ruoyi.common.utils.ValidatorUtils; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -14,7 +15,6 @@ import javax.validation.ConstraintViolation; import javax.validation.ConstraintViolationException; import java.util.Map; import java.util.Set; -import java.util.stream.Collectors; /** * Excel 导入监听 @@ -69,9 +69,7 @@ public class DefaultExcelListener extends AnalysisEventListener implements if (exception instanceof ConstraintViolationException) { ConstraintViolationException constraintViolationException = (ConstraintViolationException) exception; Set> constraintViolations = constraintViolationException.getConstraintViolations(); - String constraintViolationsMsg = constraintViolations.stream() - .map(ConstraintViolation::getMessage) - .collect(Collectors.joining(", ")); + String constraintViolationsMsg = StreamUtils.join(constraintViolations, ConstraintViolation::getMessage, ", "); errMsg = StrUtil.format("第{}行数据校验异常: {}", context.readRowHolder().getRowIndex() + 1, constraintViolationsMsg); if (log.isDebugEnabled()) { log.error(errMsg); diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java index 5584cbce3..080785c9f 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java @@ -1,52 +1,52 @@ -package com.ruoyi.common.exception; - -/** - * 全局异常 - * - * @author ruoyi - */ -public class GlobalException extends RuntimeException { - - private static final long serialVersionUID = 1L; - - /** - * 错误提示 - */ - private String message; - - /** - * 错误明细,内部调试错误 - *

- * 和 {@link CommonResult#getDetailMessage()} 一致的设计 - */ - private String detailMessage; - - /** - * 空构造方法,避免反序列化问题 - */ - public GlobalException() { - } - - public GlobalException(String message) { - this.message = message; - } - - public String getDetailMessage() { - return detailMessage; - } - - public GlobalException setDetailMessage(String detailMessage) { - this.detailMessage = detailMessage; - return this; - } - - @Override - public String getMessage() { - return message; - } - - public GlobalException setMessage(String message) { - this.message = message; - return this; - } -} \ No newline at end of file +package com.ruoyi.common.exception; + +/** + * 全局异常 + * + * @author ruoyi + */ +public class GlobalException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + /** + * 错误提示 + */ + private String message; + + /** + * 错误明细,内部调试错误 + *

+ * 和 {@link CommonResult#getDetailMessage()} 一致的设计 + */ + private String detailMessage; + + /** + * 空构造方法,避免反序列化问题 + */ + public GlobalException() { + } + + public GlobalException(String message) { + this.message = message; + } + + public String getDetailMessage() { + return detailMessage; + } + + public GlobalException setDetailMessage(String detailMessage) { + this.detailMessage = detailMessage; + return this; + } + + @Override + public String getMessage() { + return message; + } + + public GlobalException setMessage(String message) { + this.message = message; + return this; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java index 95ce6d84c..53f41b3b9 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java @@ -1,65 +1,65 @@ -package com.ruoyi.common.exception; - -/** - * 业务异常 - * - * @author ruoyi - */ -public final class ServiceException extends RuntimeException { - private static final long serialVersionUID = 1L; - - /** - * 错误码 - */ - private Integer code; - - /** - * 错误提示 - */ - private String message; - - /** - * 错误明细,内部调试错误 - *

- * 和 {@link CommonResult#getDetailMessage()} 一致的设计 - */ - private String detailMessage; - - /** - * 空构造方法,避免反序列化问题 - */ - public ServiceException() { - } - - public ServiceException(String message) { - this.message = message; - } - - public ServiceException(String message, Integer code) { - this.message = message; - this.code = code; - } - - public String getDetailMessage() { - return detailMessage; - } - - @Override - public String getMessage() { - return message; - } - - public Integer getCode() { - return code; - } - - public ServiceException setMessage(String message) { - this.message = message; - return this; - } - - public ServiceException setDetailMessage(String detailMessage) { - this.detailMessage = detailMessage; - return this; - } -} \ No newline at end of file +package com.ruoyi.common.exception; + +/** + * 业务异常 + * + * @author ruoyi + */ +public final class ServiceException extends RuntimeException { + private static final long serialVersionUID = 1L; + + /** + * 错误码 + */ + private Integer code; + + /** + * 错误提示 + */ + private String message; + + /** + * 错误明细,内部调试错误 + *

+ * 和 {@link CommonResult#getDetailMessage()} 一致的设计 + */ + private String detailMessage; + + /** + * 空构造方法,避免反序列化问题 + */ + public ServiceException() { + } + + public ServiceException(String message) { + this.message = message; + } + + public ServiceException(String message, Integer code) { + this.message = message; + this.code = code; + } + + public String getDetailMessage() { + return detailMessage; + } + + @Override + public String getMessage() { + return message; + } + + public Integer getCode() { + return code; + } + + public ServiceException setMessage(String message) { + this.message = message; + return this; + } + + public ServiceException setDetailMessage(String detailMessage) { + this.detailMessage = detailMessage; + return this; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java new file mode 100644 index 000000000..3d2b640e0 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java @@ -0,0 +1,16 @@ +package com.ruoyi.common.exception.user; + +/** + * 用户错误最大次数异常类 + * + * @author ruoyi + */ +public class UserPasswordRetryLimitExceedException extends UserException { + + private static final long serialVersionUID = 1L; + + public UserPasswordRetryLimitExceedException(int retryLimitCount, int lockTime) { + super("user.password.retry.limit.exceed", retryLimitCount, lockTime); + } + +} 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 b6fd0b65a..c1cbe3f2f 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 @@ -1,6 +1,7 @@ package com.ruoyi.common.filter; import cn.hutool.core.io.IoUtil; +import com.ruoyi.common.constant.Constants; import javax.servlet.ReadListener; import javax.servlet.ServletInputStream; @@ -11,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 @@ -23,10 +23,10 @@ public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper { public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException { super(request); - request.setCharacterEncoding("UTF-8"); - response.setCharacterEncoding("UTF-8"); + 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/XssFilter.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java index 72a8f2740..5a0879472 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java @@ -1,5 +1,6 @@ package com.ruoyi.common.filter; +import com.ruoyi.common.enums.HttpMethod; import com.ruoyi.common.utils.StringUtils; import javax.servlet.*; @@ -48,7 +49,7 @@ public class XssFilter implements Filter { String url = request.getServletPath(); String method = request.getMethod(); // GET DELETE 不过滤 - if (method == null || method.matches("GET") || method.matches("DELETE")) { + if (method == null || HttpMethod.GET.matches(method) || HttpMethod.DELETE.matches(method)) { return true; } return StringUtils.matches(url, excludes); 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 a8ffd66cc..3646f1fee 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,11 +89,9 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper { /** * 是否是Json请求 - * - * @param request */ public boolean isJsonRequest() { String header = super.getHeader(HttpHeaders.CONTENT_TYPE); return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE); } -} \ No newline at end of file +} 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 09e1dc757..1cef0278b 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 000000000..caa059b92 --- /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/jackson/SensitiveJsonSerializer.java b/ruoyi-common/src/main/java/com/ruoyi/common/jackson/SensitiveJsonSerializer.java index 404f393fe..41e578163 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/jackson/SensitiveJsonSerializer.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/jackson/SensitiveJsonSerializer.java @@ -1,5 +1,6 @@ package com.ruoyi.common.jackson; +import cn.hutool.core.util.ObjectUtil; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.BeanProperty; import com.fasterxml.jackson.databind.JsonMappingException; @@ -10,6 +11,8 @@ import com.ruoyi.common.annotation.Sensitive; import com.ruoyi.common.core.service.SensitiveService; import com.ruoyi.common.enums.SensitiveStrategy; 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; @@ -19,19 +22,24 @@ import java.util.Objects; * * @author Yjoioooo */ +@Slf4j public class SensitiveJsonSerializer extends JsonSerializer implements ContextualSerializer { private SensitiveStrategy strategy; @Override public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException { - SensitiveService sensitiveService = SpringUtils.getBean(SensitiveService.class); - if (sensitiveService.isSensitive()) { - gen.writeString(strategy.desensitizer().apply(value)); - } else { + try { + SensitiveService sensitiveService = SpringUtils.getBean(SensitiveService.class); + if (ObjectUtil.isNotNull(sensitiveService) && sensitiveService.isSensitive()) { + gen.writeString(strategy.desensitizer().apply(value)); + } else { + gen.writeString(value); + } + } catch (BeansException e) { + log.error("脱敏实现不存在, 采用默认处理 => {}", e.getMessage()); gen.writeString(value); } - } @Override diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/BeanCopyUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/BeanCopyUtils.java index 93906046d..88161daac 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/BeanCopyUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/BeanCopyUtils.java @@ -14,7 +14,6 @@ import org.springframework.cglib.core.Converter; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; /** * bean深拷贝工具(基于 cglib 性能优异) @@ -79,11 +78,11 @@ public class BeanCopyUtils { if (CollUtil.isEmpty(sourceList)) { return CollUtil.newArrayList(); } - return sourceList.stream().map(source -> { + return StreamUtils.toList(sourceList, source -> { V target = ReflectUtil.newInstanceIfPossible(desc); copy(source, target); return target; - }).collect(Collectors.toList()); + }); } /** diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/JsonUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/JsonUtils.java index 446bf1b00..e5c471e55 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/JsonUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/JsonUtils.java @@ -6,6 +6,7 @@ import cn.hutool.core.util.ObjectUtil; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.exc.MismatchedInputException; import com.ruoyi.common.utils.spring.SpringUtils; import lombok.AccessLevel; import lombok.NoArgsConstructor; @@ -78,6 +79,9 @@ public class JsonUtils { } try { return OBJECT_MAPPER.readValue(text, OBJECT_MAPPER.getTypeFactory().constructType(Dict.class)); + } catch (MismatchedInputException e) { + // 类型不匹配说明不是json + return null; } catch (IOException e) { throw new RuntimeException(e); } 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 6408c8944..91ddd3f66 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 @@ -3,6 +3,7 @@ package com.ruoyi.common.utils; import cn.hutool.core.convert.Convert; import cn.hutool.extra.servlet.ServletUtil; import cn.hutool.http.HttpStatus; +import com.ruoyi.common.constant.Constants; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.springframework.http.MediaType; @@ -10,11 +11,18 @@ 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; import java.io.IOException; +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; /** * 客户端工具类 @@ -66,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 */ @@ -117,7 +150,7 @@ public class ServletUtils extends ServletUtil { public static boolean isAjaxRequest(HttpServletRequest request) { String accept = request.getHeader("accept"); - if (accept != null && accept.contains("application/json")) { + if (accept != null && accept.contains(MediaType.APPLICATION_JSON_VALUE)) { return true; } @@ -139,4 +172,32 @@ public class ServletUtils extends ServletUtil { return getClientIP(getRequest()); } + /** + * 内容编码 + * + * @param str 内容 + * @return 编码后的内容 + */ + public static String urlEncode(String str) { + try { + return URLEncoder.encode(str, Constants.UTF8); + } catch (UnsupportedEncodingException e) { + return StringUtils.EMPTY; + } + } + + /** + * 内容解码 + * + * @param str 内容 + * @return 解码后的内容 + */ + public static String urlDecode(String str) { + try { + return URLDecoder.decode(str, Constants.UTF8); + } catch (UnsupportedEncodingException e) { + return StringUtils.EMPTY; + } + } + } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/StreamUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/StreamUtils.java new file mode 100644 index 000000000..fccd9e3d1 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/StreamUtils.java @@ -0,0 +1,251 @@ +package com.ruoyi.common.utils; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.map.MapUtil; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + +import java.util.*; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +/** + * stream 流工具类 + * + * @author Lion Li + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class StreamUtils { + + /** + * 将collection过滤 + * + * @param collection 需要转化的集合 + * @param function 过滤方法 + * @return 过滤后的list + */ + public static List filter(Collection collection, Predicate function) { + if (CollUtil.isEmpty(collection)) { + return CollUtil.newArrayList(); + } + return collection.stream().filter(function).collect(Collectors.toList()); + } + + /** + * 将collection拼接 + * + * @param collection 需要转化的集合 + * @param function 拼接方法 + * @return 拼接后的list + */ + public static String join(Collection collection, Function function) { + return join(collection, function, ","); + } + + /** + * 将collection拼接 + * + * @param collection 需要转化的集合 + * @param function 拼接方法 + * @param delimiter 拼接符 + * @return 拼接后的list + */ + public static String join(Collection collection, Function function, CharSequence delimiter) { + if (CollUtil.isEmpty(collection)) { + return StringUtils.EMPTY; + } + return collection.stream().map(function).filter(Objects::nonNull).collect(Collectors.joining(delimiter)); + } + + /** + * 将collection排序 + * + * @param collection 需要转化的集合 + * @param comparing 排序方法 + * @return 排序后的list + */ + public static List sorted(Collection collection, Comparator comparing) { + if (CollUtil.isEmpty(collection)) { + return CollUtil.newArrayList(); + } + return collection.stream().sorted(comparing).collect(Collectors.toList()); + } + + /** + * 将collection转化为类型不变的map
+ * {@code Collection ----> Map} + * + * @param collection 需要转化的集合 + * @param key V类型转化为K类型的lambda方法 + * @param collection中的泛型 + * @param map中的key类型 + * @return 转化后的map + */ + public static Map toIdentityMap(Collection collection, Function key) { + if (CollUtil.isEmpty(collection)) { + return MapUtil.newHashMap(); + } + return collection.stream().collect(Collectors.toMap(key, Function.identity(), (l, r) -> l)); + } + + /** + * 将Collection转化为map(value类型与collection的泛型不同)
+ * {@code Collection -----> Map } + * + * @param collection 需要转化的集合 + * @param key E类型转化为K类型的lambda方法 + * @param value E类型转化为V类型的lambda方法 + * @param collection中的泛型 + * @param map中的key类型 + * @param map中的value类型 + * @return 转化后的map + */ + public static Map toMap(Collection collection, Function key, Function value) { + if (CollUtil.isEmpty(collection)) { + return MapUtil.newHashMap(); + } + return collection.stream().collect(Collectors.toMap(key, value, (l, r) -> l)); + } + + /** + * 将collection按照规则(比如有相同的班级id)分类成map
+ * {@code Collection -------> Map> } + * + * @param collection 需要分类的集合 + * @param key 分类的规则 + * @param collection中的泛型 + * @param map中的key类型 + * @return 分类后的map + */ + public static Map> groupByKey(Collection collection, Function key) { + if (CollUtil.isEmpty(collection)) { + return MapUtil.newHashMap(); + } + return collection + .stream() + .collect(Collectors.groupingBy(key, LinkedHashMap::new, Collectors.toList())); + } + + /** + * 将collection按照两个规则(比如有相同的年级id,班级id)分类成双层map
+ * {@code Collection ---> Map>> } + * + * @param collection 需要分类的集合 + * @param key1 第一个分类的规则 + * @param key2 第二个分类的规则 + * @param 集合元素类型 + * @param 第一个map中的key类型 + * @param 第二个map中的key类型 + * @return 分类后的map + */ + public static Map>> groupBy2Key(Collection collection, Function key1, Function key2) { + if (CollUtil.isEmpty(collection)) { + return MapUtil.newHashMap(); + } + return collection + .stream() + .collect(Collectors.groupingBy(key1, LinkedHashMap::new, Collectors.groupingBy(key2, LinkedHashMap::new, Collectors.toList()))); + } + + /** + * 将collection按照两个规则(比如有相同的年级id,班级id)分类成双层map
+ * {@code Collection ---> Map> } + * + * @param collection 需要分类的集合 + * @param key1 第一个分类的规则 + * @param key2 第二个分类的规则 + * @param 第一个map中的key类型 + * @param 第二个map中的key类型 + * @param collection中的泛型 + * @return 分类后的map + */ + public static Map> group2Map(Collection collection, Function key1, Function key2) { + if (CollUtil.isEmpty(collection) || key1 == null || key2 == null) { + return MapUtil.newHashMap(); + } + return collection + .stream() + .collect(Collectors.groupingBy(key1, LinkedHashMap::new, Collectors.toMap(key2, Function.identity(), (l, r) -> l))); + } + + /** + * 将collection转化为List集合,但是两者的泛型不同
+ * {@code Collection ------> List } + * + * @param collection 需要转化的集合 + * @param function collection中的泛型转化为list泛型的lambda表达式 + * @param collection中的泛型 + * @param List中的泛型 + * @return 转化后的list + */ + public static List toList(Collection collection, Function function) { + if (CollUtil.isEmpty(collection)) { + return CollUtil.newArrayList(); + } + return collection + .stream() + .map(function) + .filter(Objects::nonNull) + .collect(Collectors.toList()); + } + + /** + * 将collection转化为Set集合,但是两者的泛型不同
+ * {@code Collection ------> Set } + * + * @param collection 需要转化的集合 + * @param function collection中的泛型转化为set泛型的lambda表达式 + * @param collection中的泛型 + * @param Set中的泛型 + * @return 转化后的Set + */ + public static Set toSet(Collection collection, Function function) { + if (CollUtil.isEmpty(collection) || function == null) { + return CollUtil.newHashSet(); + } + return collection + .stream() + .map(function) + .filter(Objects::nonNull) + .collect(Collectors.toSet()); + } + + + /** + * 合并两个相同key类型的map + * + * @param map1 第一个需要合并的 map + * @param map2 第二个需要合并的 map + * @param merge 合并的lambda,将key value1 value2合并成最终的类型,注意value可能为空的情况 + * @param map中的key类型 + * @param 第一个 map的value类型 + * @param 第二个 map的value类型 + * @param 最终map的value类型 + * @return 合并后的map + */ + public static Map merge(Map map1, Map map2, BiFunction merge) { + if (MapUtil.isEmpty(map1) && MapUtil.isEmpty(map2)) { + return MapUtil.newHashMap(); + } else if (MapUtil.isEmpty(map1)) { + map1 = MapUtil.newHashMap(); + } else if (MapUtil.isEmpty(map2)) { + map2 = MapUtil.newHashMap(); + } + Set key = new HashSet<>(); + key.addAll(map1.keySet()); + key.addAll(map2.keySet()); + Map map = new HashMap<>(); + for (K t : key) { + X x = map1.get(t); + Y y = map2.get(t); + V z = merge.apply(x, y); + if (z != null) { + map.put(t, z); + } + } + return map; + } + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java index e6a67b26b..3ff8fec40 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java @@ -194,7 +194,6 @@ public class ExcelUtil { */ private static void resetResponse(String sheetName, HttpServletResponse response) throws UnsupportedEncodingException { String filename = encodingFilename(sheetName); - response.reset(); FileUtils.setAttachmentResponseHeader(response, filename); response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8"); } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/CacheUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/CacheUtils.java new file mode 100644 index 000000000..9e0b09b07 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/CacheUtils.java @@ -0,0 +1,75 @@ +package com.ruoyi.common.utils.redis; + +import com.ruoyi.common.utils.spring.SpringUtils; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.redisson.api.RMap; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; + +import java.util.Set; + +/** + * 缓存操作工具类 {@link } + * + * @author Michelle.Chung + * @date 2022/8/13 + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +@SuppressWarnings(value = {"unchecked"}) +public class CacheUtils { + + private static final CacheManager CACHE_MANAGER = SpringUtils.getBean(CacheManager.class); + + /** + * 获取缓存组内所有的KEY + * + * @param cacheNames 缓存组名称 + */ + public static Set keys(String cacheNames) { + RMap rmap = (RMap) CACHE_MANAGER.getCache(cacheNames).getNativeCache(); + return rmap.keySet(); + } + + /** + * 获取缓存值 + * + * @param cacheNames 缓存组名称 + * @param key 缓存key + */ + public static T get(String cacheNames, Object key) { + Cache.ValueWrapper wrapper = CACHE_MANAGER.getCache(cacheNames).get(key); + return wrapper != null ? (T) wrapper.get() : null; + } + + /** + * 保存缓存值 + * + * @param cacheNames 缓存组名称 + * @param key 缓存key + * @param value 缓存值 + */ + public static void put(String cacheNames, Object key, Object value) { + CACHE_MANAGER.getCache(cacheNames).put(key, value); + } + + /** + * 删除缓存值 + * + * @param cacheNames 缓存组名称 + * @param key 缓存key + */ + public static void evict(String cacheNames, Object key) { + CACHE_MANAGER.getCache(cacheNames).evict(key); + } + + /** + * 清空缓存值 + * + * @param cacheNames 缓存组名称 + */ + public static void clear(String cacheNames) { + CACHE_MANAGER.getCache(cacheNames).clear(); + } + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/QueueUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/QueueUtils.java index 7850e016d..7a4bce4b3 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/QueueUtils.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/redis/QueueUtils.java @@ -5,7 +5,6 @@ import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.redisson.api.*; -import java.util.Comparator; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; @@ -30,6 +29,43 @@ public class QueueUtils { return CLIENT; } + /** + * 添加普通队列数据 + * + * @param queueName 队列名 + * @param data 数据 + */ + public static boolean addQueueObject(String queueName, T data) { + RBlockingQueue queue = CLIENT.getBlockingQueue(queueName); + return queue.offer(data); + } + + /** + * 通用获取一个队列数据 没有数据返回 null(不支持延迟队列) + * + * @param queueName 队列名 + */ + public static T getQueueObject(String queueName) { + RBlockingQueue queue = CLIENT.getBlockingQueue(queueName); + return queue.poll(); + } + + /** + * 通用删除队列数据(不支持延迟队列) + */ + public static boolean removeQueueObject(String queueName, T data) { + RBlockingQueue queue = CLIENT.getBlockingQueue(queueName); + return queue.remove(data); + } + + /** + * 通用销毁队列 所有阻塞监听 报错(不支持延迟队列) + */ + public static boolean destroyQueue(String queueName) { + RBlockingQueue queue = CLIENT.getBlockingQueue(queueName); + return queue.delete(); + } + /** * 添加延迟队列数据 默认毫秒 * @@ -84,32 +120,6 @@ public class QueueUtils { delayedQueue.destroy(); } - /** - * 尝试设置 优先队列比较器 用于排序优先级 - * - * @param queueName 队列名 - * @param comparator 比较器 - */ - public static boolean trySetPriorityQueueComparator(String queueName, Comparator comparator) { - RPriorityBlockingQueue priorityBlockingQueue = CLIENT.getPriorityBlockingQueue(queueName); - return priorityBlockingQueue.trySetComparator(comparator); - } - - /** - * 尝试设置 优先队列比较器 用于排序优先级 - * - * @param queueName 队列名 - * @param comparator 比较器 - * @param destroy 已存在是否销毁 - */ - public static boolean trySetPriorityQueueComparator(String queueName, Comparator comparator, boolean destroy) { - RPriorityBlockingQueue priorityBlockingQueue = CLIENT.getPriorityBlockingQueue(queueName); - if (priorityBlockingQueue.isExists() && destroy) { - destroyPriorityQueueObject(queueName); - } - return priorityBlockingQueue.trySetComparator(comparator); - } - /** * 添加优先队列数据 * @@ -121,32 +131,6 @@ public class QueueUtils { return priorityBlockingQueue.offer(data); } - /** - * 获取一个优先队列数据 没有数据返回 null - * - * @param queueName 队列名 - */ - public static T getPriorityQueueObject(String queueName) { - RPriorityBlockingQueue priorityBlockingQueue = CLIENT.getPriorityBlockingQueue(queueName); - return priorityBlockingQueue.poll(); - } - - /** - * 删除优先队列数据 - */ - public static boolean removePriorityQueueObject(String queueName, T data) { - RPriorityBlockingQueue priorityBlockingQueue = CLIENT.getPriorityBlockingQueue(queueName); - return priorityBlockingQueue.remove(data); - } - - /** - * 销毁优先队列 - */ - public static boolean destroyPriorityQueueObject(String queueName) { - RPriorityBlockingQueue priorityBlockingQueue = CLIENT.getPriorityBlockingQueue(queueName); - return priorityBlockingQueue.delete(); - } - /** * 尝试设置 有界队列 容量 用于限制数量 * @@ -168,7 +152,7 @@ public class QueueUtils { public static boolean trySetBoundedQueueCapacity(String queueName, int capacity, boolean destroy) { RBoundedBlockingQueue boundedBlockingQueue = CLIENT.getBoundedBlockingQueue(queueName); if (boundedBlockingQueue.isExists() && destroy) { - destroyBoundedQueueObject(queueName); + destroyQueue(queueName); } return boundedBlockingQueue.trySetCapacity(capacity); } @@ -185,32 +169,6 @@ public class QueueUtils { return boundedBlockingQueue.offer(data); } - /** - * 获取一个有界队列数据 没有数据返回 null - * - * @param queueName 队列名 - */ - public static T getBoundedQueueObject(String queueName) { - RBoundedBlockingQueue boundedBlockingQueue = CLIENT.getBoundedBlockingQueue(queueName); - return boundedBlockingQueue.poll(); - } - - /** - * 删除有界队列数据 - */ - public static boolean removeBoundedQueueObject(String queueName, T data) { - RBoundedBlockingQueue boundedBlockingQueue = CLIENT.getBoundedBlockingQueue(queueName); - return boundedBlockingQueue.remove(data); - } - - /** - * 销毁有界队列 - */ - public static boolean destroyBoundedQueueObject(String queueName) { - RBoundedBlockingQueue boundedBlockingQueue = CLIENT.getBoundedBlockingQueue(queueName); - return boundedBlockingQueue.delete(); - } - /** * 订阅阻塞队列(可订阅所有实现类 例如: 延迟 优先 有界 等) */ 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 7ed3b2827..80f5f5281 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 @@ -1,10 +1,10 @@ package com.ruoyi.common.utils.redis; -import cn.hutool.core.collection.IterUtil; import com.ruoyi.common.utils.spring.SpringUtils; import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.redisson.api.*; +import org.redisson.config.Config; import java.time.Duration; import java.util.Collection; @@ -12,6 +12,8 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Consumer; +import java.util.stream.Collectors; +import java.util.stream.Stream; /** * redis 工具类 @@ -25,6 +27,14 @@ public class RedisUtils { private static final RedissonClient CLIENT = SpringUtils.getBean(RedissonClient.class); + public static NameMapper getNameMapper() { + Config config = CLIENT.getConfig(); + if (config.isClusterConfig()) { + return config.useClusterServers().getNameMapper(); + } + return config.useSingleServer().getNameMapper(); + } + /** * 限流 * @@ -100,14 +110,13 @@ public class RedisUtils { * @since Redis 6.X 以上使用 setAndKeepTTL 兼容 5.X 方案 */ public static void setCacheObject(final String key, final T value, final boolean isSaveTtl) { - RBucket bucket = CLIENT.getBucket(key); + RBucket bucket = CLIENT.getBucket(key); if (isSaveTtl) { try { bucket.setAndKeepTTL(value); } catch (Exception e) { long timeToLive = bucket.remainTimeToLive(); - bucket.set(value); - bucket.expire(Duration.ofMillis(timeToLive)); + setCacheObject(key, value, Duration.ofMillis(timeToLive)); } } else { bucket.set(value); @@ -122,9 +131,11 @@ public class RedisUtils { * @param duration 时间 */ public static void setCacheObject(final String key, final T value, final Duration duration) { - RBucket result = CLIENT.getBucket(key); - result.set(value); - result.expire(duration); + RBatch batch = CLIENT.createBatch(); + RBucketAsync bucket = batch.getBucket(key); + bucket.setAsync(value); + bucket.expireAsync(duration); + batch.execute(); } /** @@ -316,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中存入数据 * @@ -415,8 +437,17 @@ public class RedisUtils { * @return 对象列表 */ public static Collection keys(final String pattern) { - Iterable iterable = CLIENT.getKeys().getKeysByPattern(pattern); - return IterUtil.toList(iterable); + Stream stream = CLIENT.getKeys().getKeysStreamByPattern(getNameMapper().map(pattern)); + return stream.map(key -> getNameMapper().unmap(key)).collect(Collectors.toList()); + } + + /** + * 删除缓存的基本对象列表 + * + * @param pattern 字符串前缀 + */ + public static void deleteKeys(final String pattern) { + CLIENT.getKeys().deleteByPattern(getNameMapper().map(pattern)); } /** @@ -426,6 +457,6 @@ public class RedisUtils { */ public static Boolean hasKey(String key) { RKeys rKeys = CLIENT.getKeys(); - return rKeys.countExists(key) > 0; + return rKeys.countExists(getNameMapper().map(key)) > 0; } } diff --git a/ruoyi-demo/pom.xml b/ruoyi-demo/pom.xml index bbcf0fe2b..46b45981d 100644 --- a/ruoyi-demo/pom.xml +++ b/ruoyi-demo/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.2.0 + 4.4.0 4.0.0 @@ -36,7 +36,7 @@ - + diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/MailController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/MailController.java index 6dabe5132..6db4dc4e7 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/MailController.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/MailController.java @@ -2,9 +2,6 @@ package com.ruoyi.demo.controller; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.utils.email.MailUtils; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -20,27 +17,34 @@ import java.io.File; * @author Michelle.Chung */ @Validated -@Api(value = "邮件发送案例", tags = {"邮件发送案例"}) @RequiredArgsConstructor @RestController @RequestMapping("/demo/mail") public class MailController { - @ApiOperation("发送邮件") + /** + * 发送邮件 + * + * @param to 接收人 + * @param subject 标题 + * @param text 内容 + */ @GetMapping("/sendSimpleMessage") - public R sendSimpleMessage(@ApiParam("接收人") String to, - @ApiParam("标题") String subject, - @ApiParam("内容") String text) { + public R sendSimpleMessage(String to, String subject, String text) { MailUtils.sendText(to, subject, text); return R.ok(); } - @ApiOperation("发送邮件(带附件)") + /** + * 发送邮件(带附件) + * + * @param to 接收人 + * @param subject 标题 + * @param text 内容 + * @param filePath 附件路径 + */ @GetMapping("/sendMessageWithAttachment") - public R sendMessageWithAttachment(@ApiParam("接收人") String to, - @ApiParam("标题") String subject, - @ApiParam("内容") String text, - @ApiParam("附件路径") String filePath) { + public R sendMessageWithAttachment(String to, String subject, String text, String filePath) { MailUtils.sendText(to, subject, text, new File(filePath)); return R.ok(); } diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisCacheController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisCacheController.java index 9fc93074f..7342cba98 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisCacheController.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisCacheController.java @@ -1,9 +1,8 @@ package com.ruoyi.demo.controller; +import com.ruoyi.common.constant.CacheNames; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.utils.redis.RedisUtils; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.CachePut; @@ -20,8 +19,7 @@ import java.time.Duration; * @author Lion Li */ // 类级别 缓存统一配置 -//@CacheConfig(cacheNames = "redissonCacheMap") -@Api(value = "spring-cache 演示案例", tags = {"spring-cache 演示案例"}) +//@CacheConfig(cacheNames = CacheNames.DEMO_CACHE) @RequiredArgsConstructor @RestController @RequestMapping("/demo/cache") @@ -39,10 +37,9 @@ public class RedisCacheController { * 重点说明: 缓存注解严谨与其他筛选数据功能一起使用 * 例如: 数据权限注解 会造成 缓存击穿 与 数据不一致问题 *

- * cacheNames 为配置文件内 groupId + * cacheNames 命名规则 查看 {@link CacheNames} 注释 支持多参数 */ - @ApiOperation("测试 @Cacheable") - @Cacheable(cacheNames = "redissonCacheMap", key = "#key", condition = "#key != null") + @Cacheable(cacheNames = "demo:cache#60s#10m#20", key = "#key", condition = "#key != null") @GetMapping("/test1") public R test1(String key, String value) { return R.ok("操作成功", value); @@ -52,12 +49,11 @@ public class RedisCacheController { * 测试 @CachePut *

* 加了@CachePut注解的方法,会把方法的返回值put到缓存里面缓存起来,供其它地方使用 - * 它「通常用在新增方法上」 + * 它「通常用在新增或者实时更新方法上」 *

- * cacheNames 为 配置文件内 groupId + * cacheNames 命名规则 查看 {@link CacheNames} 注释 支持多参数 */ - @ApiOperation("测试 @CachePut") - @CachePut(cacheNames = "redissonCacheMap", key = "#key", condition = "#key != null") + @CachePut(cacheNames = CacheNames.DEMO_CACHE, key = "#key", condition = "#key != null") @GetMapping("/test2") public R test2(String key, String value) { return R.ok("操作成功", value); @@ -67,12 +63,11 @@ public class RedisCacheController { * 测试 @CacheEvict *

* 使用了CacheEvict注解的方法,会清空指定缓存 - * 「一般用在更新或者删除的方法上」 + * 「一般用在删除的方法上」 *

- * cacheNames 为 配置文件内 groupId + * cacheNames 命名规则 查看 {@link CacheNames} 注释 支持多参数 */ - @ApiOperation("测试 @CacheEvict") - @CacheEvict(cacheNames = "redissonCacheMap", key = "#key", condition = "#key != null") + @CacheEvict(cacheNames = CacheNames.DEMO_CACHE, key = "#key", condition = "#key != null") @GetMapping("/test3") public R test3(String key, String value) { return R.ok("操作成功", value); @@ -83,7 +78,6 @@ public class RedisCacheController { * 手动设置过期时间10秒 * 11秒后获取 判断是否相等 */ - @ApiOperation("测试设置过期时间") @GetMapping("/test6") public R test6(String key, String value) { RedisUtils.setCacheObject(key, value); diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisLockController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisLockController.java index c31925a57..ebc923d1b 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisLockController.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisLockController.java @@ -5,8 +5,6 @@ import com.baomidou.lock.LockTemplate; import com.baomidou.lock.annotation.Lock4j; import com.baomidou.lock.executor.RedissonLockExecutor; import com.ruoyi.common.core.domain.R; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; @@ -21,7 +19,6 @@ import java.time.LocalTime; * * @author shenxinquan */ -@Api(value = "测试分布式锁的样例", tags = {"测试分布式锁的样例"}) @Slf4j @RestController @RequestMapping("/demo/redisLock") @@ -33,7 +30,6 @@ public class RedisLockController { /** * 测试lock4j 注解 */ - @ApiOperation("测试lock4j 注解") @Lock4j(keys = {"#key"}) @GetMapping("/testLock4j") public R testLock4j(String key, String value) { @@ -50,7 +46,6 @@ public class RedisLockController { /** * 测试lock4j 工具 */ - @ApiOperation("测试lock4j 工具") @GetMapping("/testLock4jLockTemplate") public R testLock4jLockTemplate(String key, String value) { final LockInfo lockInfo = lockTemplate.lock(key, 30000L, 5000L, RedissonLockExecutor.class); diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisPubSubController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisPubSubController.java index 99c3131b4..0c2af3951 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisPubSubController.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisPubSubController.java @@ -2,9 +2,6 @@ package com.ruoyi.demo.controller; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.utils.redis.RedisUtils; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -15,24 +12,32 @@ import org.springframework.web.bind.annotation.RestController; * * @author Lion Li */ -@Api(value = "Redis发布订阅 演示案例", tags = {"Redis发布订阅"}) @RequiredArgsConstructor @RestController @RequestMapping("/demo/redis/pubsub") public class RedisPubSubController { - @ApiOperation("发布消息") + /** + * 发布消息 + * + * @param key 通道Key + * @param value 发送内容 + */ @GetMapping("/pub") - public R pub(@ApiParam("通道Key") String key, @ApiParam("发送内容") String value) { + public R pub(String key, String value) { RedisUtils.publish(key, value, consumer -> { System.out.println("发布通道 => " + key + ", 发送值 => " + value); }); return R.ok("操作成功"); } - @ApiOperation("订阅消息") + /** + * 订阅消息 + * + * @param key 通道Key + */ @GetMapping("/sub") - public R sub(@ApiParam("通道Key") String key) { + public R sub(String key) { RedisUtils.subscribe(key, String.class, msg -> { System.out.println("订阅通道 => " + key + ", 接收值 => " + msg); }); diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisRateLimiterController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisRateLimiterController.java index c7f48e519..ee2e530ba 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisRateLimiterController.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisRateLimiterController.java @@ -3,8 +3,6 @@ package com.ruoyi.demo.controller; import com.ruoyi.common.annotation.RateLimiter; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.enums.LimitType; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -16,7 +14,6 @@ import org.springframework.web.bind.annotation.RestController; * * @author Lion Li */ -@Api(value = "测试分布式限流样例", tags = {"测试分布式限流样例"}) @Slf4j @RestController @RequestMapping("/demo/rateLimiter") @@ -26,7 +23,6 @@ public class RedisRateLimiterController { * 测试全局限流 * 全局影响 */ - @ApiOperation("测试全局限流") @RateLimiter(count = 2, time = 10) @GetMapping("/test") public R test(String value) { @@ -37,7 +33,6 @@ public class RedisRateLimiterController { * 测试请求IP限流 * 同一IP请求受影响 */ - @ApiOperation("测试请求IP限流") @RateLimiter(count = 2, time = 10, limitType = LimitType.IP) @GetMapping("/testip") public R testip(String value) { @@ -48,7 +43,6 @@ public class RedisRateLimiterController { * 测试集群实例限流 * 启动两个后端服务互不影响 */ - @ApiOperation("测试集群实例限流") @RateLimiter(count = 2, time = 10, limitType = LimitType.CLUSTER) @GetMapping("/testcluster") public R testcluster(String value) { diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/SmsController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/SmsController.java index b92078624..cc6012f44 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/SmsController.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/SmsController.java @@ -4,9 +4,6 @@ import com.ruoyi.common.core.domain.R; import com.ruoyi.common.utils.spring.SpringUtils; import com.ruoyi.sms.config.properties.SmsProperties; import com.ruoyi.sms.core.SmsTemplate; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -24,7 +21,6 @@ import java.util.Map; * @version 4.2.0 */ @Validated -@Api(value = "短信演示案例", tags = {"短信演示案例"}) @RequiredArgsConstructor @RestController @RequestMapping("/demo/sms") @@ -34,10 +30,14 @@ public class SmsController { // private final SmsTemplate smsTemplate; // 可以使用spring注入 // private final AliyunSmsTemplate smsTemplate; // 也可以注入某个厂家的模板工具 - @ApiOperation("发送短信Aliyun") + /** + * 发送短信Aliyun + * + * @param phones 电话号 + * @param templateId 模板ID + */ @GetMapping("/sendAliyun") - public R sendAliyun(@ApiParam("电话号") String phones, - @ApiParam("模板ID") String templateId) { + public R sendAliyun(String phones, String templateId) { if (!smsProperties.getEnabled()) { return R.fail("当前系统没有开启短信功能!"); } @@ -51,10 +51,14 @@ public class SmsController { return R.ok(send); } - @ApiOperation("发送短信Tencent") + /** + * 发送短信Tencent + * + * @param phones 电话号 + * @param templateId 模板ID + */ @GetMapping("/sendTencent") - public R sendTencent(@ApiParam("电话号") String phones, - @ApiParam("模板ID") String templateId) { + public R sendTencent(String phones, String templateId) { if (!smsProperties.getEnabled()) { return R.fail("当前系统没有开启短信功能!"); } diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/Swagger3DemoController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/Swagger3DemoController.java index e50ce03a5..0398b14d5 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/Swagger3DemoController.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/Swagger3DemoController.java @@ -1,24 +1,18 @@ package com.ruoyi.demo.controller; import com.ruoyi.common.core.domain.R; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiImplicitParam; -import io.swagger.annotations.ApiImplicitParams; -import io.swagger.annotations.ApiOperation; +import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestPart; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; -import java.io.File; - /** * swagger3 用法示例 * * @author Lion Li */ -@Api(value = "演示swagger3控制器", tags = {"演示swagger3接口"}) @RestController @RequestMapping("/swagger/demo") public class Swagger3DemoController { @@ -26,12 +20,10 @@ public class Swagger3DemoController { /** * 上传请求 * 必须使用 @RequestPart 注解标注为文件 + * + * @param file 文件 */ - @ApiOperation(value = "通用上传请求") - @ApiImplicitParams({ - @ApiImplicitParam(name = "file", value = "文件", paramType = "query", dataTypeClass = File.class, required = true) - }) - @PostMapping(value = "/upload") + @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public R upload(@RequestPart("file") MultipartFile file) { return R.ok("操作成功", file.getOriginalFilename()); } 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 aa1f064a0..3bd2867ee 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 @@ -5,8 +5,6 @@ import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.R; import com.ruoyi.demo.domain.TestDemo; import com.ruoyi.demo.mapper.TestDemoMapper; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.PostMapping; @@ -22,7 +20,6 @@ import java.util.List; * @author Lion Li * @date 2021-05-30 */ -@Api(value = "测试批量方法", tags = {"测试批量方法"}) @RequiredArgsConstructor @RestController @RequestMapping("/demo/batch") @@ -38,7 +35,6 @@ public class TestBatchController extends BaseController { *

* 3.5.0 版本 增加 rewriteBatchedStatements=true 批处理参数 使 MP 原生批处理可以达到同样的速度 */ - @ApiOperation(value = "新增批量方法") @PostMapping("/add") // @DS("slave") public R add() { @@ -50,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)); } /** @@ -58,7 +54,6 @@ public class TestBatchController extends BaseController { *

* 3.5.0 版本 增加 rewriteBatchedStatements=true 批处理参数 使 MP 原生批处理可以达到同样的速度 */ - @ApiOperation(value = "新增或更新批量方法") @PostMapping("/addOrUpdate") // @DS("slave") public R addOrUpdate() { @@ -68,7 +63,8 @@ public class TestBatchController extends BaseController { testDemo.setOrderNum(-1); testDemo.setTestKey("批量新增"); testDemo.setValue("测试新增"); - list.add(testDemo); } + list.add(testDemo); + } testDemoMapper.insertBatch(list); for (int i = 0; i < list.size(); i++) { TestDemo testDemo = list.get(i); @@ -78,13 +74,12 @@ public class TestBatchController extends BaseController { testDemo.setId(null); } } - return toAjax(testDemoMapper.insertOrUpdateBatch(list) ? 1 : 0); + return toAjax(testDemoMapper.insertOrUpdateBatch(list)); } /** * 删除批量方法 */ - @ApiOperation(value = "删除批量方法") @DeleteMapping() // @DS("slave") public R remove() { 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 9f00c0770..873facc3b 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 @@ -5,8 +5,8 @@ import cn.hutool.core.bean.BeanUtil; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.annotation.RepeatSubmit; import com.ruoyi.common.core.controller.BaseController; -import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.PageQuery; +import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.validate.AddGroup; import com.ruoyi.common.core.validate.EditGroup; @@ -20,8 +20,8 @@ import com.ruoyi.demo.domain.bo.TestDemoBo; import com.ruoyi.demo.domain.bo.TestDemoImportVo; import com.ruoyi.demo.domain.vo.TestDemoVo; import com.ruoyi.demo.service.ITestDemoService; -import io.swagger.annotations.*; import lombok.RequiredArgsConstructor; +import org.springframework.http.MediaType; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -29,7 +29,6 @@ import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; -import java.io.File; import java.util.Arrays; import java.util.List; import java.util.concurrent.TimeUnit; @@ -41,7 +40,6 @@ import java.util.concurrent.TimeUnit; * @date 2021-07-26 */ @Validated -@Api(value = "测试单表控制器", tags = {"测试单表管理"}) @RequiredArgsConstructor @RestController @RequestMapping("/demo/demo") @@ -52,7 +50,6 @@ public class TestDemoController extends BaseController { /** * 查询测试单表列表 */ - @ApiOperation("查询测试单表列表") @SaCheckPermission("demo:demo:list") @GetMapping("/list") public TableDataInfo list(@Validated(QueryGroup.class) TestDemoBo bo, PageQuery pageQuery) { @@ -62,20 +59,20 @@ public class TestDemoController extends BaseController { /** * 自定义分页查询 */ - @ApiOperation("自定义分页查询") @SaCheckPermission("demo:demo:list") @GetMapping("/page") public TableDataInfo page(@Validated(QueryGroup.class) TestDemoBo bo, PageQuery pageQuery) { return iTestDemoService.customPageList(bo, pageQuery); } - @ApiOperation("导入测试-校验") - @ApiImplicitParams({ - @ApiImplicitParam(name = "file", value = "导入文件", paramType = "query", dataTypeClass = File.class, required = true), - }) + /** + * 导入数据 + * + * @param file 导入文件 + */ @Log(title = "测试单表", businessType = BusinessType.IMPORT) @SaCheckPermission("demo:demo:import") - @PostMapping("/importData") + @PostMapping(value = "/importData", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public R importData(@RequestPart("file") MultipartFile file) throws Exception { ExcelResult excelResult = ExcelUtil.importExcel(file.getInputStream(), TestDemoImportVo.class, true); List volist = excelResult.getList(); @@ -87,7 +84,6 @@ public class TestDemoController extends BaseController { /** * 导出测试单表列表 */ - @ApiOperation("导出测试单表列表") @SaCheckPermission("demo:demo:export") @Log(title = "测试单表", businessType = BusinessType.EXPORT) @PostMapping("/export") @@ -102,20 +98,19 @@ public class TestDemoController extends BaseController { /** * 获取测试单表详细信息 + * + * @param id 测试ID */ - @ApiOperation("获取测试单表详细信息") @SaCheckPermission("demo:demo:query") @GetMapping("/{id}") - public R getInfo(@ApiParam("测试ID") - @NotNull(message = "主键不能为空") - @PathVariable("id") Long id) { + public R getInfo(@NotNull(message = "主键不能为空") + @PathVariable("id") Long id) { return R.ok(iTestDemoService.queryById(id)); } /** * 新增测试单表 */ - @ApiOperation("新增测试单表") @SaCheckPermission("demo:demo:add") @Log(title = "测试单表", businessType = BusinessType.INSERT) @RepeatSubmit(interval = 2, timeUnit = TimeUnit.SECONDS, message = "{repeat.submit.message}") @@ -124,31 +119,30 @@ 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)); } /** * 修改测试单表 */ - @ApiOperation("修改测试单表") @SaCheckPermission("demo:demo:edit") @Log(title = "测试单表", businessType = BusinessType.UPDATE) @RepeatSubmit @PutMapping() public R edit(@Validated(EditGroup.class) @RequestBody TestDemoBo bo) { - return toAjax(iTestDemoService.updateByBo(bo) ? 1 : 0); + return toAjax(iTestDemoService.updateByBo(bo)); } /** * 删除测试单表 + * + * @param ids 测试ID串 */ - @ApiOperation("删除测试单表") @SaCheckPermission("demo:demo:remove") @Log(title = "测试单表", businessType = BusinessType.DELETE) @DeleteMapping("/{ids}") - public R remove(@ApiParam("测试ID串") - @NotEmpty(message = "主键不能为空") - @PathVariable Long[] ids) { - return toAjax(iTestDemoService.deleteWithValidByIds(Arrays.asList(ids), true) ? 1 : 0); + public R remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] ids) { + return toAjax(iTestDemoService.deleteWithValidByIds(Arrays.asList(ids), true)); } } diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestExcelController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestExcelController.java index a318b4658..51b81c582 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestExcelController.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestExcelController.java @@ -2,8 +2,6 @@ package com.ruoyi.demo.controller; import cn.hutool.core.collection.CollUtil; import com.ruoyi.common.utils.poi.ExcelUtil; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; import lombok.AllArgsConstructor; import lombok.Data; import org.springframework.web.bind.annotation.GetMapping; @@ -21,7 +19,6 @@ import java.util.Map; * * @author Lion Li */ -@Api(value = "测试Excel功能", tags = {"测试Excel功能"}) @RestController @RequestMapping("/demo/excel") public class TestExcelController { @@ -29,35 +26,33 @@ public class TestExcelController { /** * 单列表多数据 */ - @ApiOperation(value = "单列表多数据") @GetMapping("/exportTemplateOne") public void exportTemplateOne(HttpServletResponse response) { - Map map = new HashMap<>(); - map.put("title","单列表多数据"); - map.put("test1","数据测试1"); - map.put("test2","数据测试2"); - map.put("test3","数据测试3"); - map.put("test4","数据测试4"); - map.put("testTest","666"); + Map map = new HashMap<>(); + map.put("title", "单列表多数据"); + map.put("test1", "数据测试1"); + map.put("test2", "数据测试2"); + map.put("test3", "数据测试3"); + map.put("test4", "数据测试4"); + map.put("testTest", "666"); List list = new ArrayList<>(); list.add(new TestObj("单列表测试1", "列表测试1", "列表测试2", "列表测试3", "列表测试4")); list.add(new TestObj("单列表测试2", "列表测试5", "列表测试6", "列表测试7", "列表测试8")); list.add(new TestObj("单列表测试3", "列表测试9", "列表测试10", "列表测试11", "列表测试12")); - ExcelUtil.exportTemplate(CollUtil.newArrayList(map,list),"单列表.xlsx", "excel/单列表.xlsx", response); + ExcelUtil.exportTemplate(CollUtil.newArrayList(map, list), "单列表.xlsx", "excel/单列表.xlsx", response); } /** * 多列表多数据 */ - @ApiOperation(value = "多列表多数据") @GetMapping("/exportTemplateMuliti") public void exportTemplateMuliti(HttpServletResponse response) { - Map map = new HashMap<>(); - map.put("title1","标题1"); - map.put("title2","标题2"); - map.put("title3","标题3"); - map.put("title4","标题4"); - map.put("author","Lion Li"); + Map map = new HashMap<>(); + map.put("title1", "标题1"); + map.put("title2", "标题2"); + map.put("title3", "标题3"); + map.put("title4", "标题4"); + map.put("author", "Lion Li"); List list1 = new ArrayList<>(); list1.add(new TestObj1("list1测试1", "list1测试2", "list1测试3")); list1.add(new TestObj1("list1测试4", "list1测试5", "list1测试6")); @@ -72,12 +67,12 @@ public class TestExcelController { list4.add(new TestObj1("list4测试4", "list4测试5", "list4测试6")); list4.add(new TestObj1("list4测试7", "list4测试8", "list4测试9")); list4.add(new TestObj1("list4测试10", "list4测试11", "list4测试12")); - Map multiListMap = new HashMap<>(); - multiListMap.put("map",map); - multiListMap.put("data1",list1); - multiListMap.put("data2",list2); - multiListMap.put("data3",list3); - multiListMap.put("data4",list4); + Map multiListMap = new HashMap<>(); + multiListMap.put("map", map); + multiListMap.put("data1", list1); + multiListMap.put("data2", list2); + multiListMap.put("data3", list3); + multiListMap.put("data4", list4); ExcelUtil.exportTemplateMultiList(multiListMap, "多列表.xlsx", "excel/多列表.xlsx", response); } diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestI18nController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestI18nController.java index 9b3bffc09..0cc529a61 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestI18nController.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestI18nController.java @@ -2,9 +2,6 @@ package com.ruoyi.demo.controller; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.utils.MessageUtils; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; import lombok.Data; import org.hibernate.validator.constraints.Range; import org.springframework.validation.annotation.Validated; @@ -22,7 +19,6 @@ import javax.validation.constraints.NotNull; * @author Lion Li */ @Validated -@Api(value = "测试国际化控制器", tags = {"测试国际化管理"}) @RestController @RequestMapping("/demo/i18n") public class TestI18nController { @@ -32,10 +28,11 @@ public class TestI18nController { * code为 messages.properties 中的 key *

* 测试使用 user.register.success + * + * @param code 国际化code */ - @ApiOperation("通过code获取国际化内容") @GetMapping() - public R get(@ApiParam("国际化code") String code) { + public R get(String code) { return R.ok(MessageUtils.message(code)); } @@ -45,7 +42,6 @@ public class TestI18nController { *

* 测试使用 not.null */ - @ApiOperation("Validator 校验国际化") @GetMapping("/test1") public R test1(@NotBlank(message = "{not.null}") String str) { return R.ok(str); @@ -57,7 +53,6 @@ public class TestI18nController { *

* 测试使用 not.null */ - @ApiOperation("Bean 校验国际化") @GetMapping("/test2") public R test2(@Validated TestI18nBo bo) { return R.ok(bo); diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestSensitiveController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestSensitiveController.java index 1f34f9cf4..6bf904caf 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestSensitiveController.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestSensitiveController.java @@ -4,8 +4,6 @@ import com.ruoyi.common.annotation.Sensitive; import com.ruoyi.common.core.controller.BaseController; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.enums.SensitiveStrategy; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; import lombok.Data; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -21,7 +19,6 @@ import org.springframework.web.bind.annotation.RestController; * @version 3.6.0 * @see com.ruoyi.common.core.service.SensitiveService */ -@Api(value = "测试数据脱敏控制器", tags = {"测试数据脱敏管理"}) @RestController @RequestMapping("/demo/sensitive") public class TestSensitiveController extends BaseController { @@ -29,7 +26,6 @@ public class TestSensitiveController extends BaseController { /** * 测试数据脱敏 */ - @ApiOperation("查询测试单表列表") @GetMapping("/test") public R test() { TestSensitive testSensitive = new TestSensitive(); 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 64f36c941..db54230c6 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 @@ -13,9 +13,6 @@ import com.ruoyi.common.utils.poi.ExcelUtil; import com.ruoyi.demo.domain.bo.TestTreeBo; import com.ruoyi.demo.domain.vo.TestTreeVo; import com.ruoyi.demo.service.ITestTreeService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -33,7 +30,6 @@ import java.util.List; * @date 2021-07-26 */ @Validated -@Api(value = "测试树表控制器", tags = {"测试树表管理"}) @RequiredArgsConstructor @RestController @RequestMapping("/demo/tree") @@ -44,7 +40,6 @@ public class TestTreeController extends BaseController { /** * 查询测试树表列表 */ - @ApiOperation("查询测试树表列表") @SaCheckPermission("demo:tree:list") @GetMapping("/list") public R> list(@Validated(QueryGroup.class) TestTreeBo bo) { @@ -55,7 +50,6 @@ public class TestTreeController extends BaseController { /** * 导出测试树表列表 */ - @ApiOperation("导出测试树表列表") @SaCheckPermission("demo:tree:export") @Log(title = "测试树表", businessType = BusinessType.EXPORT) @GetMapping("/export") @@ -66,50 +60,48 @@ public class TestTreeController extends BaseController { /** * 获取测试树表详细信息 + * + * @param id 测试树ID */ - @ApiOperation("获取测试树表详细信息") @SaCheckPermission("demo:tree:query") @GetMapping("/{id}") - public R getInfo(@ApiParam("测试树ID") - @NotNull(message = "主键不能为空") - @PathVariable("id") Long id) { + public R getInfo(@NotNull(message = "主键不能为空") + @PathVariable("id") Long id) { return R.ok(iTestTreeService.queryById(id)); } /** * 新增测试树表 */ - @ApiOperation("新增测试树表") @SaCheckPermission("demo:tree:add") @Log(title = "测试树表", businessType = BusinessType.INSERT) @RepeatSubmit @PostMapping() public R add(@Validated(AddGroup.class) @RequestBody TestTreeBo bo) { - return toAjax(iTestTreeService.insertByBo(bo) ? 1 : 0); + return toAjax(iTestTreeService.insertByBo(bo)); } /** * 修改测试树表 */ - @ApiOperation("修改测试树表") @SaCheckPermission("demo:tree:edit") @Log(title = "测试树表", businessType = BusinessType.UPDATE) @RepeatSubmit @PutMapping() public R edit(@Validated(EditGroup.class) @RequestBody TestTreeBo bo) { - return toAjax(iTestTreeService.updateByBo(bo) ? 1 : 0); + return toAjax(iTestTreeService.updateByBo(bo)); } /** * 删除测试树表 + * + * @param ids 测试树ID串 */ - @ApiOperation("删除测试树表") @SaCheckPermission("demo:tree:remove") @Log(title = "测试树表", businessType = BusinessType.DELETE) @DeleteMapping("/{ids}") - public R remove(@ApiParam("测试树ID串") - @NotEmpty(message = "主键不能为空") - @PathVariable Long[] ids) { - return toAjax(iTestTreeService.deleteWithValidByIds(Arrays.asList(ids), true) ? 1 : 0); + public R remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] ids) { + return toAjax(iTestTreeService.deleteWithValidByIds(Arrays.asList(ids), true)); } } diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/BoundedQueueController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/BoundedQueueController.java index 532c499e1..968a4193f 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/BoundedQueueController.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/BoundedQueueController.java @@ -2,9 +2,6 @@ package com.ruoyi.demo.controller.queue; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.utils.redis.QueueUtils; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; @@ -23,19 +20,22 @@ import org.springframework.web.bind.annotation.RestController; * @version 3.6.0 */ @Slf4j -@Api(value = "有界队列 演示案例", tags = {"有界队列"}) @RequiredArgsConstructor @RestController @RequestMapping("/demo/queue/bounded") public class BoundedQueueController { - @ApiOperation("添加队列数据") + /** + * 添加队列数据 + * + * @param queueName 队列名 + * @param capacity 容量 + */ @GetMapping("/add") - public R add(@ApiParam("队列名") String queueName, - @ApiParam("容量") int capacity) { + public R add(String queueName, int capacity) { // 用完了一定要销毁 否则会一直存在 - boolean b = QueueUtils.destroyBoundedQueueObject(queueName); + boolean b = QueueUtils.destroyQueue(queueName); log.info("通道: {} , 删除: {}", queueName, b); // 初始化设置一次即可 if (QueueUtils.trySetBoundedQueueCapacity(queueName, capacity)) { @@ -56,11 +56,15 @@ public class BoundedQueueController { return R.ok("操作成功"); } - @ApiOperation("删除队列数据") + /** + * 删除队列数据 + * + * @param queueName 队列名 + */ @GetMapping("/remove") - public R remove(@ApiParam("队列名") String queueName) { + public R remove(String queueName) { String data = "data-" + 5; - if (QueueUtils.removeBoundedQueueObject(queueName, data)) { + if (QueueUtils.removeQueueObject(queueName, data)) { log.info("通道: {} , 删除数据: {}", queueName, data); } else { return R.fail("操作失败"); @@ -68,12 +72,16 @@ public class BoundedQueueController { return R.ok("操作成功"); } - @ApiOperation("获取队列数据") + /** + * 获取队列数据 + * + * @param queueName 队列名 + */ @GetMapping("/get") - public R get(@ApiParam("队列名") String queueName) { + public R get(String queueName) { String data; do { - data = QueueUtils.getBoundedQueueObject(queueName); + data = QueueUtils.getQueueObject(queueName); log.info("通道: {} , 获取数据: {}", queueName, data); } while (data != null); return R.ok("操作成功"); diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/DelayedQueueController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/DelayedQueueController.java index f8777533c..e6dbee863 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/DelayedQueueController.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/DelayedQueueController.java @@ -2,9 +2,6 @@ package com.ruoyi.demo.controller.queue; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.utils.redis.QueueUtils; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; @@ -26,15 +23,18 @@ import java.util.concurrent.TimeUnit; * @version 3.6.0 */ @Slf4j -@Api(value = "延迟队列 演示案例", tags = {"延迟队列"}) @RequiredArgsConstructor @RestController @RequestMapping("/demo/queue/delayed") public class DelayedQueueController { - @ApiOperation("订阅队列") + /** + * 订阅队列 + * + * @param queueName 队列名 + */ @GetMapping("/subscribe") - public R subscribe(@ApiParam("队列名") String queueName) { + public R subscribe(String queueName) { log.info("通道: {} 监听中......", queueName); // 项目初始化设置一次即可 QueueUtils.subscribeBlockingQueue(queueName, (String orderNum) -> { @@ -44,21 +44,29 @@ public class DelayedQueueController { return R.ok("操作成功"); } - @ApiOperation("添加队列数据") + /** + * 添加队列数据 + * + * @param queueName 队列名 + * @param orderNum 订单号 + * @param time 延迟时间(秒) + */ @GetMapping("/add") - public R add(@ApiParam("队列名") String queueName, - @ApiParam("订单号") String orderNum, - @ApiParam("延迟时间(秒)") Long time) { + public R add(String queueName, String orderNum, Long time) { QueueUtils.addDelayedQueueObject(queueName, orderNum, time, TimeUnit.SECONDS); // 观察发送时间 log.info("通道: {} , 发送数据: {}", queueName, orderNum); return R.ok("操作成功"); } - @ApiOperation("删除队列数据") + /** + * 删除队列数据 + * + * @param queueName 队列名 + * @param orderNum 订单号 + */ @GetMapping("/remove") - public R remove(@ApiParam("队列名") String queueName, - @ApiParam("订单号") String orderNum) { + public R remove(String queueName, String orderNum) { if (QueueUtils.removeDelayedQueueObject(queueName, orderNum)) { log.info("通道: {} , 删除数据: {}", queueName, orderNum); } else { @@ -67,9 +75,13 @@ public class DelayedQueueController { return R.ok("操作成功"); } - @ApiOperation("销毁队列") + /** + * 销毁队列 + * + * @param queueName 队列名 + */ @GetMapping("/destroy") - public R destroy(@ApiParam("队列名") String queueName) { + public R destroy(String queueName) { // 用完了一定要销毁 否则会一直存在 QueueUtils.destroyDelayedQueue(queueName); return R.ok("操作成功"); diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityDemo.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityDemo.java index 80f1b1155..320a640da 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityDemo.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityDemo.java @@ -2,6 +2,7 @@ package com.ruoyi.demo.controller.queue; import lombok.Data; import lombok.NoArgsConstructor; +import org.jetbrains.annotations.NotNull; /** * 实体类 注意不允许使用内部类 否则会找不到类 @@ -11,7 +12,12 @@ import lombok.NoArgsConstructor; */ @Data @NoArgsConstructor -public class PriorityDemo { +public class PriorityDemo implements Comparable { private String name; private Integer orderNum; + + @Override + public int compareTo(@NotNull PriorityDemo other) { + return Integer.compare(getOrderNum(), other.getOrderNum()); + } } diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityDemoComparator.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityDemoComparator.java deleted file mode 100644 index f72e6950d..000000000 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityDemoComparator.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.ruoyi.demo.controller.queue; - -import java.util.Comparator; - -/** - * 比较器 注意不允许使用 内部类或匿名类或lambda表达式 会找不到类 - * - * @author Lion Li - * @version 3.6.0 - */ -public class PriorityDemoComparator implements Comparator { - @Override - public int compare(PriorityDemo pd1, PriorityDemo pd2) { - return Integer.compare(pd1.getOrderNum(), pd2.getOrderNum()); - } -} diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityQueueController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityQueueController.java index baec18440..4a60232c7 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityQueueController.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/queue/PriorityQueueController.java @@ -3,9 +3,6 @@ package com.ruoyi.demo.controller.queue; import cn.hutool.core.util.RandomUtil; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.utils.redis.QueueUtils; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; @@ -24,26 +21,22 @@ import org.springframework.web.bind.annotation.RestController; * @version 3.6.0 */ @Slf4j -@Api(value = "优先队列 演示案例", tags = {"优先队列"}) @RequiredArgsConstructor @RestController @RequestMapping("/demo/queue/priority") public class PriorityQueueController { - @ApiOperation("添加队列数据") + /** + * 添加队列数据 + * + * @param queueName 队列名 + */ @GetMapping("/add") - public R add(@ApiParam("队列名") String queueName) { + public R add(String queueName) { // 用完了一定要销毁 否则会一直存在 - boolean b = QueueUtils.destroyPriorityQueueObject(queueName); + boolean b = QueueUtils.destroyQueue(queueName); log.info("通道: {} , 删除: {}", queueName, b); - // 初始化设置一次即可 此处注意 不允许用内部类或匿名类 - boolean flag = QueueUtils.trySetPriorityQueueComparator(queueName, new PriorityDemoComparator()); - if (flag) { - log.info("通道: {} , 设置比较器成功", queueName); - } else { - log.info("通道: {} , 设置比较器失败", queueName); - return R.fail("操作失败"); - } + for (int i = 0; i < 10; i++) { int randomNum = RandomUtil.randomInt(10); PriorityDemo data = new PriorityDemo(); @@ -58,15 +51,19 @@ public class PriorityQueueController { return R.ok("操作成功"); } - @ApiOperation("删除队列数据") + /** + * 删除队列数据 + * + * @param queueName 队列名 + * @param name 对象名 + * @param orderNum 排序号 + */ @GetMapping("/remove") - public R remove(@ApiParam("队列名") String queueName, - @ApiParam("对象名") String name, - @ApiParam("排序号") Integer orderNum) { + public R remove(String queueName, String name, Integer orderNum) { PriorityDemo data = new PriorityDemo(); data.setName(name); data.setOrderNum(orderNum); - if (QueueUtils.removePriorityQueueObject(queueName, data)) { + if (QueueUtils.removeQueueObject(queueName, data)) { log.info("通道: {} , 删除数据: {}", queueName, data); } else { return R.fail("操作失败"); @@ -74,12 +71,16 @@ public class PriorityQueueController { return R.ok("操作成功"); } - @ApiOperation("获取队列数据") + /** + * 获取队列数据 + * + * @param queueName 队列名 + */ @GetMapping("/get") - public R get(@ApiParam("队列名") String queueName) { + public R get(String queueName) { PriorityDemo data; do { - data = QueueUtils.getPriorityQueueObject(queueName); + data = QueueUtils.getQueueObject(queueName); log.info("通道: {} , 获取数据: {}", queueName, data); } while (data != null); return R.ok("操作成功"); diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestDemoBo.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestDemoBo.java index 61c10ab16..54ecae117 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestDemoBo.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestDemoBo.java @@ -3,8 +3,6 @@ package com.ruoyi.demo.domain.bo; import com.ruoyi.common.core.domain.BaseEntity; import com.ruoyi.common.core.validate.AddGroup; import com.ruoyi.common.core.validate.EditGroup; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; @@ -20,48 +18,41 @@ import javax.validation.constraints.NotNull; @Data @EqualsAndHashCode(callSuper = true) -@ApiModel("测试单表业务对象") public class TestDemoBo extends BaseEntity { /** * 主键 */ - @ApiModelProperty("主键") @NotNull(message = "主键不能为空", groups = {EditGroup.class}) private Long id; /** * 部门id */ - @ApiModelProperty("部门id") @NotNull(message = "部门id不能为空", groups = {AddGroup.class, EditGroup.class}) private Long deptId; /** * 用户id */ - @ApiModelProperty("用户id") @NotNull(message = "用户id不能为空", groups = {AddGroup.class, EditGroup.class}) private Long userId; /** * 排序号 */ - @ApiModelProperty("排序号") @NotNull(message = "排序号不能为空", groups = {AddGroup.class, EditGroup.class}) private Integer orderNum; /** * key键 */ - @ApiModelProperty("key键") @NotBlank(message = "key键不能为空", groups = {AddGroup.class, EditGroup.class}) private String testKey; /** * 值 */ - @ApiModelProperty("值") @NotBlank(message = "值不能为空", groups = {AddGroup.class, EditGroup.class}) private String value; diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestDemoImportVo.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestDemoImportVo.java index 7185514fd..8f417fb2e 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestDemoImportVo.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestDemoImportVo.java @@ -1,8 +1,6 @@ package com.ruoyi.demo.domain.bo; import com.alibaba.excel.annotation.ExcelProperty; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotBlank; @@ -15,13 +13,11 @@ import javax.validation.constraints.NotNull; * @date 2021-07-26 */ @Data -@ApiModel("测试单表业务对象") public class TestDemoImportVo { /** * 部门id */ - @ApiModelProperty("部门id") @NotNull(message = "部门id不能为空") @ExcelProperty(value = "部门id") private Long deptId; @@ -29,7 +25,6 @@ public class TestDemoImportVo { /** * 用户id */ - @ApiModelProperty("用户id") @NotNull(message = "用户id不能为空") @ExcelProperty(value = "用户id") private Long userId; @@ -37,7 +32,6 @@ public class TestDemoImportVo { /** * 排序号 */ - @ApiModelProperty("排序号") @NotNull(message = "排序号不能为空") @ExcelProperty(value = "排序号") private Long orderNum; @@ -45,7 +39,6 @@ public class TestDemoImportVo { /** * key键 */ - @ApiModelProperty("key键") @NotBlank(message = "key键不能为空") @ExcelProperty(value = "key键") private String testKey; @@ -53,7 +46,6 @@ public class TestDemoImportVo { /** * 值 */ - @ApiModelProperty("值") @NotBlank(message = "值不能为空") @ExcelProperty(value = "值") private String value; diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestTreeBo.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestTreeBo.java index 211a79f14..a51b3fe37 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestTreeBo.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/bo/TestTreeBo.java @@ -3,8 +3,6 @@ package com.ruoyi.demo.domain.bo; import com.ruoyi.common.core.domain.TreeEntity; import com.ruoyi.common.core.validate.AddGroup; import com.ruoyi.common.core.validate.EditGroup; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; @@ -20,34 +18,29 @@ import javax.validation.constraints.NotNull; @Data @EqualsAndHashCode(callSuper = true) -@ApiModel("测试树表业务对象") public class TestTreeBo extends TreeEntity { /** * 主键 */ - @ApiModelProperty("主键") @NotNull(message = "主键不能为空", groups = {EditGroup.class}) private Long id; /** * 部门id */ - @ApiModelProperty("部门id") @NotNull(message = "部门id不能为空", groups = {AddGroup.class, EditGroup.class}) private Long deptId; /** * 用户id */ - @ApiModelProperty("用户id") @NotNull(message = "用户id不能为空", groups = {AddGroup.class, EditGroup.class}) private Long userId; /** * 树节点名 */ - @ApiModelProperty("树节点名") @NotBlank(message = "树节点名不能为空", groups = {AddGroup.class, EditGroup.class}) private String treeName; diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/vo/TestDemoVo.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/vo/TestDemoVo.java index 1e896500d..c4a46edf3 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/vo/TestDemoVo.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/vo/TestDemoVo.java @@ -2,8 +2,6 @@ package com.ruoyi.demo.domain.vo; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.util.Date; @@ -16,7 +14,6 @@ import java.util.Date; * @date 2021-07-26 */ @Data -@ApiModel("测试单表视图对象") @ExcelIgnoreUnannotated public class TestDemoVo { @@ -26,70 +23,60 @@ public class TestDemoVo { * 主键 */ @ExcelProperty(value = "主键") - @ApiModelProperty("主键") private Long id; /** * 部门id */ @ExcelProperty(value = "部门id") - @ApiModelProperty("部门id") private Long deptId; /** * 用户id */ @ExcelProperty(value = "用户id") - @ApiModelProperty("用户id") private Long userId; /** * 排序号 */ @ExcelProperty(value = "排序号") - @ApiModelProperty("排序号") private Integer orderNum; /** * key键 */ @ExcelProperty(value = "key键") - @ApiModelProperty("key键") private String testKey; /** * 值 */ @ExcelProperty(value = "值") - @ApiModelProperty("值") private String value; /** * 创建时间 */ @ExcelProperty(value = "创建时间") - @ApiModelProperty("创建时间") private Date createTime; /** * 创建人 */ @ExcelProperty(value = "创建人") - @ApiModelProperty("创建人") private String createBy; /** * 更新时间 */ @ExcelProperty(value = "更新时间") - @ApiModelProperty("更新时间") private Date updateTime; /** * 更新人 */ @ExcelProperty(value = "更新人") - @ApiModelProperty("更新人") private String updateBy; diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/vo/TestTreeVo.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/vo/TestTreeVo.java index 309a0ae4e..6836c06bb 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/vo/TestTreeVo.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/vo/TestTreeVo.java @@ -2,8 +2,6 @@ package com.ruoyi.demo.domain.vo; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.util.Date; @@ -16,7 +14,6 @@ import java.util.Date; * @date 2021-07-26 */ @Data -@ApiModel("测试树表视图对象") @ExcelIgnoreUnannotated public class TestTreeVo { @@ -25,42 +22,36 @@ public class TestTreeVo { /** * 主键 */ - @ApiModelProperty("主键") private Long id; /** * 父id */ @ExcelProperty(value = "父id") - @ApiModelProperty("父id") private Long parentId; /** * 部门id */ @ExcelProperty(value = "部门id") - @ApiModelProperty("部门id") private Long deptId; /** * 用户id */ @ExcelProperty(value = "用户id") - @ApiModelProperty("用户id") private Long userId; /** * 树节点名 */ @ExcelProperty(value = "树节点名") - @ApiModelProperty("树节点名") private String treeName; /** * 创建时间 */ @ExcelProperty(value = "创建时间") - @ApiModelProperty("创建时间") private Date createTime; diff --git a/ruoyi-extend/pom.xml b/ruoyi-extend/pom.xml index 2be8693e4..8b0e2fb67 100644 --- a/ruoyi-extend/pom.xml +++ b/ruoyi-extend/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.2.0 + 4.4.0 4.0.0 ruoyi-extend diff --git a/ruoyi-extend/ruoyi-monitor-admin/Dockerfile b/ruoyi-extend/ruoyi-monitor-admin/Dockerfile index b506a2ddd..02b741f48 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-monitor-admin/pom.xml b/ruoyi-extend/ruoyi-monitor-admin/pom.xml index e42e8e0f4..687d95853 100644 --- a/ruoyi-extend/ruoyi-monitor-admin/pom.xml +++ b/ruoyi-extend/ruoyi-monitor-admin/pom.xml @@ -5,7 +5,7 @@ ruoyi-extend com.ruoyi - 4.2.0 + 4.4.0 4.0.0 jar @@ -59,25 +59,6 @@ - - com.spotify - docker-maven-plugin - ${docker.plugin.version} - - ${docker.namespace}/${project.artifactId}:${project.version} - ${project.basedir} - ${docker.registry.host} - ${docker.registry.url} - ${docker.registry.url} - - - / - ${project.build.directory} - ${project.build.finalName}.jar - - - - diff --git a/ruoyi-extend/ruoyi-monitor-admin/src/main/java/com/ruoyi/monitor/admin/config/SecurityConfig.java b/ruoyi-extend/ruoyi-monitor-admin/src/main/java/com/ruoyi/monitor/admin/config/SecurityConfig.java index 2b04f712f..627fa835a 100644 --- a/ruoyi-extend/ruoyi-monitor-admin/src/main/java/com/ruoyi/monitor/admin/config/SecurityConfig.java +++ b/ruoyi-extend/ruoyi-monitor-admin/src/main/java/com/ruoyi/monitor/admin/config/SecurityConfig.java @@ -1,10 +1,10 @@ package com.ruoyi.monitor.admin.config; import de.codecentric.boot.admin.server.config.AdminServerProperties; -import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Bean; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; /** @@ -12,9 +12,8 @@ import org.springframework.security.web.authentication.SavedRequestAwareAuthenti * * @author Lion Li */ -@Configuration @EnableWebSecurity -public class SecurityConfig extends WebSecurityConfigurerAdapter { +public class SecurityConfig { private final String adminContextPath; @@ -22,27 +21,30 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { this.adminContextPath = adminServerProperties.getContextPath(); } - @Override - protected void configure(HttpSecurity httpSecurity) throws Exception { + @Bean + public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception { SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler(); successHandler.setTargetUrlParameter("redirectTo"); successHandler.setDefaultTargetUrl(adminContextPath + "/"); - // admin监控 用户鉴权 - httpSecurity.authorizeRequests() - //授予对所有静态资产和登录页面的公共访问权限。 - .antMatchers(adminContextPath + "/assets/**").permitAll() - .antMatchers(adminContextPath + "/login").permitAll() - .antMatchers("/actuator").permitAll() - .antMatchers("/actuator/**").permitAll() - //必须对每个其他请求进行身份验证 - .anyRequest().authenticated().and() - //配置登录和注销 - .formLogin().loginPage(adminContextPath + "/login") - .successHandler(successHandler).and() - .logout().logoutUrl(adminContextPath + "/logout").and() - //启用HTTP-Basic支持。这是Spring Boot Admin Client注册所必需的 - .httpBasic().and().csrf().disable() - .headers().frameOptions().disable(); + + return httpSecurity + .headers().frameOptions().disable() + .and().authorizeRequests() + .antMatchers(adminContextPath + "/assets/**" + , adminContextPath + "/login" + , "/actuator" + , "/actuator/**" + ).permitAll() + .anyRequest().authenticated() + .and() + .formLogin().loginPage(adminContextPath + "/login") + .successHandler(successHandler).and() + .logout().logoutUrl(adminContextPath + "/logout") + .and() + .httpBasic().and() + .csrf() + .disable() + .build(); } } diff --git a/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application-dev.yml b/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application-dev.yml deleted file mode 100644 index 0b10bbd76..000000000 --- a/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application-dev.yml +++ /dev/null @@ -1,14 +0,0 @@ ---- # 监控配置 -spring: - boot: - admin: - # Spring Boot Admin Client 客户端的相关配置 - client: - # 增加客户端开关 - enabled: true - # 设置 Spring Boot Admin Server 地址 - url: http://localhost:9090/admin - instance: - service-host-type: IP - username: ruoyi - password: 123456 diff --git a/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application-prod.yml b/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application-prod.yml deleted file mode 100644 index 2e020390d..000000000 --- a/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application-prod.yml +++ /dev/null @@ -1,14 +0,0 @@ ---- # 监控配置 -spring: - boot: - admin: - # Spring Boot Admin Client 客户端的相关配置 - client: - # 增加客户端开关 - enabled: true - # 设置 Spring Boot Admin Server 地址 - url: http://172.30.0.90:9090/admin - instance: - service-host-type: IP - username: ruoyi - password: 123456 diff --git a/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application.yml b/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application.yml index bf0db5620..22ef1abfc 100644 --- a/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application.yml +++ b/ruoyi-extend/ruoyi-monitor-admin/src/main/resources/application.yml @@ -14,18 +14,29 @@ spring: password: 123456 boot: admin: + ui: + title: RuoYi-Vue-Plus服务监控中心 context-path: /admin --- # Actuator 监控端点的配置项 management: endpoints: web: - # Actuator 提供的 API 接口的根目录。默认为 /actuator - base-path: /actuator exposure: - # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。 - # 生产环境不建议放开所有 根据项目需求放开即可 - include: @endpoints.include@ + include: '*' endpoint: + health: + show-details: ALWAYS logfile: external-file: ./logs/ruoyi-monitor-admin.log + +--- # 监控配置 +spring.boot.admin.client: + # 增加客户端开关 + enabled: true + # 设置 Spring Boot Admin Server 地址 + url: http://localhost:9090/admin + instance: + service-host-type: IP + username: ruoyi + password: 123456 diff --git a/ruoyi-extend/ruoyi-xxl-job-admin/Dockerfile b/ruoyi-extend/ruoyi-xxl-job-admin/Dockerfile index f7221bdf0..bd61580a6 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 b9954beac..9305051d9 100644 --- a/ruoyi-extend/ruoyi-xxl-job-admin/pom.xml +++ b/ruoyi-extend/ruoyi-xxl-job-admin/pom.xml @@ -4,7 +4,7 @@ ruoyi-extend com.ruoyi - 4.2.0 + 4.4.0 ruoyi-xxl-job-admin jar @@ -64,8 +64,8 @@ - mysql - mysql-connector-java + com.mysql + mysql-connector-j @@ -96,27 +96,6 @@ - - - com.spotify - docker-maven-plugin - ${docker.plugin.version} - - - ${docker.namespace}/${project.artifactId}:${project.version} - ${project.basedir} - ${docker.registry.host} - ${docker.registry.url} - ${docker.registry.url} - - - / - ${project.build.directory} - ${project.build.finalName}.jar - - - - diff --git a/ruoyi-extend/ruoyi-xxl-job-admin/src/main/java/com/xxl/job/admin/core/util/JacksonUtil.java b/ruoyi-extend/ruoyi-xxl-job-admin/src/main/java/com/xxl/job/admin/core/util/JacksonUtil.java index a75595683..0312b7479 100644 --- a/ruoyi-extend/ruoyi-xxl-job-admin/src/main/java/com/xxl/job/admin/core/util/JacksonUtil.java +++ b/ruoyi-extend/ruoyi-xxl-job-admin/src/main/java/com/xxl/job/admin/core/util/JacksonUtil.java @@ -21,10 +21,10 @@ import java.io.IOException; public class JacksonUtil { private static Logger logger = LoggerFactory.getLogger(JacksonUtil.class); - private final static ObjectMapper objectMapper = new ObjectMapper(); + private final static ObjectMapper OBJECT_MAPPER = new ObjectMapper(); public static ObjectMapper getInstance() { - return objectMapper; + return OBJECT_MAPPER; } /** diff --git a/ruoyi-extend/ruoyi-xxl-job-admin/src/main/resources/application-dev.yml b/ruoyi-extend/ruoyi-xxl-job-admin/src/main/resources/application-dev.yml index 09ed519fa..fa04b5686 100644 --- a/ruoyi-extend/ruoyi-xxl-job-admin/src/main/resources/application-dev.yml +++ b/ruoyi-extend/ruoyi-xxl-job-admin/src/main/resources/application-dev.yml @@ -1,17 +1,13 @@ --- # 监控配置 -spring: - boot: - admin: - # Spring Boot Admin Client 客户端的相关配置 - client: - # 增加客户端开关 - enabled: true - # 设置 Spring Boot Admin Server 地址 - url: http://localhost:9090/admin - instance: - service-host-type: IP - username: ruoyi - password: 123456 +spring.boot.admin.client: + # 增加客户端开关 + enabled: true + # 设置 Spring Boot Admin Server 地址 + url: http://localhost:9090/admin + instance: + service-host-type: IP + username: ruoyi + password: 123456 --- # 数据库配置 spring: diff --git a/ruoyi-extend/ruoyi-xxl-job-admin/src/main/resources/application-prod.yml b/ruoyi-extend/ruoyi-xxl-job-admin/src/main/resources/application-prod.yml index 401f60af9..d4193d0be 100644 --- a/ruoyi-extend/ruoyi-xxl-job-admin/src/main/resources/application-prod.yml +++ b/ruoyi-extend/ruoyi-xxl-job-admin/src/main/resources/application-prod.yml @@ -1,24 +1,20 @@ --- # 监控配置 -spring: - boot: - admin: - # Spring Boot Admin Client 客户端的相关配置 - client: - # 增加客户端开关 - enabled: true - # 设置 Spring Boot Admin Server 地址 - url: http://172.30.0.90:9090/admin - instance: - service-host-type: IP - username: ruoyi - password: 123456 +spring.boot.admin.client: + # 增加客户端开关 + enabled: true + # 设置 Spring Boot Admin Server 地址 + url: http://localhost:9090/admin + instance: + service-host-type: IP + username: ruoyi + password: 123456 --- # 数据库配置 spring: datasource: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://172.30.0.36:3306/ry-vue?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai + url: jdbc:mysql://127.0.0.1:3306/ry-vue?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai username: root password: root hikari: diff --git a/ruoyi-extend/ruoyi-xxl-job-admin/src/main/resources/application.yml b/ruoyi-extend/ruoyi-xxl-job-admin/src/main/resources/application.yml index 202272087..d4fda939a 100644 --- a/ruoyi-extend/ruoyi-xxl-job-admin/src/main/resources/application.yml +++ b/ruoyi-extend/ruoyi-xxl-job-admin/src/main/resources/application.yml @@ -37,13 +37,11 @@ management: enabled: false endpoints: web: - # Actuator 提供的 API 接口的根目录。默认为 /actuator - base-path: /actuator exposure: - # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。 - # 生产环境不建议放开所有 根据项目需求放开即可 - include: @endpoints.include@ + include: '*' endpoint: + health: + show-details: ALWAYS logfile: external-file: ./logs/ruoyi-xxl-job-admin.log diff --git a/ruoyi-framework/pom.xml b/ruoyi-framework/pom.xml index c6837bec0..52e1b0651 100644 --- a/ruoyi-framework/pom.xml +++ b/ruoyi-framework/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.2.0 + 4.4.0 4.0.0 @@ -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 551a1ece3..3b6a858a4 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 @@ -1,5 +1,7 @@ package com.ruoyi.framework.aspectj; +import cn.hutool.core.lang.Dict; +import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ObjectUtil; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.core.domain.dto.OperLogDTO; @@ -19,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; @@ -36,6 +37,11 @@ import java.util.Map; @Component public class LogAspect { + /** + * 排除敏感属性字段 + */ + public static final String[] EXCLUDE_PROPERTIES = { "password", "oldPassword", "newPassword", "confirmPassword" }; + /** * 处理完请求后执行 * @@ -66,7 +72,7 @@ public class LogAspect { // 请求的地址 String ip = ServletUtils.getClientIP(); operLog.setOperIp(ip); - operLog.setOperUrl(ServletUtils.getRequest().getRequestURI()); + operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255)); operLog.setOperName(LoginHelper.getUsername()); if (e != null) { @@ -85,7 +91,6 @@ public class LogAspect { SpringUtils.getBean(OperLogService.class).recordOper(operLog); } catch (Exception exp) { // 记录本地异常日志 - log.error("==前置通知异常=="); log.error("异常信息:{}", exp.getMessage()); exp.printStackTrace(); } @@ -128,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)); } } @@ -142,7 +148,13 @@ public class LogAspect { for (Object o : paramsArray) { if (ObjectUtil.isNotNull(o) && !isFilterObject(o)) { try { - params.append(JsonUtils.toJsonString(o)).append(" "); + String str = JsonUtils.toJsonString(o); + Dict dict = JsonUtils.parseMap(str); + if (MapUtil.isNotEmpty(dict)) { + MapUtil.removeAny(dict, EXCLUDE_PROPERTIES); + str = JsonUtils.toJsonString(dict); + } + params.append(str).append(" "); } catch (Exception e) { e.printStackTrace(); } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RepeatSubmitAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RepeatSubmitAspect.java index b77acb40e..7c2fa2a41 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RepeatSubmitAspect.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RepeatSubmitAspect.java @@ -4,7 +4,7 @@ import cn.dev33.satoken.SaManager; import cn.hutool.core.util.ObjectUtil; import cn.hutool.crypto.SecureUtil; import com.ruoyi.common.annotation.RepeatSubmit; -import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.JsonUtils; @@ -63,7 +63,7 @@ public class RepeatSubmitAspect { submitKey = SecureUtil.md5(submitKey + ":" + nowParams); // 唯一标识(指定key + url + 消息头) - String cacheRepeatKey = Constants.REPEAT_SUBMIT_KEY + url + submitKey; + String cacheRepeatKey = CacheConstants.REPEAT_SUBMIT_KEY + url + submitKey; String key = RedisUtils.getCacheObject(cacheRepeatKey); if (key == null) { RedisUtils.setCacheObject(cacheRepeatKey, "", Duration.ofMillis(interval)); @@ -85,12 +85,16 @@ public class RepeatSubmitAspect { @AfterReturning(pointcut = "@annotation(repeatSubmit)", returning = "jsonResult") public void doAfterReturning(JoinPoint joinPoint, RepeatSubmit repeatSubmit, Object jsonResult) { if (jsonResult instanceof R) { - R r = (R) jsonResult; - if (r.getCode() == R.SUCCESS) { - return; + try { + R r = (R) jsonResult; + // 成功则不删除redis数据 保证在有效时间内无法重复提交 + if (r.getCode() == R.SUCCESS) { + return; + } + RedisUtils.deleteObject(KEY_CACHE.get()); + } finally { + KEY_CACHE.remove(); } - RedisUtils.deleteObject(KEY_CACHE.get()); - KEY_CACHE.remove(); } } 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 6f7a82ecc..000000000 --- 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/RedisConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java index 38a871895..9a7938a4b 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java @@ -3,11 +3,10 @@ package com.ruoyi.framework.config; import cn.hutool.core.util.ObjectUtil; import com.fasterxml.jackson.databind.ObjectMapper; import com.ruoyi.framework.config.properties.RedissonProperties; +import com.ruoyi.framework.handler.KeyPrefixHandler; +import com.ruoyi.framework.manager.PlusSpringCacheManager; import lombok.extern.slf4j.Slf4j; -import org.redisson.api.RedissonClient; import org.redisson.codec.JsonJacksonCodec; -import org.redisson.spring.cache.CacheConfig; -import org.redisson.spring.cache.RedissonSpringCacheManager; import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.context.properties.EnableConfigurationProperties; @@ -17,10 +16,6 @@ import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - /** * redis配置 * @@ -48,6 +43,8 @@ public class RedisConfig extends CachingConfigurerSupport { if (ObjectUtil.isNotNull(singleServerConfig)) { // 使用单机模式 config.useSingleServer() + //设置redis key前缀 + .setNameMapper(new KeyPrefixHandler(redissonProperties.getKeyPrefix())) .setTimeout(singleServerConfig.getTimeout()) .setClientName(singleServerConfig.getClientName()) .setIdleConnectionTimeout(singleServerConfig.getIdleConnectionTimeout()) @@ -59,6 +56,8 @@ public class RedisConfig extends CachingConfigurerSupport { RedissonProperties.ClusterServersConfig clusterServersConfig = redissonProperties.getClusterServersConfig(); if (ObjectUtil.isNotNull(clusterServersConfig)) { config.useClusterServers() + //设置redis key前缀 + .setNameMapper(new KeyPrefixHandler(redissonProperties.getKeyPrefix())) .setTimeout(clusterServersConfig.getTimeout()) .setClientName(clusterServersConfig.getClientName()) .setIdleConnectionTimeout(clusterServersConfig.getIdleConnectionTimeout()) @@ -75,18 +74,11 @@ public class RedisConfig extends CachingConfigurerSupport { } /** - * 整合spring-cache + * 自定义缓存管理器 整合spring-cache */ @Bean - public CacheManager cacheManager(RedissonClient redissonClient) { - List cacheGroup = redissonProperties.getCacheGroup(); - Map config = new HashMap<>(); - for (RedissonProperties.CacheGroup group : cacheGroup) { - CacheConfig cacheConfig = new CacheConfig(group.getTtl(), group.getMaxIdleTime()); - cacheConfig.setMaxSize(group.getMaxSize()); - config.put(group.getGroupId(), cacheConfig); - } - return new RedissonSpringCacheManager(redissonClient, config, new JsonJacksonCodec(objectMapper)); + public CacheManager cacheManager() { + return new PlusSpringCacheManager(); } /** 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 f43ecab7d..ea83338ba 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 a5be2678e..291228667 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 @@ -1,13 +1,10 @@ package com.ruoyi.framework.config; -import cn.dev33.satoken.interceptor.SaAnnotationInterceptor; -import cn.dev33.satoken.interceptor.SaRouteInterceptor; +import cn.dev33.satoken.interceptor.SaInterceptor; 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,15 +31,11 @@ public class SaTokenConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { // 注册路由拦截器,自定义验证规则 - registry.addInterceptor(new SaRouteInterceptor((request, response, handler) -> { - ExcludeUrlProperties excludeUrlProperties = SpringUtils.getBean(ExcludeUrlProperties.class); + registry.addInterceptor(new SaInterceptor(handler -> { // 登录验证 -- 排除多个路径 SaRouter // 获取所有的 .match("/**") - // 排除下不需要拦截的 - .notMatch(securityProperties.getExcludes()) - .notMatch(excludeUrlProperties.getExcludes()) // 对未排除的路径进行检查 .check(() -> { // 检查是否登录 是否有token @@ -55,8 +48,9 @@ public class SaTokenConfig implements WebMvcConfigurer { // } }); - })).addPathPatterns("/**"); - registry.addInterceptor(new SaAnnotationInterceptor()).addPathPatterns("/**"); + })).addPathPatterns("/**") + // 排除不需要拦截的路径 + .excludePathPatterns(securityProperties.getExcludes()); } @Bean diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SwaggerConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SwaggerConfig.java index 2424981c1..7107661cb 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SwaggerConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SwaggerConfig.java @@ -1,33 +1,28 @@ package com.ruoyi.framework.config; -import cn.dev33.satoken.config.SaTokenConfig; -import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j; -import com.github.xiaoymin.knife4j.spring.extension.OpenApiExtensionResolver; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.spring.SpringUtils; import com.ruoyi.framework.config.properties.SwaggerProperties; -import io.swagger.models.auth.In; +import com.ruoyi.framework.handler.OpenApiHandler; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.Paths; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.security.SecurityRequirement; import lombok.RequiredArgsConstructor; -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springdoc.core.*; +import org.springdoc.core.customizers.OpenApiBuilderCustomizer; +import org.springdoc.core.customizers.OpenApiCustomiser; +import org.springdoc.core.customizers.ServerBaseUrlCustomizer; +import org.springdoc.core.providers.JavadocProvider; +import org.springframework.boot.autoconfigure.AutoConfigureBefore; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.web.ServerProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.util.ReflectionUtils; -import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping; -import springfox.documentation.builders.ApiInfoBuilder; -import springfox.documentation.builders.PathSelectors; -import springfox.documentation.builders.RequestHandlerSelectors; -import springfox.documentation.service.*; -import springfox.documentation.spi.DocumentationType; -import springfox.documentation.spi.service.contexts.SecurityContext; -import springfox.documentation.spring.web.plugins.Docket; -import springfox.documentation.spring.web.plugins.WebFluxRequestHandlerProvider; -import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider; -import javax.annotation.PostConstruct; -import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; +import java.util.Optional; /** * Swagger 文档配置 @@ -36,125 +31,89 @@ import java.util.List; */ @RequiredArgsConstructor @Configuration -@EnableKnife4j +@AutoConfigureBefore(SpringDocConfiguration.class) +@ConditionalOnProperty(name = "swagger.enabled", havingValue = "true", matchIfMissing = true) public class SwaggerConfig { private final SwaggerProperties swaggerProperties; - private final SaTokenConfig saTokenConfig; - private final OpenApiExtensionResolver openApiExtensionResolver; + private final ServerProperties serverProperties; + + @Bean + @ConditionalOnMissingBean(OpenAPI.class) + public OpenAPI openApi() { + OpenAPI openApi = new OpenAPI(); + // 文档基本信息 + SwaggerProperties.InfoProperties infoProperties = swaggerProperties.getInfo(); + Info info = convertInfo(infoProperties); + openApi.info(info); + // 扩展文档信息 + openApi.externalDocs(swaggerProperties.getExternalDocs()); + openApi.tags(swaggerProperties.getTags()); + openApi.paths(swaggerProperties.getPaths()); + openApi.components(swaggerProperties.getComponents()); + List list = new ArrayList<>(); + list.add(new SecurityRequirement().addList("apikey")); + openApi.security(list); + + return openApi; + } + + private Info convertInfo(SwaggerProperties.InfoProperties infoProperties) { + Info info = new Info(); + info.setTitle(infoProperties.getTitle()); + info.setDescription(infoProperties.getDescription()); + info.setContact(infoProperties.getContact()); + info.setLicense(infoProperties.getLicense()); + info.setVersion(infoProperties.getVersion()); + return info; + } /** - * 用于适配springboot 2.6 + * 自定义 openapi 处理器 */ @Bean - @SuppressWarnings("all") - public BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() { - return new BeanPostProcessor() { - @Override - public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) { - customizeSpringfoxHandlerMappings(getHandlerMappings(bean)); - } - return bean; - } + public OpenAPIService openApiBuilder(Optional openAPI, + SecurityService securityParser, + SpringDocConfigProperties springDocConfigProperties, PropertyResolverUtils propertyResolverUtils, + Optional> openApiBuilderCustomisers, + Optional> serverBaseUrlCustomisers, Optional javadocProvider) { + return new OpenApiHandler(openAPI, securityParser, springDocConfigProperties, propertyResolverUtils, openApiBuilderCustomisers, serverBaseUrlCustomisers, javadocProvider); + } - private void customizeSpringfoxHandlerMappings(List mappings) { - mappings.removeIf(mapping -> mapping.getPatternParser() != null); - } - - private List getHandlerMappings(Object bean) { - try { - Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings"); - field.setAccessible(true); - return (List) field.get(bean); - } catch (IllegalArgumentException | IllegalAccessException e) { - throw new IllegalStateException(e); - } + /** + * 对已经生成好的 OpenApi 进行自定义操作 + */ + @Bean + public OpenApiCustomiser openApiCustomiser() { + String contextPath = serverProperties.getServlet().getContextPath(); + String finalContextPath; + if (StringUtils.isBlank(contextPath) || "/".equals(contextPath)) { + finalContextPath = ""; + } else { + finalContextPath = contextPath; + } + // 对所有路径增加前置上下文路径 + return openApi -> { + Paths oldPaths = openApi.getPaths(); + if (oldPaths instanceof PlusPaths) { + return; } + PlusPaths newPaths = new PlusPaths(); + oldPaths.forEach((k,v) -> newPaths.addPathItem(finalContextPath + k, v)); + openApi.setPaths(newPaths); }; } /** - * 创建API + * 单独使用一个类便于判断 解决springdoc路径拼接重复问题 + * + * @author Lion Li */ - @PostConstruct - public void createRestApi() { - for (SwaggerProperties.Groups group : swaggerProperties.getGroups()) { - String basePackage = group.getBasePackage(); - Docket docket = new Docket(DocumentationType.OAS_30) - .enable(swaggerProperties.getEnabled()) - // 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息) - .apiInfo(apiInfo()) - // 设置哪些接口暴露给Swagger展示 - .select() - // 扫描所有有注解的api,用这种方式更灵活 - //.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) - // 扫描指定包中的swagger注解 - .apis(RequestHandlerSelectors.basePackage(basePackage)) - // 扫描所有 .apis(RequestHandlerSelectors.any()) - .paths(PathSelectors.any()) - .build() - .groupName(group.getName()) - // 设置安全模式,swagger可以设置访问token - .securitySchemes(securitySchemes()) - .securityContexts(securityContexts()) - .extensions(openApiExtensionResolver.buildExtensions(group.getName())) - .pathMapping(swaggerProperties.getPathMapping()); - String beanName = StringUtils.substringAfterLast(basePackage, ".") + "Docket"; - SpringUtils.registerBean(beanName, docket); + static class PlusPaths extends Paths { + + public PlusPaths() { + super(); } } - /** - * 安全模式,这里指定token通过Authorization头请求头传递 - */ - private List securitySchemes() { - List apiKeyList = new ArrayList<>(); - String header = saTokenConfig.getTokenName(); - apiKeyList.add(new ApiKey(header, header, In.HEADER.toValue())); - return apiKeyList; - } - - /** - * 安全上下文 - */ - private List securityContexts() { - List securityContexts = new ArrayList<>(); - securityContexts.add( - SecurityContext.builder() - .securityReferences(defaultAuth()) - .operationSelector(o -> o.requestMappingPattern().matches("/.*")) - .build()); - return securityContexts; - } - - /** - * 默认的安全上引用 - */ - private List defaultAuth() { - AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything"); - AuthorizationScope[] authorizationScopes = new AuthorizationScope[1]; - authorizationScopes[0] = authorizationScope; - List securityReferences = new ArrayList<>(); - securityReferences.add(new SecurityReference(saTokenConfig.getTokenName(), authorizationScopes)); - return securityReferences; - } - - /** - * 添加摘要信息 - */ - private ApiInfo apiInfo() { - // 用ApiInfoBuilder进行定制 - SwaggerProperties.Contact contact = swaggerProperties.getContact(); - return new ApiInfoBuilder() - // 设置标题 - .title(swaggerProperties.getTitle()) - // 描述 - .description(swaggerProperties.getDescription()) - // 作者信息 - .contact(new Contact(contact.getName(), contact.getUrl(), contact.getEmail())) - // 版本 - .version(swaggerProperties.getVersion()) - .build(); - } } 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 5ae55add2..000000000 --- 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 b4e3eae6d..000000000 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/ExcludeUrlProperties.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.ruoyi.framework.config.properties; - -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 java.util.*; -import java.util.regex.Pattern; - -/** - * 设置注解允许匿名访问的url - * - * @author Lion Li - */ -@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.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.getPatternsCondition().getPatterns(); - patterns.forEach(url -> { - excludes.add(ReUtil.replaceAll(url, PATTERN, asterisk)); - }); - }); - - // 获取类上边的注解, 替代path variable 为 * - Anonymous controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Anonymous.class); - Optional.ofNullable(controller).ifPresent(anonymous -> { - Set patterns = info.getPatternsCondition().getPatterns(); - patterns.forEach(url -> { - excludes.add(ReUtil.replaceAll(url, PATTERN, asterisk)); - }); - }); - }); - } - -} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/RedissonProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/RedissonProperties.java index cd320eb50..b0bf285f3 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/RedissonProperties.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/RedissonProperties.java @@ -7,8 +7,6 @@ import org.redisson.config.SubscriptionMode; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; -import java.util.List; - /** * Redisson 配置属性 * @@ -19,6 +17,11 @@ import java.util.List; @ConfigurationProperties(prefix = "redisson") public class RedissonProperties { + /** + * redis缓存key前缀 + */ + private String keyPrefix; + /** * 线程池数量,默认值 = 当前处理核数量 * 2 */ @@ -39,11 +42,6 @@ public class RedissonProperties { */ private ClusterServersConfig clusterServersConfig; - /** - * 缓存组 - */ - private List cacheGroup; - @Data @NoArgsConstructor public static class SingleServerConfig { @@ -136,30 +134,4 @@ public class RedissonProperties { } - @Data - @NoArgsConstructor - public static class CacheGroup { - - /** - * 组id - */ - private String groupId; - - /** - * 组过期时间 - */ - private long ttl; - - /** - * 组最大空闲时间 - */ - private long maxIdleTime; - - /** - * 组最大长度 - */ - private int maxSize; - - } - } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/SwaggerProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/SwaggerProperties.java index 7293e1e90..736d70a45 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/SwaggerProperties.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/SwaggerProperties.java @@ -1,8 +1,14 @@ package com.ruoyi.framework.config.properties; +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.ExternalDocumentation; +import io.swagger.v3.oas.models.Paths; +import io.swagger.v3.oas.models.info.Contact; +import io.swagger.v3.oas.models.info.License; +import io.swagger.v3.oas.models.tags.Tag; import lombok.Data; -import lombok.NoArgsConstructor; import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.NestedConfigurationProperty; import org.springframework.stereotype.Component; import java.util.List; @@ -18,74 +24,77 @@ import java.util.List; public class SwaggerProperties { /** - * 文档开关 + * 是否开启 openApi 文档 */ - private Boolean enabled; + private Boolean enabled = true; /** - * 设置请求的统一前缀 + * 文档基本信息 */ - private String pathMapping; + @NestedConfigurationProperty + private InfoProperties info = new InfoProperties(); /** - * 标头 + * 扩展文档地址 */ - private String title; + @NestedConfigurationProperty + private ExternalDocumentation externalDocs; /** - * 描述 + * 标签 */ - private String description; + private List tags = null; /** - * 项目版本 + * 路径 */ - private String version; + @NestedConfigurationProperty + private Paths paths = null; /** - * 联系方式 + * 组件 */ - private Contact contact; + @NestedConfigurationProperty + private Components components = null; /** - * 组配置 + *

+ * 文档的基础属性信息 + *

+ * + * @see io.swagger.v3.oas.models.info.Info + * + * 为了 springboot 自动生产配置提示信息,所以这里复制一个类出来 */ - private List groups; - @Data - @NoArgsConstructor - public static class Contact { + public static class InfoProperties { /** - * 联系人 + * 标题 */ - private String name; + private String title = null; /** - * 联系人url + * 描述 */ - private String url; + private String description = null; /** - * 联系人email + * 联系人信息 */ - private String email; - - } - - @Data - @NoArgsConstructor - public static class Groups { + @NestedConfigurationProperty + private Contact contact = null; /** - * 组名 + * 许可证 */ - private String name; + @NestedConfigurationProperty + private License license = null; /** - * 基础包路径 + * 版本 */ - private String basePackage; + private String version = null; } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/KeyPrefixHandler.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/KeyPrefixHandler.java new file mode 100644 index 000000000..161c271b3 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/KeyPrefixHandler.java @@ -0,0 +1,50 @@ +package com.ruoyi.framework.handler; + +import com.ruoyi.common.utils.StringUtils; +import org.redisson.api.NameMapper; + +/** + * redis缓存key前缀处理 + * + * @author ye + * @date 2022/7/14 17:44 + * @since 4.3.0 + */ +public class KeyPrefixHandler implements NameMapper { + + private final String keyPrefix; + + public KeyPrefixHandler(String keyPrefix) { + //前缀为空 则返回空前缀 + this.keyPrefix = StringUtils.isBlank(keyPrefix) ? "" : keyPrefix + ":"; + } + + /** + * 增加前缀 + */ + @Override + public String map(String name) { + if (StringUtils.isBlank(name)) { + return null; + } + if (StringUtils.isNotBlank(keyPrefix) && !name.startsWith(keyPrefix)) { + return keyPrefix + name; + } + return name; + } + + /** + * 去除前缀 + */ + @Override + public String unmap(String name) { + if (StringUtils.isBlank(name)) { + return null; + } + if (StringUtils.isNotBlank(keyPrefix) && name.startsWith(keyPrefix)) { + return name.substring(keyPrefix.length()); + } + return name; + } + +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/OpenApiHandler.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/OpenApiHandler.java new file mode 100644 index 000000000..608cae5de --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/OpenApiHandler.java @@ -0,0 +1,272 @@ +package com.ruoyi.framework.handler; + +import cn.hutool.core.io.IoUtil; +import io.swagger.v3.core.jackson.TypeNameResolver; +import io.swagger.v3.core.util.AnnotationsUtils; +import io.swagger.v3.oas.annotations.tags.Tags; +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.Paths; +import io.swagger.v3.oas.models.tags.Tag; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springdoc.core.OpenAPIService; +import org.springdoc.core.PropertyResolverUtils; +import org.springdoc.core.SecurityService; +import org.springdoc.core.SpringDocConfigProperties; +import org.springdoc.core.customizers.OpenApiBuilderCustomizer; +import org.springdoc.core.customizers.ServerBaseUrlCustomizer; +import org.springdoc.core.providers.JavadocProvider; +import org.springframework.context.ApplicationContext; +import org.springframework.core.annotation.AnnotatedElementUtils; +import org.springframework.util.CollectionUtils; +import org.springframework.web.method.HandlerMethod; + +import java.io.StringReader; +import java.lang.reflect.Method; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * 自定义 openapi 处理器 + * 对源码功能进行修改 增强使用 + */ +@SuppressWarnings("all") +public class OpenApiHandler extends OpenAPIService { + + /** + * The constant LOGGER. + */ + private static final Logger LOGGER = LoggerFactory.getLogger(OpenAPIService.class); + + /** + * The Context. + */ + private ApplicationContext context; + + /** + * The Security parser. + */ + private final SecurityService securityParser; + + /** + * The Mappings map. + */ + private final Map mappingsMap = new HashMap<>(); + + /** + * The Springdoc tags. + */ + private final Map springdocTags = new HashMap<>(); + + /** + * The Open api builder customisers. + */ + private final Optional> openApiBuilderCustomisers; + + /** + * The server base URL customisers. + */ + private final Optional> serverBaseUrlCustomizers; + + /** + * The Spring doc config properties. + */ + private final SpringDocConfigProperties springDocConfigProperties; + + /** + * The Open api. + */ + private OpenAPI openAPI; + + /** + * The Cached open api map. + */ + private final Map cachedOpenAPI = new HashMap<>(); + + /** + * The Is servers present. + */ + private boolean isServersPresent; + + /** + * The Server base url. + */ + private String serverBaseUrl; + + /** + * The Property resolver utils. + */ + private final PropertyResolverUtils propertyResolverUtils; + + /** + * The javadoc provider. + */ + private final Optional javadocProvider; + + /** + * The Basic error controller. + */ + private static Class basicErrorController; + + static { + try { + //spring-boot 2 + basicErrorController = Class.forName("org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController"); + } catch (ClassNotFoundException e) { + //spring-boot 1 + try { + basicErrorController = Class.forName("org.springframework.boot.autoconfigure.web.BasicErrorController"); + } catch (ClassNotFoundException classNotFoundException) { + //Basic error controller class not found + LOGGER.trace(classNotFoundException.getMessage()); + } + } + } + + /** + * Instantiates a new Open api builder. + * + * @param openAPI the open api + * @param securityParser the security parser + * @param springDocConfigProperties the spring doc config properties + * @param propertyResolverUtils the property resolver utils + * @param openApiBuilderCustomizers the open api builder customisers + * @param serverBaseUrlCustomizers the server base url customizers + * @param javadocProvider the javadoc provider + */ + public OpenApiHandler(Optional openAPI, SecurityService securityParser, + SpringDocConfigProperties springDocConfigProperties, PropertyResolverUtils propertyResolverUtils, + Optional> openApiBuilderCustomizers, + Optional> serverBaseUrlCustomizers, + Optional javadocProvider) { + super(openAPI, securityParser, springDocConfigProperties, propertyResolverUtils, openApiBuilderCustomizers, serverBaseUrlCustomizers, javadocProvider); + if (openAPI.isPresent()) { + this.openAPI = openAPI.get(); + if (this.openAPI.getComponents() == null) + this.openAPI.setComponents(new Components()); + if (this.openAPI.getPaths() == null) + this.openAPI.setPaths(new Paths()); + if (!CollectionUtils.isEmpty(this.openAPI.getServers())) + this.isServersPresent = true; + } + this.propertyResolverUtils = propertyResolverUtils; + this.securityParser = securityParser; + this.springDocConfigProperties = springDocConfigProperties; + this.openApiBuilderCustomisers = openApiBuilderCustomizers; + this.serverBaseUrlCustomizers = serverBaseUrlCustomizers; + this.javadocProvider = javadocProvider; + if (springDocConfigProperties.isUseFqn()) + TypeNameResolver.std.setUseFqn(true); + } + + @Override + public Operation buildTags(HandlerMethod handlerMethod, Operation operation, OpenAPI openAPI, Locale locale) { + + Set tags = new HashSet<>(); + Set tagsStr = new HashSet<>(); + + buildTagsFromMethod(handlerMethod.getMethod(), tags, tagsStr, locale); + buildTagsFromClass(handlerMethod.getBeanType(), tags, tagsStr, locale); + + if (!CollectionUtils.isEmpty(tagsStr)) + tagsStr = tagsStr.stream() + .map(str -> propertyResolverUtils.resolve(str, locale)) + .collect(Collectors.toSet()); + + if (springdocTags.containsKey(handlerMethod)) { + io.swagger.v3.oas.models.tags.Tag tag = springdocTags.get(handlerMethod); + tagsStr.add(tag.getName()); + if (openAPI.getTags() == null || !openAPI.getTags().contains(tag)) { + openAPI.addTagsItem(tag); + } + } + + if (!CollectionUtils.isEmpty(tagsStr)) { + if (CollectionUtils.isEmpty(operation.getTags())) + operation.setTags(new ArrayList<>(tagsStr)); + else { + Set operationTagsSet = new HashSet<>(operation.getTags()); + operationTagsSet.addAll(tagsStr); + operation.getTags().clear(); + operation.getTags().addAll(operationTagsSet); + } + } + + if (isAutoTagClasses(operation)) { + + + if (javadocProvider.isPresent()) { + String description = javadocProvider.get().getClassJavadoc(handlerMethod.getBeanType()); + if (StringUtils.isNotBlank(description)) { + io.swagger.v3.oas.models.tags.Tag tag = new io.swagger.v3.oas.models.tags.Tag(); + + // 自定义部分 修改使用java注释当tag名 + List list = IoUtil.readLines(new StringReader(description), new ArrayList<>()); + // tag.setName(tagAutoName); + tag.setName(list.get(0)); + operation.addTagsItem(list.get(0)); + + tag.setDescription(description); + if (openAPI.getTags() == null || !openAPI.getTags().contains(tag)) { + openAPI.addTagsItem(tag); + } + } + } else { + String tagAutoName = splitCamelCase(handlerMethod.getBeanType().getSimpleName()); + operation.addTagsItem(tagAutoName); + } + } + + if (!CollectionUtils.isEmpty(tags)) { + // Existing tags + List openApiTags = openAPI.getTags(); + if (!CollectionUtils.isEmpty(openApiTags)) + tags.addAll(openApiTags); + openAPI.setTags(new ArrayList<>(tags)); + } + + // Handle SecurityRequirement at operation level + io.swagger.v3.oas.annotations.security.SecurityRequirement[] securityRequirements = securityParser + .getSecurityRequirements(handlerMethod); + if (securityRequirements != null) { + if (securityRequirements.length == 0) + operation.setSecurity(Collections.emptyList()); + else + securityParser.buildSecurityRequirement(securityRequirements, operation); + } + + return operation; + } + + private void buildTagsFromMethod(Method method, Set tags, Set tagsStr, Locale locale) { + // method tags + Set tagsSet = AnnotatedElementUtils + .findAllMergedAnnotations(method, Tags.class); + Set methodTags = tagsSet.stream() + .flatMap(x -> Stream.of(x.value())).collect(Collectors.toSet()); + methodTags.addAll(AnnotatedElementUtils.findAllMergedAnnotations(method, io.swagger.v3.oas.annotations.tags.Tag.class)); + if (!CollectionUtils.isEmpty(methodTags)) { + tagsStr.addAll(methodTags.stream().map(tag -> propertyResolverUtils.resolve(tag.name(), locale)).collect(Collectors.toSet())); + List allTags = new ArrayList<>(methodTags); + addTags(allTags, tags, locale); + } + } + + private void addTags(List sourceTags, Set tags, Locale locale) { + Optional> optionalTagSet = AnnotationsUtils + .getTags(sourceTags.toArray(new io.swagger.v3.oas.annotations.tags.Tag[0]), true); + optionalTagSet.ifPresent(tagsSet -> { + tagsSet.forEach(tag -> { + tag.name(propertyResolverUtils.resolve(tag.getName(), locale)); + tag.description(propertyResolverUtils.resolve(tag.getDescription(), locale)); + if (tags.stream().noneMatch(t -> t.getName().equals(tag.getName()))) + tags.add(tag); + }); + }); + } + +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/PlusDataPermissionHandler.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/PlusDataPermissionHandler.java index 7ecc12a3f..63e777dee 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/PlusDataPermissionHandler.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/handler/PlusDataPermissionHandler.java @@ -1,6 +1,7 @@ package com.ruoyi.framework.handler; import cn.hutool.core.annotation.AnnotationUtil; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ConcurrentHashSet; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ClassUtil; @@ -13,6 +14,7 @@ import com.ruoyi.common.enums.DataScopeType; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.helper.DataPermissionHelper; import com.ruoyi.common.helper.LoginHelper; +import com.ruoyi.common.utils.StreamUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.spring.SpringUtils; import lombok.extern.slf4j.Slf4j; @@ -30,11 +32,9 @@ import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; import java.util.stream.Collectors; /** @@ -104,13 +104,13 @@ public class PlusDataPermissionHandler { * 构造数据过滤sql */ private String buildDataFilter(DataColumn[] dataColumns, boolean isSelect) { - StringBuilder sqlString = new StringBuilder(); // 更新或删除需满足所有条件 String joinStr = isSelect ? " OR " : " AND "; LoginUser user = DataPermissionHelper.getVariable("user"); StandardEvaluationContext context = new StandardEvaluationContext(); context.setBeanResolver(beanResolver); DataPermissionHelper.getContext().forEach(context::setVariable); + Set conditions = new HashSet<>(); for (RoleDTO role : user.getRoles()) { user.setRoleId(role.getRoleId()); // 获取角色权限泛型 @@ -124,26 +124,34 @@ public class PlusDataPermissionHandler { } boolean isSuccess = false; for (DataColumn dataColumn : dataColumns) { + if (dataColumn.key().length != dataColumn.value().length) { + throw new ServiceException("角色数据范围异常 => key与value长度不匹配"); + } // 不包含 key 变量 则不处理 - if (!StringUtils.contains(type.getSqlTemplate(), "#" + dataColumn.key())) { + if (!StringUtils.containsAny(type.getSqlTemplate(), + Arrays.stream(dataColumn.key()).map(key -> "#" + key).toArray(String[]::new) + )) { continue; } // 设置注解变量 key 为表达式变量 value 为变量值 - context.setVariable(dataColumn.key(), dataColumn.value()); + for (int i = 0; i < dataColumn.key().length; i++) { + context.setVariable(dataColumn.key()[i], dataColumn.value()[i]); + } // 解析sql模板并填充 String sql = parser.parseExpression(type.getSqlTemplate(), parserContext).getValue(context, String.class); - sqlString.append(joinStr).append(sql); + conditions.add(joinStr + sql); isSuccess = true; } // 未处理成功则填充兜底方案 - if (!isSuccess) { - sqlString.append(joinStr).append(type.getElseSql()); + if (!isSuccess && StringUtils.isNotBlank(type.getElseSql())) { + conditions.add(joinStr + type.getElseSql()); } } - if (StringUtils.isNotBlank(sqlString.toString())) { - return sqlString.substring(joinStr.length()); + if (CollUtil.isNotEmpty(conditions)) { + String sql = StreamUtils.join(conditions, Function.identity(), ""); + return sql.substring(joinStr.length()); } return ""; } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/PlusWebInvokeTimeInterceptor.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/PlusWebInvokeTimeInterceptor.java index 9ba4cff8e..78bffab4f 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/PlusWebInvokeTimeInterceptor.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/PlusWebInvokeTimeInterceptor.java @@ -28,11 +28,13 @@ import java.util.Map; @Slf4j public class PlusWebInvokeTimeInterceptor implements HandlerInterceptor { + private final String prodProfile = "prod"; + private final TransmittableThreadLocal invokeTimeTL = new TransmittableThreadLocal<>(); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { - if (!"prod".equals(SpringUtils.getActiveProfile())) { + if (!prodProfile.equals(SpringUtils.getActiveProfile())) { String url = request.getMethod() + " " + request.getRequestURI(); // 打印请求参数 @@ -67,7 +69,7 @@ public class PlusWebInvokeTimeInterceptor implements HandlerInterceptor { @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { - if (!"prod".equals(SpringUtils.getActiveProfile())) { + if (!prodProfile.equals(SpringUtils.getActiveProfile())) { StopWatch stopWatch = invokeTimeTL.get(); stopWatch.stop(); log.debug("[PLUS]结束请求 => URL[{}],耗时:[{}]毫秒", request.getMethod() + " " + request.getRequestURI(), stopWatch.getTime()); 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 dcb9b1996..a9de17e60 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 @@ -5,7 +5,7 @@ import cn.dev33.satoken.listener.SaTokenListener; import cn.dev33.satoken.stp.SaLoginModel; import cn.hutool.http.useragent.UserAgent; import cn.hutool.http.useragent.UserAgentUtil; -import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.core.domain.dto.UserOnlineDTO; import com.ruoyi.common.core.domain.model.LoginUser; import com.ruoyi.common.enums.UserType; @@ -50,7 +50,11 @@ public class UserActionListener implements SaTokenListener { dto.setTokenId(tokenValue); dto.setUserName(user.getUsername()); dto.setDeptName(user.getDeptName()); - RedisUtils.setCacheObject(Constants.ONLINE_TOKEN_KEY + tokenValue, dto, Duration.ofSeconds(tokenConfig.getTimeout())); + if(tokenConfig.getTimeout() == -1) { + RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, dto); + } else { + RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, dto, Duration.ofSeconds(tokenConfig.getTimeout())); + } log.info("user doLogin, userId:{}, token:{}", loginId, tokenValue); } else if (userType == UserType.APP_USER) { // app端 自行根据业务编写 @@ -62,7 +66,7 @@ public class UserActionListener implements SaTokenListener { */ @Override public void doLogout(String loginType, Object loginId, String tokenValue) { - RedisUtils.deleteObject(Constants.ONLINE_TOKEN_KEY + tokenValue); + RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); log.info("user doLogout, userId:{}, token:{}", loginId, tokenValue); } @@ -71,7 +75,7 @@ public class UserActionListener implements SaTokenListener { */ @Override public void doKickout(String loginType, Object loginId, String tokenValue) { - RedisUtils.deleteObject(Constants.ONLINE_TOKEN_KEY + tokenValue); + RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); log.info("user doLogoutByLoginId, userId:{}, token:{}", loginId, tokenValue); } @@ -80,7 +84,7 @@ public class UserActionListener implements SaTokenListener { */ @Override public void doReplaced(String loginType, Object loginId, String tokenValue) { - RedisUtils.deleteObject(Constants.ONLINE_TOKEN_KEY + tokenValue); + RedisUtils.deleteObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue); log.info("user doReplaced, userId:{}, token:{}", loginId, tokenValue); } @@ -88,14 +92,28 @@ public class UserActionListener implements SaTokenListener { * 每次被封禁时触发 */ @Override - public void doDisable(String loginType, Object loginId, long disableTime) { + public void doDisable(String loginType, Object loginId, String service, int level, long disableTime) { } /** * 每次被解封时触发 */ @Override - public void doUntieDisable(String loginType, Object loginId) { + 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) { } /** @@ -112,5 +130,10 @@ public class UserActionListener implements SaTokenListener { public void doLogoutSession(String id) { } - + /** + * 每次Token续期时触发 + */ + @Override + public void doRenewTimeout(String tokenValue, Object loginId, long timeout) { + } } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/PlusSpringCacheManager.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/PlusSpringCacheManager.java new file mode 100644 index 000000000..d8bfce7c5 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/PlusSpringCacheManager.java @@ -0,0 +1,191 @@ +/** + * Copyright (c) 2013-2021 Nikita Koksharov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.ruoyi.framework.manager; + +import com.ruoyi.common.utils.redis.RedisUtils; +import org.redisson.api.RMap; +import org.redisson.api.RMapCache; +import org.redisson.spring.cache.CacheConfig; +import org.redisson.spring.cache.RedissonCache; +import org.springframework.boot.convert.DurationStyle; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; +import org.springframework.cache.transaction.TransactionAwareCacheDecorator; +import org.springframework.util.StringUtils; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * A {@link org.springframework.cache.CacheManager} implementation + * backed by Redisson instance. + *

+ * 修改 RedissonSpringCacheManager 源码 + * 重写 cacheName 处理方法 支持多参数 + * + * @author Nikita Koksharov + * + */ +@SuppressWarnings("unchecked") +public class PlusSpringCacheManager implements CacheManager { + + private boolean dynamic = true; + + private boolean allowNullValues = true; + + private boolean transactionAware = true; + + Map configMap = new ConcurrentHashMap<>(); + ConcurrentMap instanceMap = new ConcurrentHashMap<>(); + + /** + * Creates CacheManager supplied by Redisson instance + */ + public PlusSpringCacheManager() { + } + + + /** + * Defines possibility of storing {@code null} values. + *

+ * Default is true + * + * @param allowNullValues stores if true + */ + public void setAllowNullValues(boolean allowNullValues) { + this.allowNullValues = allowNullValues; + } + + /** + * Defines if cache aware of Spring-managed transactions. + * If {@code true} put/evict operations are executed only for successful transaction in after-commit phase. + *

+ * Default is false + * + * @param transactionAware cache is transaction aware if true + */ + public void setTransactionAware(boolean transactionAware) { + this.transactionAware = transactionAware; + } + + /** + * Defines 'fixed' cache names. + * A new cache instance will not be created in dynamic for non-defined names. + *

+ * `null` parameter setups dynamic mode + * + * @param names of caches + */ + public void setCacheNames(Collection names) { + if (names != null) { + for (String name : names) { + getCache(name); + } + dynamic = false; + } else { + dynamic = true; + } + } + + /** + * Set cache config mapped by cache name + * + * @param config object + */ + public void setConfig(Map config) { + this.configMap = (Map) config; + } + + protected CacheConfig createDefaultConfig() { + return new CacheConfig(); + } + + @Override + public Cache getCache(String name) { + Cache cache = instanceMap.get(name); + if (cache != null) { + return cache; + } + if (!dynamic) { + return cache; + } + + CacheConfig config = configMap.get(name); + if (config == null) { + config = createDefaultConfig(); + configMap.put(name, config); + } + + // 重写 cacheName 支持多参数 + String[] array = StringUtils.delimitedListToStringArray(name, "#"); + name = array[0]; + if (array.length > 1) { + config.setTTL(DurationStyle.detectAndParse(array[1]).toMillis()); + } + if (array.length > 2) { + config.setMaxIdleTime(DurationStyle.detectAndParse(array[2]).toMillis()); + } + if (array.length > 3) { + config.setMaxSize(Integer.parseInt(array[3])); + } + + if (config.getMaxIdleTime() == 0 && config.getTTL() == 0 && config.getMaxSize() == 0) { + return createMap(name, config); + } + + return createMapCache(name, config); + } + + private Cache createMap(String name, CacheConfig config) { + RMap map = RedisUtils.getClient().getMap(name); + + Cache cache = new RedissonCache(map, allowNullValues); + if (transactionAware) { + cache = new TransactionAwareCacheDecorator(cache); + } + Cache oldCache = instanceMap.putIfAbsent(name, cache); + if (oldCache != null) { + cache = oldCache; + } + return cache; + } + + private Cache createMapCache(String name, CacheConfig config) { + RMapCache map = RedisUtils.getClient().getMapCache(name); + + Cache cache = new RedissonCache(map, config, allowNullValues); + if (transactionAware) { + cache = new TransactionAwareCacheDecorator(cache); + } + Cache oldCache = instanceMap.putIfAbsent(name, cache); + if (oldCache != null) { + cache = oldCache; + } else { + map.setMaxSize(config.getMaxSize()); + } + return cache; + } + + @Override + public Collection getCacheNames() { + return Collections.unmodifiableSet(configMap.keySet()); + } + + +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/satoken/dao/PlusSaTokenDao.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/satoken/dao/PlusSaTokenDao.java index 68df5a646..83c3d5455 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/satoken/dao/PlusSaTokenDao.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/satoken/dao/PlusSaTokenDao.java @@ -170,10 +170,9 @@ public class PlusSaTokenDao implements SaTokenDao { * 搜索数据 */ @Override - public List searchData(String prefix, String keyword, int start, int size) { + public List searchData(String prefix, String keyword, int start, int size, boolean sortType) { Collection keys = RedisUtils.keys(prefix + "*" + keyword + "*"); List list = new ArrayList<>(keys); - return SaFoxUtil.searchList(list, start, size); + return SaFoxUtil.searchList(list, start, size, sortType); } - } 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 326c96a7b..40f2d27c3 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 @@ -8,6 +8,7 @@ import cn.hutool.http.HttpStatus; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.exception.DemoModeException; import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.StreamUtils; import lombok.extern.slf4j.Slf4j; import org.mybatis.spring.MyBatisSystemException; import org.springframework.context.support.DefaultMessageSourceResolvable; @@ -21,7 +22,6 @@ import org.springframework.web.bind.annotation.RestControllerAdvice; import javax.servlet.http.HttpServletRequest; import javax.validation.ConstraintViolation; import javax.validation.ConstraintViolationException; -import java.util.stream.Collectors; /** * 全局异常处理器 @@ -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()); } /** @@ -134,9 +134,7 @@ public class GlobalExceptionHandler { @ExceptionHandler(BindException.class) public R handleBindException(BindException e) { log.error(e.getMessage(), e); - String message = e.getAllErrors().stream() - .map(DefaultMessageSourceResolvable::getDefaultMessage) - .collect(Collectors.joining(", ")); + String message = StreamUtils.join(e.getAllErrors(), DefaultMessageSourceResolvable::getDefaultMessage, ", "); return R.fail(message); } @@ -146,9 +144,7 @@ public class GlobalExceptionHandler { @ExceptionHandler(ConstraintViolationException.class) public R constraintViolationException(ConstraintViolationException e) { log.error(e.getMessage(), e); - String message = e.getConstraintViolations().stream() - .map(ConstraintViolation::getMessage) - .collect(Collectors.joining(", ")); + String message = StreamUtils.join(e.getConstraintViolations(), ConstraintViolation::getMessage, ", "); return R.fail(message); } diff --git a/ruoyi-generator/pom.xml b/ruoyi-generator/pom.xml index b45858da3..3e55d4424 100644 --- a/ruoyi-generator/pom.xml +++ b/ruoyi-generator/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.2.0 + 4.4.0 4.0.0 diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java index e9e61e72b..77df9fd92 100644 --- a/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java @@ -12,8 +12,6 @@ import com.ruoyi.common.enums.BusinessType; import com.ruoyi.generator.domain.GenTable; import com.ruoyi.generator.domain.GenTableColumn; import com.ruoyi.generator.service.IGenTableService; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -30,7 +28,6 @@ import java.util.Map; * @author Lion Li */ @Validated -@Api(value = "代码生成", tags = {"代码生成管理"}) @RequiredArgsConstructor @RestController @RequestMapping("/tool/gen") @@ -41,7 +38,6 @@ public class GenController extends BaseController { /** * 查询代码生成列表 */ - @ApiOperation("查询代码生成列表") @SaCheckPermission("tool:gen:list") @GetMapping("/list") public TableDataInfo genList(GenTable genTable, PageQuery pageQuery) { @@ -50,8 +46,9 @@ public class GenController extends BaseController { /** * 修改代码生成业务 + * + * @param tableId 表ID */ - @ApiOperation("修改代码生成业务") @SaCheckPermission("tool:gen:query") @GetMapping(value = "/{tableId}") public R> getInfo(@PathVariable Long tableId) { @@ -68,7 +65,6 @@ public class GenController extends BaseController { /** * 查询数据库列表 */ - @ApiOperation("查询数据库列表") @SaCheckPermission("tool:gen:list") @GetMapping("/db/list") public TableDataInfo dataList(GenTable genTable, PageQuery pageQuery) { @@ -77,8 +73,9 @@ public class GenController extends BaseController { /** * 查询数据表字段列表 + * + * @param tableId 表ID */ - @ApiOperation("查询数据表字段列表") @SaCheckPermission("tool:gen:list") @GetMapping(value = "/column/{tableId}") public TableDataInfo columnList(Long tableId) { @@ -91,8 +88,9 @@ public class GenController extends BaseController { /** * 导入表结构(保存) + * + * @param tables 表名串 */ - @ApiOperation("导入表结构(保存)") @SaCheckPermission("tool:gen:import") @Log(title = "代码生成", businessType = BusinessType.IMPORT) @PostMapping("/importTable") @@ -107,7 +105,6 @@ public class GenController extends BaseController { /** * 修改保存代码生成业务 */ - @ApiOperation("修改保存代码生成业务") @SaCheckPermission("tool:gen:edit") @Log(title = "代码生成", businessType = BusinessType.UPDATE) @PutMapping @@ -119,8 +116,9 @@ public class GenController extends BaseController { /** * 删除代码生成 + * + * @param tableIds 表ID串 */ - @ApiOperation("删除代码生成") @SaCheckPermission("tool:gen:remove") @Log(title = "代码生成", businessType = BusinessType.DELETE) @DeleteMapping("/{tableIds}") @@ -131,8 +129,9 @@ public class GenController extends BaseController { /** * 预览代码 + * + * @param tableId 表ID */ - @ApiOperation("预览代码") @SaCheckPermission("tool:gen:preview") @GetMapping("/preview/{tableId}") public R> preview(@PathVariable("tableId") Long tableId) throws IOException { @@ -142,8 +141,9 @@ public class GenController extends BaseController { /** * 生成代码(下载方式) + * + * @param tableName 表名 */ - @ApiOperation("生成代码(下载方式)") @SaCheckPermission("tool:gen:code") @Log(title = "代码生成", businessType = BusinessType.GENCODE) @GetMapping("/download/{tableName}") @@ -154,8 +154,9 @@ public class GenController extends BaseController { /** * 生成代码(自定义路径) + * + * @param tableName 表名 */ - @ApiOperation("生成代码(自定义路径)") @SaCheckPermission("tool:gen:code") @Log(title = "代码生成", businessType = BusinessType.GENCODE) @GetMapping("/genCode/{tableName}") @@ -166,8 +167,9 @@ public class GenController extends BaseController { /** * 同步数据库 + * + * @param tableName 表名 */ - @ApiOperation("同步数据库") @SaCheckPermission("tool:gen:edit") @Log(title = "代码生成", businessType = BusinessType.UPDATE) @GetMapping("/synchDb/{tableName}") @@ -178,8 +180,9 @@ public class GenController extends BaseController { /** * 批量生成代码 + * + * @param tables 表名串 */ - @ApiOperation("批量生成代码") @SaCheckPermission("tool:gen:code") @Log(title = "代码生成", businessType = BusinessType.GENCODE) @GetMapping("/batchGenCode") diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java index 1ea991796..280204b55 100644 --- a/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java @@ -124,7 +124,7 @@ public class GenTableColumn extends BaseEntity { private Integer sort; public String getCapJavaField() { - return StringUtils.uncapitalize(javaField); + return StringUtils.capitalize(javaField); } public boolean isPk() { diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java index 2a99a2e65..7a80229b1 100644 --- a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java +++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java @@ -18,6 +18,7 @@ import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.helper.LoginHelper; import com.ruoyi.common.utils.JsonUtils; +import com.ruoyi.common.utils.StreamUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.file.FileUtils; import com.ruoyi.generator.domain.GenTable; @@ -41,8 +42,6 @@ import java.io.IOException; import java.io.StringWriter; import java.nio.charset.StandardCharsets; import java.util.*; -import java.util.function.Function; -import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @@ -293,13 +292,13 @@ public class GenTableServiceImpl implements IGenTableService { public void synchDb(String tableName) { GenTable table = baseMapper.selectGenTableByName(tableName); List tableColumns = table.getColumns(); - Map tableColumnMap = tableColumns.stream().collect(Collectors.toMap(GenTableColumn::getColumnName, Function.identity())); + Map tableColumnMap = StreamUtils.toIdentityMap(tableColumns, GenTableColumn::getColumnName); List dbTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName); if (CollUtil.isEmpty(dbTableColumns)) { throw new ServiceException("同步数据失败,原表结构不存在"); } - List dbTableColumnNames = dbTableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList()); + List dbTableColumnNames = StreamUtils.toList(dbTableColumns, GenTableColumn::getColumnName); List saveColumns = new ArrayList<>(); dbTableColumns.forEach(column -> { @@ -327,10 +326,9 @@ public class GenTableServiceImpl implements IGenTableService { if (CollUtil.isNotEmpty(saveColumns)) { genTableColumnMapper.insertBatch(saveColumns); } - - List delColumns = tableColumns.stream().filter(column -> !dbTableColumnNames.contains(column.getColumnName())).collect(Collectors.toList()); + List delColumns = StreamUtils.filter(tableColumns, column -> !dbTableColumnNames.contains(column.getColumnName())); if (CollUtil.isNotEmpty(delColumns)) { - List ids = delColumns.stream().map(GenTableColumn::getColumnId).collect(Collectors.toList()); + List ids = StreamUtils.toList(delColumns, GenTableColumn::getColumnId); genTableColumnMapper.deleteBatchIds(ids); } } diff --git a/ruoyi-generator/src/main/resources/vm/java/bo.java.vm b/ruoyi-generator/src/main/resources/vm/java/bo.java.vm index 13b987318..870014add 100644 --- a/ruoyi-generator/src/main/resources/vm/java/bo.java.vm +++ b/ruoyi-generator/src/main/resources/vm/java/bo.java.vm @@ -2,8 +2,6 @@ package ${packageName}.domain.bo; import com.ruoyi.common.core.validate.AddGroup; import com.ruoyi.common.core.validate.EditGroup; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; import javax.validation.constraints.*; @@ -33,7 +31,6 @@ import com.ruoyi.common.core.domain.TreeEntity; @Data @EqualsAndHashCode(callSuper = true) -@ApiModel("${functionName}业务对象") public class ${ClassName}Bo extends ${Entity} { #foreach ($column in $columns) @@ -49,14 +46,11 @@ public class ${ClassName}Bo extends ${Entity} { #set($Group="EditGroup.class") #end #if($column.isRequired == 1) - @ApiModelProperty(value = "$column.columnComment", required = true) #if($column.javaType == 'String') @NotBlank(message = "$column.columnComment不能为空", groups = { $Group }) #else @NotNull(message = "$column.columnComment不能为空", groups = { $Group }) #end -#else - @ApiModelProperty(value = "$column.columnComment") #end private $column.javaType $column.javaField; 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 6b2fc6582..3edbc3382 100644 --- a/ruoyi-generator/src/main/resources/vm/java/controller.java.vm +++ b/ruoyi-generator/src/main/resources/vm/java/controller.java.vm @@ -27,18 +27,14 @@ import ${packageName}.service.I${ClassName}Service; import com.ruoyi.common.core.page.TableDataInfo; #elseif($table.tree) #end -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiParam; -import io.swagger.annotations.ApiOperation; /** - * ${functionName}Controller + * ${functionName} * * @author ${author} * @date ${datetime} */ @Validated -@Api(value = "${functionName}控制器", tags = {"${functionName}管理"}) @RequiredArgsConstructor @RestController @RequestMapping("/${moduleName}/${businessName}") @@ -49,7 +45,6 @@ public class ${ClassName}Controller extends BaseController { /** * 查询${functionName}列表 */ - @ApiOperation("查询${functionName}列表") @SaCheckPermission("${permissionPrefix}:list") @GetMapping("/list") #if($table.crud || $table.sub) @@ -66,7 +61,6 @@ public class ${ClassName}Controller extends BaseController { /** * 导出${functionName}列表 */ - @ApiOperation("导出${functionName}列表") @SaCheckPermission("${permissionPrefix}:export") @Log(title = "${functionName}", businessType = BusinessType.EXPORT) @PostMapping("/export") @@ -77,50 +71,48 @@ public class ${ClassName}Controller extends BaseController { /** * 获取${functionName}详细信息 + * + * @param ${pkColumn.javaField} 主键 */ - @ApiOperation("获取${functionName}详细信息") @SaCheckPermission("${permissionPrefix}:query") @GetMapping("/{${pkColumn.javaField}}") - public R<${ClassName}Vo> getInfo(@ApiParam("主键") - @NotNull(message = "主键不能为空") - @PathVariable("${pkColumn.javaField}") ${pkColumn.javaType} ${pkColumn.javaField}) { + public R<${ClassName}Vo> getInfo(@NotNull(message = "主键不能为空") + @PathVariable ${pkColumn.javaType} ${pkColumn.javaField}) { return R.ok(i${ClassName}Service.queryById(${pkColumn.javaField})); } /** * 新增${functionName} */ - @ApiOperation("新增${functionName}") @SaCheckPermission("${permissionPrefix}:add") @Log(title = "${functionName}", businessType = BusinessType.INSERT) @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)); } /** * 修改${functionName} */ - @ApiOperation("修改${functionName}") @SaCheckPermission("${permissionPrefix}:edit") @Log(title = "${functionName}", businessType = BusinessType.UPDATE) @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)); } /** * 删除${functionName} + * + * @param ${pkColumn.javaField}s 主键串 */ - @ApiOperation("删除${functionName}") @SaCheckPermission("${permissionPrefix}:remove") @Log(title = "${functionName}", businessType = BusinessType.DELETE) @DeleteMapping("/{${pkColumn.javaField}s}") - public R remove(@ApiParam("主键串") - @NotEmpty(message = "主键不能为空") - @PathVariable ${pkColumn.javaType}[] ${pkColumn.javaField}s) { - return toAjax(i${ClassName}Service.deleteWithValidByIds(Arrays.asList(${pkColumn.javaField}s), true) ? 1 : 0); + public R remove(@NotEmpty(message = "主键不能为空") + @PathVariable ${pkColumn.javaType}[] ${pkColumn.javaField}s) { + return toAjax(i${ClassName}Service.deleteWithValidByIds(Arrays.asList(${pkColumn.javaField}s), true)); } } diff --git a/ruoyi-generator/src/main/resources/vm/java/service.java.vm b/ruoyi-generator/src/main/resources/vm/java/service.java.vm index 0f9137a5d..7faafb8fa 100644 --- a/ruoyi-generator/src/main/resources/vm/java/service.java.vm +++ b/ruoyi-generator/src/main/resources/vm/java/service.java.vm @@ -37,7 +37,7 @@ public interface I${ClassName}Service { List<${ClassName}Vo> queryList(${ClassName}Bo bo); /** - * 修改${functionName} + * 新增${functionName} */ Boolean insertByBo(${ClassName}Bo bo); diff --git a/ruoyi-generator/src/main/resources/vm/java/vo.java.vm b/ruoyi-generator/src/main/resources/vm/java/vo.java.vm index 216e90fc7..983c29c0d 100644 --- a/ruoyi-generator/src/main/resources/vm/java/vo.java.vm +++ b/ruoyi-generator/src/main/resources/vm/java/vo.java.vm @@ -7,8 +7,6 @@ import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; import com.ruoyi.common.annotation.ExcelDictFormat; import com.ruoyi.common.convert.ExcelDictConvert; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.util.Date; @@ -21,7 +19,6 @@ import java.util.Date; * @date ${datetime} */ @Data -@ApiModel("${functionName}视图对象") @ExcelIgnoreUnannotated public class ${ClassName}Vo { @@ -47,7 +44,6 @@ public class ${ClassName}Vo { #else @ExcelProperty(value = "${comment}") #end - @ApiModelProperty("$column.columnComment") private $column.javaType $column.javaField; #end diff --git a/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm index ac0c2b2c8..4ad96df33 100644 --- a/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm +++ b/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm @@ -504,6 +504,7 @@ export default { this.loading = false; this.getList(); this.#[[$modal]]#.msgSuccess("删除成功"); + }).catch(() => { }).finally(() => { this.loading = false; }); diff --git a/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm index 7a597f389..7a57c7fde 100644 --- a/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm +++ b/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm @@ -561,6 +561,7 @@ export default { this.loading = false; this.getList(); this.#[[$modal]]#.msgSuccess("删除成功"); + }).catch(() => { }).finally(() => { this.loading = false; }); 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 5db196710..01a7367f8 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 @@ -487,6 +472,7 @@ function handleDelete(row) { loading.value = false; getList(); proxy.#[[$modal]]#.msgSuccess("删除成功"); + }).catch(() => { }).finally(() => { loading.value = false; }); 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 6c9cdd612..d0f4f8bc8 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 @@ -492,8 +482,8 @@ function handleAdd() { function handleUpdate(row) { loading.value = true reset(); - const ${pkColumn.javaField} = row.${pkColumn.javaField} || ids.value - get${BusinessName}(${pkColumn.javaField}).then(response => { + const _${pkColumn.javaField} = row.${pkColumn.javaField} || ids.value + get${BusinessName}(_${pkColumn.javaField}).then(response => { loading.value = false; form.value = response.data; #foreach ($column in $columns) @@ -545,14 +535,15 @@ function submitForm() { /** 删除按钮操作 */ function handleDelete(row) { - const ${pkColumn.javaField}s = row.${pkColumn.javaField} || ids.value; + const _${pkColumn.javaField}s = row.${pkColumn.javaField} || ids.value; proxy.#[[$modal]]#.confirm('是否确认删除${functionName}编号为"' + ${pkColumn.javaField}s + '"的数据项?').then(function() { loading.value = true; - return del${BusinessName}(${pkColumn.javaField}s); + return del${BusinessName}(_${pkColumn.javaField}s); }).then(() => { loading.value = true; getList(); proxy.#[[$modal]]#.msgSuccess("删除成功"); + }).catch(() => { }).finally(() => { loading.value = false; }); diff --git a/ruoyi-generator/src/main/resources/vm/vue/v3/readme.txt b/ruoyi-generator/src/main/resources/vm/vue/v3/readme.txt index 99239bb53..e6dc758af 100644 --- a/ruoyi-generator/src/main/resources/vm/vue/v3/readme.txt +++ b/ruoyi-generator/src/main/resources/vm/vue/v3/readme.txt @@ -1 +1 @@ -ʹõRuoYi-Vue3ǰˣôҪһ´Ŀ¼ģindex.vue.vmindex-tree.vue.vmļϼvueĿ¼ \ No newline at end of file +如果使用的是Vue3前端,那么需要覆盖一下此目录的模板index.vue.vm、index-tree.vue.vm文件到上级vue目录。 diff --git a/ruoyi-job/pom.xml b/ruoyi-job/pom.xml index af6ae960d..4162183f4 100644 --- a/ruoyi-job/pom.xml +++ b/ruoyi-job/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.2.0 + 4.4.0 4.0.0 jar @@ -29,11 +29,7 @@ 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 20afa2e64..4ca170be7 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/pom.xml b/ruoyi-oss/pom.xml index b339e7b4d..78e618e95 100644 --- a/ruoyi-oss/pom.xml +++ b/ruoyi-oss/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.2.0 + 4.4.0 4.0.0 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 1d1a77708..06202d0f2 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 @@ -11,19 +11,9 @@ import java.util.List; public interface OssConstant { /** - * OSS模块KEY + * 默认配置KEY */ - String SYS_OSS_KEY = "sys_oss:"; - - /** - * 对象存储配置KEY - */ - String OSS_CONFIG_KEY = "OssConfig"; - - /** - * 缓存配置KEY - */ - String CACHE_CONFIG_KEY = SYS_OSS_KEY + OSS_CONFIG_KEY; + String DEFAULT_CONFIG_KEY = "sys_oss:default_config"; /** * 预览列表资源开关Key @@ -33,12 +23,12 @@ public interface OssConstant { /** * 系统数据ids */ - List SYSTEM_DATA_IDS = Arrays.asList(1, 2, 3, 4); + List SYSTEM_DATA_IDS = Arrays.asList(1L, 2L, 3L, 4L); /** * 云服务商 */ - 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 6f6be8f8c..fe409ce7d 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; @@ -10,20 +12,21 @@ import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.client.builder.AwsClientBuilder; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3Client; -import com.amazonaws.services.s3.model.CannedAccessControlList; -import com.amazonaws.services.s3.model.CreateBucketRequest; -import com.amazonaws.services.s3.model.ObjectMetadata; -import com.amazonaws.services.s3.model.PutObjectRequest; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import com.amazonaws.services.s3.model.*; 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协议的云厂商均支持 @@ -54,12 +57,16 @@ public class OssClient { } else { clientConfig.setProtocol(Protocol.HTTP); } - this.client = AmazonS3Client.builder() + AmazonS3ClientBuilder build = AmazonS3Client.builder() .withEndpointConfiguration(endpointConfig) .withClientConfiguration(clientConfig) .withCredentials(credentialsProvider) - .disableChunkedEncoding() - .build(); + .disableChunkedEncoding(); + if (!StringUtils.containsAny(properties.getEndpoint(), OssConstant.CLOUD_SERVICE)) { + // minio 使用https限制使用域名访问 需要此配置 站点填域名 + build.enablePathStyleAccess(); + } + this.client = build.build(); createBucket(); } catch (Exception e) { @@ -77,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() + "]"); } @@ -90,11 +98,17 @@ 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()); - client.putObject(new PutObjectRequest(properties.getBucketName(), path, inputStream, metadata)); + PutObjectRequest putObjectRequest = new PutObjectRequest(properties.getBucketName(), path, inputStream, metadata); + // 设置上传对象的 Acl 为公共读 + putObjectRequest.setCannedAcl(getAccessPolicy().getAcl()); + client.putObject(putObjectRequest); } catch (Exception e) { throw new OssException("上传文件失败,请检查配置信息:[" + e.getMessage() + "]"); } @@ -106,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() + "]"); } } @@ -118,18 +132,38 @@ public class OssClient { return upload(inputStream, getPath(properties.getPrefix(), suffix), contentType); } + /** + * 获取文件元数据 + * + * @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(); - if (StringUtils.isNotBlank(domain)) { - return domain; - } 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; + } return header + properties.getBucketName() + "." + endpoint; } // minio 单独处理 + if (StringUtils.isNotBlank(domain)) { + return header + domain + "/" + properties.getBucketName(); + } return header + endpoint + "/" + properties.getBucketName(); } @@ -149,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 000000000..1cae67094 --- /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/factory/OssFactory.java b/ruoyi-oss/src/main/java/com/ruoyi/oss/factory/OssFactory.java index 7065c4a4a..c3312d730 100644 --- a/ruoyi-oss/src/main/java/com/ruoyi/oss/factory/OssFactory.java +++ b/ruoyi-oss/src/main/java/com/ruoyi/oss/factory/OssFactory.java @@ -1,7 +1,9 @@ package com.ruoyi.oss.factory; +import com.ruoyi.common.constant.CacheNames; import com.ruoyi.common.utils.JsonUtils; import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.redis.CacheUtils; import com.ruoyi.common.utils.redis.RedisUtils; import com.ruoyi.oss.constant.OssConstant; import com.ruoyi.oss.core.OssClient; @@ -27,7 +29,7 @@ public class OssFactory { */ public static void init() { log.info("初始化OSS工厂"); - RedisUtils.subscribe(OssConstant.CACHE_CONFIG_KEY, String.class, configKey -> { + RedisUtils.subscribe(OssConstant.DEFAULT_CONFIG_KEY, String.class, configKey -> { OssClient client = getClient(configKey); // 未初始化不处理 if (client != null) { @@ -42,7 +44,7 @@ public class OssFactory { */ public static OssClient instance() { // 获取redis 默认类型 - String configKey = RedisUtils.getCacheObject(OssConstant.CACHE_CONFIG_KEY); + String configKey = RedisUtils.getCacheObject(OssConstant.DEFAULT_CONFIG_KEY); if (StringUtils.isEmpty(configKey)) { throw new OssException("文件存储服务类型无法找到!"); } @@ -62,11 +64,11 @@ public class OssFactory { } private static void refresh(String configKey) { - Object json = RedisUtils.getCacheObject(OssConstant.SYS_OSS_KEY + configKey); - OssProperties properties = JsonUtils.parseObject(json.toString(), OssProperties.class); - if (properties == null) { + String json = CacheUtils.get(CacheNames.SYS_OSS_CONFIG, configKey); + if (json == null) { throw new OssException("系统异常, '" + configKey + "'配置信息不存在!"); } + OssProperties properties = JsonUtils.parseObject(json, OssProperties.class); CLIENT_CACHE.put(configKey, new OssClient(configKey, properties)); } 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 a01777901..781a17005 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 b2a6cf5cc..0ebabbb25 100644 --- a/ruoyi-sms/pom.xml +++ b/ruoyi-sms/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.2.0 + 4.4.0 4.0.0 @@ -31,7 +31,7 @@ com.tencentcloudapi - tencentcloud-sdk-java + tencentcloud-sdk-java-sms true diff --git a/ruoyi-sms/src/main/java/com/ruoyi/sms/core/AliyunSmsTemplate.java b/ruoyi-sms/src/main/java/com/ruoyi/sms/core/AliyunSmsTemplate.java index eede376e5..3c16a5b41 100644 --- a/ruoyi-sms/src/main/java/com/ruoyi/sms/core/AliyunSmsTemplate.java +++ b/ruoyi-sms/src/main/java/com/ruoyi/sms/core/AliyunSmsTemplate.java @@ -56,7 +56,7 @@ public class AliyunSmsTemplate implements SmsTemplate { return SmsResult.builder() .isSuccess("OK".equals(resp.getBody().getCode())) .message(resp.getBody().getMessage()) - .response(resp) + .response(JsonUtils.toJsonString(resp)) .build(); } catch (Exception e) { throw new SmsException(e.getMessage()); diff --git a/ruoyi-sms/src/main/java/com/ruoyi/sms/core/TencentSmsTemplate.java b/ruoyi-sms/src/main/java/com/ruoyi/sms/core/TencentSmsTemplate.java index 1de8eae14..17f5b5b16 100644 --- a/ruoyi-sms/src/main/java/com/ruoyi/sms/core/TencentSmsTemplate.java +++ b/ruoyi-sms/src/main/java/com/ruoyi/sms/core/TencentSmsTemplate.java @@ -2,6 +2,7 @@ package com.ruoyi.sms.core; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ArrayUtil; +import com.ruoyi.common.utils.JsonUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.sms.config.properties.SmsProperties; import com.ruoyi.sms.entity.SmsResult; @@ -65,7 +66,7 @@ public class TencentSmsTemplate implements SmsTemplate { SmsResult.SmsResultBuilder builder = SmsResult.builder() .isSuccess(true) .message("send success") - .response(resp); + .response(JsonUtils.toJsonString(resp)); for (SendStatus sendStatus : resp.getSendStatusSet()) { if (!"Ok".equals(sendStatus.getCode())) { builder.isSuccess(false).message(sendStatus.getMessage()); diff --git a/ruoyi-sms/src/main/java/com/ruoyi/sms/entity/SmsResult.java b/ruoyi-sms/src/main/java/com/ruoyi/sms/entity/SmsResult.java index 3f13b2774..89c39b403 100644 --- a/ruoyi-sms/src/main/java/com/ruoyi/sms/entity/SmsResult.java +++ b/ruoyi-sms/src/main/java/com/ruoyi/sms/entity/SmsResult.java @@ -24,6 +24,8 @@ public class SmsResult { /** * 实际响应体 + *

+ * 可自行转换为 SDK 对应的 SendSmsResponse */ - private Object response; + private String response; } diff --git a/ruoyi-system/pom.xml b/ruoyi-system/pom.xml index 9e49b71ad..daa5aba7b 100644 --- a/ruoyi-system/pom.xml +++ b/ruoyi-system/pom.xml @@ -5,7 +5,7 @@ ruoyi-vue-plus com.ruoyi - 4.2.0 + 4.4.0 4.0.0 diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysCache.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysCache.java new file mode 100644 index 000000000..974019dd9 --- /dev/null +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysCache.java @@ -0,0 +1,47 @@ +package com.ruoyi.system.domain; + +import com.ruoyi.common.utils.StringUtils; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 缓存信息 + * + * @author Lion Li + */ +@Data +@NoArgsConstructor +public class SysCache { + + /** + * 缓存名称 + */ + private String cacheName = ""; + + /** + * 缓存键名 + */ + private String cacheKey = ""; + + /** + * 缓存内容 + */ + private String cacheValue = ""; + + /** + * 备注 + */ + private String remark = ""; + + public SysCache(String cacheName, String remark) { + this.cacheName = cacheName; + this.remark = remark; + } + + public SysCache(String cacheName, String cacheKey, String cacheValue) { + this.cacheName = StringUtils.replace(cacheName, ":", ""); + this.cacheKey = StringUtils.replace(cacheKey, cacheName, ""); + this.cacheValue = cacheValue; + } + +} diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java index b1091b458..40bc2821d 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java @@ -7,8 +7,6 @@ import com.baomidou.mybatisplus.annotation.TableName; import com.ruoyi.common.annotation.ExcelDictFormat; import com.ruoyi.common.convert.ExcelDictConvert; import com.ruoyi.common.core.domain.BaseEntity; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; @@ -25,13 +23,11 @@ import javax.validation.constraints.Size; @EqualsAndHashCode(callSuper = true) @TableName("sys_config") @ExcelIgnoreUnannotated -@ApiModel("参数配置业务对象") public class SysConfig extends BaseEntity { /** * 参数主键 */ - @ApiModelProperty(value = "参数主键") @ExcelProperty(value = "参数主键") @TableId(value = "config_id") private Long configId; @@ -39,7 +35,6 @@ public class SysConfig extends BaseEntity { /** * 参数名称 */ - @ApiModelProperty(value = "参数名称") @ExcelProperty(value = "参数名称") @NotBlank(message = "参数名称不能为空") @Size(min = 0, max = 100, message = "参数名称不能超过100个字符") @@ -48,7 +43,6 @@ public class SysConfig extends BaseEntity { /** * 参数键名 */ - @ApiModelProperty(value = "参数键名") @ExcelProperty(value = "参数键名") @NotBlank(message = "参数键名长度不能为空") @Size(min = 0, max = 100, message = "参数键名长度不能超过100个字符") @@ -57,7 +51,6 @@ public class SysConfig extends BaseEntity { /** * 参数键值 */ - @ApiModelProperty(value = "参数键值") @ExcelProperty(value = "参数键值") @NotBlank(message = "参数键值不能为空") @Size(min = 0, max = 500, message = "参数键值长度不能超过500个字符") @@ -66,7 +59,6 @@ public class SysConfig extends BaseEntity { /** * 系统内置(Y是 N否) */ - @ApiModelProperty(value = "系统内置(Y是 N否)") @ExcelProperty(value = "系统内置", converter = ExcelDictConvert.class) @ExcelDictFormat(dictType = "sys_yes_no") private String configType; @@ -74,7 +66,6 @@ public class SysConfig extends BaseEntity { /** * 备注 */ - @ApiModelProperty(value = "备注") private String remark; } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java index de095ec38..f95b332e7 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java @@ -7,8 +7,6 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.ruoyi.common.annotation.ExcelDictFormat; import com.ruoyi.common.convert.ExcelDictConvert; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; @@ -25,14 +23,12 @@ import java.util.Map; @Data @TableName("sys_logininfor") @ExcelIgnoreUnannotated -@ApiModel("系统访问记录业务对象") public class SysLogininfor implements Serializable { private static final long serialVersionUID = 1L; /** * ID */ - @ApiModelProperty(value = "访问ID") @ExcelProperty(value = "序号") @TableId(value = "info_id") private Long infoId; @@ -40,14 +36,12 @@ public class SysLogininfor implements Serializable { /** * 用户账号 */ - @ApiModelProperty(value = "用户账号") @ExcelProperty(value = "用户账号") private String userName; /** * 登录状态 0成功 1失败 */ - @ApiModelProperty(value = "登录状态 0成功 1失败") @ExcelProperty(value = "登录状态", converter = ExcelDictConvert.class) @ExcelDictFormat(dictType = "sys_common_status") private String status; @@ -55,49 +49,42 @@ public class SysLogininfor implements Serializable { /** * 登录IP地址 */ - @ApiModelProperty(value = "登录IP地址") @ExcelProperty(value = "登录地址") private String ipaddr; /** * 登录地点 */ - @ApiModelProperty(value = "登录地点") @ExcelProperty(value = "登录地点") private String loginLocation; /** * 浏览器类型 */ - @ApiModelProperty(value = "浏览器类型") @ExcelProperty(value = "浏览器") private String browser; /** * 操作系统 */ - @ApiModelProperty(value = "操作系统") @ExcelProperty(value = "操作系统") private String os; /** * 提示消息 */ - @ApiModelProperty(value = "提示消息") @ExcelProperty(value = "提示消息") private String msg; /** * 访问时间 */ - @ApiModelProperty(value = "访问时间") @ExcelProperty(value = "访问时间") private Date loginTime; /** * 请求参数 */ - @ApiModelProperty(value = "请求参数") @TableField(exist = false) private Map params = new HashMap<>(); diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java index 2371bb7e5..f9457406a 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java @@ -4,7 +4,6 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.ruoyi.common.core.domain.BaseEntity; import com.ruoyi.common.xss.Xss; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; @@ -25,7 +24,6 @@ public class SysNotice extends BaseEntity { /** * 公告ID */ - @ApiModelProperty(value = "公告ID") @TableId(value = "notice_id") private Long noticeId; @@ -33,7 +31,6 @@ public class SysNotice extends BaseEntity { * 公告标题 */ @Xss(message = "公告标题不能包含脚本字符") - @ApiModelProperty(value = "公告标题") @NotBlank(message = "公告标题不能为空") @Size(min = 0, max = 50, message = "公告标题不能超过50个字符") private String noticeTitle; @@ -41,25 +38,21 @@ public class SysNotice extends BaseEntity { /** * 公告类型(1通知 2公告) */ - @ApiModelProperty(value = "公告类型(1通知 2公告)") private String noticeType; /** * 公告内容 */ - @ApiModelProperty(value = "公告内容") private String noticeContent; /** * 公告状态(0正常 1关闭) */ - @ApiModelProperty(value = "公告状态(0正常 1关闭)") private String status; /** * 备注 */ - @ApiModelProperty(value = "备注") private String remark; } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java index f6f373776..84af07b91 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java @@ -7,8 +7,6 @@ import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.ruoyi.common.annotation.ExcelDictFormat; import com.ruoyi.common.convert.ExcelDictConvert; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; @@ -25,7 +23,6 @@ import java.util.Map; @Data @TableName("sys_oper_log") @ExcelIgnoreUnannotated -@ApiModel("操作日志记录业务对象") public class SysOperLog implements Serializable { private static final long serialVersionUID = 1L; @@ -33,7 +30,6 @@ public class SysOperLog implements Serializable { /** * 日志主键 */ - @ApiModelProperty(value = "日志主键") @ExcelProperty(value = "日志主键") @TableId(value = "oper_id") private Long operId; @@ -41,14 +37,12 @@ public class SysOperLog implements Serializable { /** * 操作模块 */ - @ApiModelProperty(value = "操作模块") @ExcelProperty(value = "操作模块") private String title; /** * 业务类型(0其它 1新增 2修改 3删除) */ - @ApiModelProperty(value = "业务类型(0其它 1新增 2修改 3删除)") @ExcelProperty(value = "业务类型", converter = ExcelDictConvert.class) @ExcelDictFormat(dictType = "sys_oper_type") private Integer businessType; @@ -56,28 +50,24 @@ public class SysOperLog implements Serializable { /** * 业务类型数组 */ - @ApiModelProperty(value = "业务类型数组") @TableField(exist = false) private Integer[] businessTypes; /** * 请求方法 */ - @ApiModelProperty(value = "请求方法") @ExcelProperty(value = "请求方法") private String method; /** * 请求方式 */ - @ApiModelProperty(value = "请求方式") @ExcelProperty(value = "请求方式") private String requestMethod; /** * 操作类别(0其它 1后台用户 2手机端用户) */ - @ApiModelProperty(value = "操作类别(0其它 1后台用户 2手机端用户)") @ExcelProperty(value = "操作类别", converter = ExcelDictConvert.class) @ExcelDictFormat(readConverterExp = "0=其它,1=后台用户,2=手机端用户") private Integer operatorType; @@ -85,56 +75,48 @@ public class SysOperLog implements Serializable { /** * 操作人员 */ - @ApiModelProperty(value = "操作人员") @ExcelProperty(value = "操作人员") private String operName; /** * 部门名称 */ - @ApiModelProperty(value = "部门名称") @ExcelProperty(value = "部门名称") private String deptName; /** * 请求url */ - @ApiModelProperty(value = "请求url") @ExcelProperty(value = "请求地址") private String operUrl; /** * 操作地址 */ - @ApiModelProperty(value = "操作地址") @ExcelProperty(value = "操作地址") private String operIp; /** * 操作地点 */ - @ApiModelProperty(value = "操作地点") @ExcelProperty(value = "操作地点") private String operLocation; /** * 请求参数 */ - @ApiModelProperty(value = "请求参数") @ExcelProperty(value = "请求参数") private String operParam; /** * 返回参数 */ - @ApiModelProperty(value = "返回参数") @ExcelProperty(value = "返回参数") private String jsonResult; /** * 操作状态(0正常 1异常) */ - @ApiModelProperty(value = "操作状态(0正常 1异常)") @ExcelProperty(value = "状态", converter = ExcelDictConvert.class) @ExcelDictFormat(dictType = "sys_common_status") private Integer status; @@ -142,21 +124,18 @@ public class SysOperLog implements Serializable { /** * 错误消息 */ - @ApiModelProperty(value = "错误消息") @ExcelProperty(value = "错误消息") private String errorMsg; /** * 操作时间 */ - @ApiModelProperty(value = "操作时间") @ExcelProperty(value = "操作时间") private Date operTime; /** * 请求参数 */ - @ApiModelProperty(value = "请求参数") @TableField(exist = false) private Map params = new HashMap<>(); 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 577f17fb8..7f2b05f6a 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/SysPost.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java index d0c968e42..1edabf509 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java @@ -8,8 +8,6 @@ import com.baomidou.mybatisplus.annotation.TableName; import com.ruoyi.common.annotation.ExcelDictFormat; import com.ruoyi.common.convert.ExcelDictConvert; import com.ruoyi.common.core.domain.BaseEntity; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; @@ -27,13 +25,11 @@ import javax.validation.constraints.Size; @EqualsAndHashCode(callSuper = true) @TableName("sys_post") @ExcelIgnoreUnannotated -@ApiModel("岗位信息业务对象") public class SysPost extends BaseEntity { /** * 岗位序号 */ - @ApiModelProperty(value = "岗位序号") @ExcelProperty(value = "岗位序号") @TableId(value = "post_id") private Long postId; @@ -41,7 +37,6 @@ public class SysPost extends BaseEntity { /** * 岗位编码 */ - @ApiModelProperty(value = "岗位编码") @ExcelProperty(value = "岗位编码") @NotBlank(message = "岗位编码不能为空") @Size(min = 0, max = 64, message = "岗位编码长度不能超过64个字符") @@ -50,7 +45,6 @@ public class SysPost extends BaseEntity { /** * 岗位名称 */ - @ApiModelProperty(value = "岗位名称") @ExcelProperty(value = "岗位名称") @NotBlank(message = "岗位名称不能为空") @Size(min = 0, max = 50, message = "岗位名称长度不能超过50个字符") @@ -59,7 +53,6 @@ public class SysPost extends BaseEntity { /** * 岗位排序 */ - @ApiModelProperty(value = "岗位排序") @ExcelProperty(value = "岗位排序") @NotNull(message = "显示顺序不能为空") private Integer postSort; @@ -67,21 +60,18 @@ public class SysPost extends BaseEntity { /** * 状态(0正常 1停用) */ - @ApiModelProperty(value = "状态(0正常 1停用)") @ExcelProperty(value = "状态", converter = ExcelDictConvert.class) - @ExcelDictFormat(dictType = "sys_common_status") + @ExcelDictFormat(dictType = "sys_normal_disable") private String status; /** * 备注 */ - @ApiModelProperty(value = "备注") private String remark; /** * 用户是否存在此岗位标识 默认不存在 */ - @ApiModelProperty(value = "用户是否存在此岗位标识 默认不存在") @TableField(exist = false) private boolean flag = false; diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java index c3043c253..38e7048c4 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java @@ -3,8 +3,6 @@ package com.ruoyi.system.domain; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** @@ -15,20 +13,17 @@ import lombok.Data; @Data @TableName("sys_role_dept") -@ApiModel("角色和部门关联") public class SysRoleDept { /** * 角色ID */ @TableId(type = IdType.INPUT) - @ApiModelProperty(value = "角色ID") private Long roleId; /** * 部门ID */ - @ApiModelProperty(value = "部门ID") private Long deptId; } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java index f3e4dd7c2..dd359c425 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java @@ -3,8 +3,6 @@ package com.ruoyi.system.domain; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** @@ -15,20 +13,17 @@ import lombok.Data; @Data @TableName("sys_role_menu") -@ApiModel("角色和菜单关联") public class SysRoleMenu { /** * 角色ID */ @TableId(type = IdType.INPUT) - @ApiModelProperty(value = "角色ID") private Long roleId; /** * 菜单ID */ - @ApiModelProperty(value = "角色ID") private Long menuId; } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java index 605d1645b..e8fa5bffa 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java @@ -1,7 +1,5 @@ package com.ruoyi.system.domain; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** @@ -11,55 +9,46 @@ import lombok.Data; */ @Data -@ApiModel("当前在线会话业务对象") public class SysUserOnline { /** * 会话编号 */ - @ApiModelProperty(value = "会话编号") private String tokenId; /** * 部门名称 */ - @ApiModelProperty(value = "部门名称") private String deptName; /** * 用户名称 */ - @ApiModelProperty(value = "用户名称") private String userName; /** * 登录IP地址 */ - @ApiModelProperty(value = "登录IP地址") private String ipaddr; /** * 登录地址 */ - @ApiModelProperty(value = "登录地址") private String loginLocation; /** * 浏览器类型 */ - @ApiModelProperty(value = "浏览器类型") private String browser; /** * 操作系统 */ - @ApiModelProperty(value = "操作系统") private String os; /** * 登录时间 */ - @ApiModelProperty(value = "登录时间") private Long loginTime; } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java index 243e3c8ae..a6980557c 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java @@ -3,8 +3,6 @@ package com.ruoyi.system.domain; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** @@ -15,20 +13,17 @@ import lombok.Data; @Data @TableName("sys_user_post") -@ApiModel("用户和岗位关联") public class SysUserPost { /** * 用户ID */ @TableId(type = IdType.INPUT) - @ApiModelProperty(value = "用户ID") private Long userId; /** * 岗位ID */ - @ApiModelProperty(value = "岗位ID") private Long postId; } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java index 5fa712a4b..8d3543702 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java @@ -3,8 +3,6 @@ package com.ruoyi.system.domain; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** @@ -15,20 +13,17 @@ import lombok.Data; @Data @TableName("sys_user_role") -@ApiModel("用户和角色关联") public class SysUserRole { /** * 用户ID */ @TableId(type = IdType.INPUT) - @ApiModelProperty(value = "用户ID") private Long userId; /** * 角色ID */ - @ApiModelProperty(value = "角色ID") private Long roleId; } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssBo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssBo.java index c48ae5b8e..3f5ab4a8d 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssBo.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysOssBo.java @@ -1,8 +1,6 @@ package com.ruoyi.system.domain.bo; import com.ruoyi.common.core.domain.BaseEntity; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; @@ -13,33 +11,27 @@ import lombok.EqualsAndHashCode; */ @Data @EqualsAndHashCode(callSuper = true) -@ApiModel("OSS对象存储分页查询对象") public class SysOssBo extends BaseEntity { /** * 文件名 */ - @ApiModelProperty("文件名") private String fileName; /** * 原名 */ - @ApiModelProperty("原名") private String originalName; /** * 文件后缀名 */ - @ApiModelProperty("文件后缀名") private String fileSuffix; /** * URL地址 */ - @ApiModelProperty("URL地址") private String url; /** * 服务商 */ - @ApiModelProperty("服务商") private String service; } 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 5ac4e96e4..af289376c 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 @@ -3,8 +3,6 @@ package com.ruoyi.system.domain.bo; import com.ruoyi.common.core.domain.BaseEntity; import com.ruoyi.common.core.validate.AddGroup; import com.ruoyi.common.core.validate.EditGroup; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; @@ -22,20 +20,17 @@ import javax.validation.constraints.Size; @Data @EqualsAndHashCode(callSuper = true) -@ApiModel("对象存储配置业务对象") public class SysOssConfigBo extends BaseEntity { /** * 主建 */ - @ApiModelProperty(value = "主建", required = true) @NotNull(message = "主建不能为空", groups = {EditGroup.class}) private Long ossConfigId; /** * 配置key */ - @ApiModelProperty(value = "配置key", required = true) @NotBlank(message = "配置key不能为空", groups = {AddGroup.class, EditGroup.class}) @Size(min = 2, max = 100, message = "configKey长度必须介于2和20 之间") private String configKey; @@ -43,7 +38,6 @@ public class SysOssConfigBo extends BaseEntity { /** * accessKey */ - @ApiModelProperty(value = "accessKey", required = true) @NotBlank(message = "accessKey不能为空", groups = {AddGroup.class, EditGroup.class}) @Size(min = 2, max = 100, message = "accessKey长度必须介于2和100 之间") private String accessKey; @@ -51,7 +45,6 @@ public class SysOssConfigBo extends BaseEntity { /** * 秘钥 */ - @ApiModelProperty(value = "secretKey", required = true) @NotBlank(message = "secretKey不能为空", groups = {AddGroup.class, EditGroup.class}) @Size(min = 2, max = 100, message = "secretKey长度必须介于2和100 之间") private String secretKey; @@ -59,7 +52,6 @@ public class SysOssConfigBo extends BaseEntity { /** * 桶名称 */ - @ApiModelProperty(value = "桶名称", required = true) @NotBlank(message = "桶名称不能为空", groups = {AddGroup.class, EditGroup.class}) @Size(min = 2, max = 100, message = "bucketName长度必须介于2和100之间") private String bucketName; @@ -67,13 +59,11 @@ public class SysOssConfigBo extends BaseEntity { /** * 前缀 */ - @ApiModelProperty(value = "前缀") private String prefix; /** * 访问站点 */ - @ApiModelProperty(value = "访问站点", required = true) @NotBlank(message = "访问站点不能为空", groups = {AddGroup.class, EditGroup.class}) @Size(min = 2, max = 100, message = "endpoint长度必须介于2和100之间") private String endpoint; @@ -81,37 +71,37 @@ public class SysOssConfigBo extends BaseEntity { /** * 自定义域名 */ - @ApiModelProperty("自定义域名") private String domain; /** * 是否https(Y=是,N=否) */ - @ApiModelProperty("是否https(Y=是,N=否)") private String isHttps; /** * 状态(0=正常,1=停用) */ - @ApiModelProperty("状态(0=正常,1=停用)") private String status; /** * 域 */ - @ApiModelProperty(value = "域") private String region; /** * 扩展字段 */ - @ApiModelProperty(value = "扩展字段") private String ext1; /** * 备注 */ - @ApiModelProperty(value = "备注") 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/MetaVo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java index d3e1a353a..ec1f02e19 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java @@ -1,8 +1,6 @@ package com.ruoyi.system.domain.vo; import com.ruoyi.common.utils.StringUtils; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; /** @@ -12,31 +10,26 @@ import lombok.Data; */ @Data -@ApiModel("路由显示信息") public class MetaVo { /** * 设置该路由在侧边栏和面包屑中展示的名字 */ - @ApiModelProperty(value = "设置该路由在侧边栏和面包屑中展示的名字") private String title; /** * 设置该路由的图标,对应路径src/assets/icons/svg */ - @ApiModelProperty(value = "设置该路由的图标,对应路径src/assets/icons/svg") private String icon; /** * 设置为true,则不会被 缓存 */ - @ApiModelProperty(value = "设置为true,则不会被 缓存") private boolean noCache; /** * 内链地址(http(s)://开头) */ - @ApiModelProperty(value = "内链地址(http(s)://开头)") private String link; public MetaVo(String title, String icon) { diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RouterVo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RouterVo.java index a451bb95b..8351f7c34 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RouterVo.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RouterVo.java @@ -1,8 +1,6 @@ package com.ruoyi.system.domain.vo; import com.fasterxml.jackson.annotation.JsonInclude; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.util.List; @@ -14,61 +12,51 @@ import java.util.List; */ @Data @JsonInclude(JsonInclude.Include.NON_EMPTY) -@ApiModel("路由配置信息") public class RouterVo { /** * 路由名字 */ - @ApiModelProperty(value = "路由名字") private String name; /** * 路由地址 */ - @ApiModelProperty(value = "路由地址") private String path; /** * 是否隐藏路由,当设置 true 的时候该路由不会再侧边栏出现 */ - @ApiModelProperty(value = "是否隐藏路由,当设置 true 的时候该路由不会再侧边栏出现") private boolean hidden; /** * 重定向地址,当设置 noRedirect 的时候该路由在面包屑导航中不可被点击 */ - @ApiModelProperty(value = "重定向地址,当设置 noRedirect 的时候该路由在面包屑导航中不可被点击") private String redirect; /** * 组件地址 */ - @ApiModelProperty(value = "组件地址") private String component; /** * 路由参数:如 {"id": 1, "name": "ry"} */ - @ApiModelProperty(value = "路由参数:如 {\"id\": 1, \"name\": \"ry\"}") private String query; /** * 当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式--如组件页面 */ - @ApiModelProperty(value = "当你一个路由下面的 children 声明的路由大于1个时,自动会变成嵌套的模式--如组件页面") private Boolean alwaysShow; /** * 其他元素 */ - @ApiModelProperty(value = "其他元素") private MetaVo meta; /** * 子路由 */ - @ApiModelProperty(value = "子路由") private List children; } 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 20edacaa6..616e4e82d 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 @@ -1,8 +1,6 @@ package com.ruoyi.system.domain.vo; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -14,7 +12,6 @@ import lombok.Data; * @date 2021-08-13 */ @Data -@ApiModel("对象存储配置视图对象") @ExcelIgnoreUnannotated public class SysOssConfigVo { @@ -23,79 +20,71 @@ public class SysOssConfigVo { /** * 主建 */ - @ApiModelProperty("主建") private Long ossConfigId; /** * 配置key */ - @ApiModelProperty("配置key") private String configKey; /** * accessKey */ - @ApiModelProperty("accessKey") private String accessKey; /** * 秘钥 */ - @ApiModelProperty("secretKey") private String secretKey; /** * 桶名称 */ - @ApiModelProperty("桶名称") private String bucketName; /** * 前缀 */ - @ApiModelProperty("前缀") private String prefix; /** * 访问站点 */ - @ApiModelProperty("访问站点") private String endpoint; /** * 自定义域名 */ - @ApiModelProperty("自定义域名") private String domain; /** * 是否https(Y=是,N=否) */ - @ApiModelProperty("是否https(Y=是,N=否)") private String isHttps; /** * 域 */ - @ApiModelProperty("域") private String region; /** * 状态(0=正常,1=停用) */ - @ApiModelProperty("状态(0=正常,1=停用)") private String status; /** * 扩展字段 */ - @ApiModelProperty("扩展字段") private String ext1; /** * 备注 */ - @ApiModelProperty("备注") private String remark; + /** + * 桶权限类型(0private 1public 2custom) + */ + private String accessPolicy; + } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOssVo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOssVo.java index eb2299ee6..53f5f8de8 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOssVo.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysOssVo.java @@ -1,7 +1,5 @@ package com.ruoyi.system.domain.vo; -import io.swagger.annotations.ApiModel; -import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.util.Date; @@ -12,7 +10,6 @@ import java.util.Date; * @author Lion Li */ @Data -@ApiModel("OSS对象存储视图对象") public class SysOssVo { private static final long serialVersionUID = 1L; @@ -20,49 +17,41 @@ public class SysOssVo { /** * 对象存储主键 */ - @ApiModelProperty("对象存储主键") private Long ossId; /** * 文件名 */ - @ApiModelProperty("文件名") private String fileName; /** * 原名 */ - @ApiModelProperty("原名") private String originalName; /** * 文件后缀名 */ - @ApiModelProperty("文件后缀名") private String fileSuffix; /** * URL地址 */ - @ApiModelProperty("URL地址") private String url; /** * 创建时间 */ - @ApiModelProperty("创建时间") private Date createTime; /** * 上传人 */ - @ApiModelProperty("上传人") private String createBy; /** * 服务商 */ - @ApiModelProperty("服务商") private String service; diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysUserExportVo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysUserExportVo.java index 683cb83fa..a50283d28 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysUserExportVo.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysUserExportVo.java @@ -61,7 +61,7 @@ public class SysUserExportVo implements Serializable { * 帐号状态(0正常 1停用) */ @ExcelProperty(value = "帐号状态", converter = ExcelDictConvert.class) - @ExcelDictFormat(dictType = "sys_common_status") + @ExcelDictFormat(dictType = "sys_normal_disable") private String status; /** diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/listener/SysUserImportListener.java b/ruoyi-system/src/main/java/com/ruoyi/system/listener/SysUserImportListener.java index 58f2f3136..b883dae93 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/listener/SysUserImportListener.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/listener/SysUserImportListener.java @@ -62,7 +62,12 @@ public class SysUserImportListener extends AnalysisEventListener").append(successNum).append("、账号 ").append(user.getUserName()).append(" 导入成功"); } else if (isUpdateSupport) { + Long userId = user.getUserId(); + user = BeanUtil.toBean(userVo, SysUser.class); + user.setUserId(userId); ValidatorUtils.validate(user); + userService.checkUserAllowed(user); + userService.checkUserDataScope(user.getUserId()); user.setUpdateBy(operName); userService.updateUser(user); successNum++; diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java index 8844f2798..00439032c 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java @@ -40,6 +40,14 @@ public interface SysMenuMapper extends BaseMapperPlus selectMenuPermsByUserId(Long userId); + /** + * 根据角色ID查询权限 + * + * @param roleId 角色ID + * @return 权限列表 + */ + List selectMenuPermsByRoleId(Long roleId); + /** * 根据用户ID查询菜单 * diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java index 10c4acdd7..adcb5d3f7 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java @@ -37,7 +37,7 @@ public interface ISysConfigService { * * @return true开启,false关闭 */ - boolean selectCaptchaOnOff(); + boolean selectCaptchaEnabled(); /** * 查询参数配置列表 @@ -53,7 +53,7 @@ public interface ISysConfigService { * @param config 参数配置信息 * @return 结果 */ - int insertConfig(SysConfig config); + String insertConfig(SysConfig config); /** * 修改参数配置 @@ -61,7 +61,7 @@ public interface ISysConfigService { * @param config 参数配置信息 * @return 结果 */ - int updateConfig(SysConfig config); + String updateConfig(SysConfig config); /** * 批量删除参数信息 @@ -93,6 +93,4 @@ public interface ISysConfigService { */ String checkConfigKeyUnique(SysConfig config); - SysConfig getOne(SysConfig config); - } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java index 8508d4f86..d821a4ab3 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java @@ -19,6 +19,14 @@ public interface ISysDeptService { */ List selectDeptList(SysDept dept); + /** + * 查询部门树结构信息 + * + * @param dept 部门信息 + * @return 部门树信息集合 + */ + List> selectDeptTreeList(SysDept dept); + /** * 构建前端所需要下拉树结构 * diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java index 504032ee1..3c5a04e65 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java @@ -54,7 +54,7 @@ public interface ISysDictDataService { * @param dictData 字典数据信息 * @return 结果 */ - int insertDictData(SysDictData dictData); + List insertDictData(SysDictData dictData); /** * 修改保存字典数据信息 @@ -62,5 +62,5 @@ public interface ISysDictDataService { * @param dictData 字典数据信息 * @return 结果 */ - int updateDictData(SysDictData dictData); + List updateDictData(SysDictData dictData); } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java index 5966e08c0..1bad68089 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java @@ -84,7 +84,7 @@ public interface ISysDictTypeService { * @param dictType 字典类型信息 * @return 结果 */ - int insertDictType(SysDictType dictType); + List insertDictType(SysDictType dictType); /** * 修改保存字典类型信息 @@ -92,7 +92,7 @@ public interface ISysDictTypeService { * @param dictType 字典类型信息 * @return 结果 */ - int updateDictType(SysDictType dictType); + List updateDictType(SysDictType dictType); /** * 校验字典类型称是否唯一 diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java index e7b5c9b37..813b1e282 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java @@ -39,6 +39,14 @@ public interface ISysMenuService { */ Set selectMenuPermsByUserId(Long userId); + /** + * 根据角色ID查询权限 + * + * @param roleId 角色ID + * @return 权限列表 + */ + Set selectMenuPermsByRoleId(Long roleId); + /** * 根据用户ID查询菜单树信息 * 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 c55e5bc12..6472cebcb 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 @@ -7,6 +7,8 @@ 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; @@ -21,9 +23,11 @@ public interface ISysOssService { List listByIds(Collection ossIds); - SysOss getById(Long ossId); + 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/ISysUserService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java index 9ecd86e6b..042efc2c9 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java @@ -83,10 +83,10 @@ public interface ISysUserService { /** * 校验用户名称是否唯一 * - * @param userName 用户名称 + * @param user 用户信息 * @return 结果 */ - String checkUserNameUnique(String userName); + String checkUserNameUnique(SysUser user); /** * 校验手机号码是否唯一 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 1a672e59c..a257fd988 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 @@ -1,9 +1,11 @@ package com.ruoyi.system.service; +import cn.dev33.satoken.exception.NotLoginException; import cn.dev33.satoken.secure.BCrypt; import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.ObjectUtil; +import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.core.domain.dto.RoleDTO; import com.ruoyi.common.core.domain.entity.SysUser; @@ -13,9 +15,7 @@ import com.ruoyi.common.core.service.LogininforService; import com.ruoyi.common.enums.DeviceType; import com.ruoyi.common.enums.LoginType; import com.ruoyi.common.enums.UserStatus; -import com.ruoyi.common.exception.user.CaptchaException; -import com.ruoyi.common.exception.user.CaptchaExpireException; -import com.ruoyi.common.exception.user.UserException; +import com.ruoyi.common.exception.user.*; import com.ruoyi.common.helper.LoginHelper; import com.ruoyi.common.utils.DateUtils; import com.ruoyi.common.utils.MessageUtils; @@ -24,6 +24,7 @@ import com.ruoyi.common.utils.StringUtils; import com.ruoyi.common.utils.redis.RedisUtils; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import javax.servlet.http.HttpServletRequest; @@ -46,6 +47,12 @@ public class SysLoginService { private final LogininforService asyncService; private final SysPermissionService permissionService; + @Value("${user.password.maxRetryCount}") + private Integer maxRetryCount; + + @Value("${user.password.lockTime}") + private Integer lockTime; + /** * 登录验证 * @@ -57,9 +64,9 @@ public class SysLoginService { */ public String login(String username, String password, String code, String uuid) { HttpServletRequest request = ServletUtils.getRequest(); - boolean captchaOnOff = configService.selectCaptchaOnOff(); + boolean captchaEnabled = configService.selectCaptchaEnabled(); // 验证码开关 - if (captchaOnOff) { + if (captchaEnabled) { validateCaptcha(username, code, uuid, request); } SysUser user = loadUserByUsername(username); @@ -113,16 +120,23 @@ public class SysLoginService { return StpUtil.getTokenValue(); } - - public void logout(String loginName) { - asyncService.recordLogininfor(loginName, Constants.LOGOUT, MessageUtils.message("user.logout.success"), ServletUtils.getRequest()); + /** + * 退出登录 + */ + public void logout() { + try { + LoginUser loginUser = LoginHelper.getLoginUser(); + StpUtil.logout(); + asyncService.recordLogininfor(loginUser.getUsername(), Constants.LOGOUT, MessageUtils.message("user.logout.success"), ServletUtils.getRequest()); + } catch (NotLoginException ignored) { + } } /** * 校验短信验证码 */ private boolean validateSmsCode(String phonenumber, String smsCode, HttpServletRequest request) { - String code = RedisUtils.getCacheObject(Constants.CAPTCHA_CODE_KEY + phonenumber); + String code = RedisUtils.getCacheObject(CacheConstants.CAPTCHA_CODE_KEY + phonenumber); if (StringUtils.isBlank(code)) { asyncService.recordLogininfor(phonenumber, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"), request); throw new CaptchaExpireException(); @@ -138,7 +152,7 @@ public class SysLoginService { * @param uuid 唯一标识 */ public void validateCaptcha(String username, String code, String uuid, HttpServletRequest request) { - String verifyKey = Constants.CAPTCHA_CODE_KEY + StringUtils.defaultString(uuid, ""); + String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.defaultString(uuid, ""); String captcha = RedisUtils.getCacheObject(verifyKey); RedisUtils.deleteObject(verifyKey); if (captcha == null) { @@ -234,27 +248,25 @@ public class SysLoginService { */ private void checkLogin(LoginType loginType, String username, Supplier supplier) { HttpServletRequest request = ServletUtils.getRequest(); - String errorKey = Constants.LOGIN_ERROR + username; - Integer errorLimitTime = Constants.LOGIN_ERROR_LIMIT_TIME; - Integer setErrorNumber = Constants.LOGIN_ERROR_NUMBER; + String errorKey = CacheConstants.PWD_ERR_CNT_KEY + username; String loginFail = Constants.LOGIN_FAIL; // 获取用户登录错误次数(可自定义限制策略 例如: key + username + ip) Integer errorNumber = RedisUtils.getCacheObject(errorKey); // 锁定时间内登录 则踢出 - if (ObjectUtil.isNotNull(errorNumber) && errorNumber.equals(setErrorNumber)) { - asyncService.recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), errorLimitTime), request); - throw new UserException(loginType.getRetryLimitExceed(), errorLimitTime); + if (ObjectUtil.isNotNull(errorNumber) && errorNumber.equals(maxRetryCount)) { + asyncService.recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime), request); + throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime); } if (supplier.get()) { // 是否第一次 errorNumber = ObjectUtil.isNull(errorNumber) ? 1 : errorNumber + 1; // 达到规定错误次数 则锁定登录 - if (errorNumber.equals(setErrorNumber)) { - RedisUtils.setCacheObject(errorKey, errorNumber, Duration.ofMinutes(errorLimitTime)); - asyncService.recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), errorLimitTime), request); - throw new UserException(loginType.getRetryLimitExceed(), errorLimitTime); + if (errorNumber.equals(maxRetryCount)) { + RedisUtils.setCacheObject(errorKey, errorNumber, Duration.ofMinutes(lockTime)); + asyncService.recordLogininfor(username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime), request); + throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime); } else { // 未达到规定错误次数 则递增 RedisUtils.setCacheObject(errorKey, errorNumber); diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/SysPermissionService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/SysPermissionService.java index a255fe818..97ff4801a 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/SysPermissionService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/SysPermissionService.java @@ -1,10 +1,12 @@ package com.ruoyi.system.service; +import com.ruoyi.common.core.domain.entity.SysRole; import com.ruoyi.common.core.domain.entity.SysUser; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import java.util.HashSet; +import java.util.List; import java.util.Set; /** @@ -48,7 +50,17 @@ public class SysPermissionService { if (user.isAdmin()) { perms.add("*:*:*"); } else { - perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId())); + List roles = user.getRoles(); + if (!roles.isEmpty() && roles.size() > 1) { + // 多角色设置permissions属性,以便数据权限匹配权限 + for (SysRole role : roles) { + Set rolePerms = menuService.selectMenuPermsByRoleId(role.getRoleId()); + role.setPermissions(rolePerms); + perms.addAll(rolePerms); + } + } else { + perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId())); + } } return perms; } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/SysRegisterService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/SysRegisterService.java index 8c7274ef8..983173d11 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/SysRegisterService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/SysRegisterService.java @@ -1,6 +1,7 @@ package com.ruoyi.system.service; import cn.dev33.satoken.secure.BCrypt; +import com.ruoyi.common.constant.CacheConstants; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.domain.entity.SysUser; @@ -42,20 +43,20 @@ public class SysRegisterService { // 校验用户类型是否存在 String userType = UserType.getUserType(registerBody.getUserType()).getUserType(); - boolean captchaOnOff = configService.selectCaptchaOnOff(); + boolean captchaEnabled = configService.selectCaptchaEnabled(); // 验证码开关 - if (captchaOnOff) { + if (captchaEnabled) { validateCaptcha(username, registerBody.getCode(), registerBody.getUuid(), request); } - - if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(username))) { - throw new UserException("user.register.save.error", username); - } SysUser sysUser = new SysUser(); sysUser.setUserName(username); sysUser.setNickName(username); sysUser.setPassword(BCrypt.hashpw(password)); sysUser.setUserType(userType); + + if (UserConstants.NOT_UNIQUE.equals(userService.checkUserNameUnique(sysUser))) { + throw new UserException("user.register.save.error", username); + } boolean regFlag = userService.registerUser(sysUser); if (!regFlag) { throw new UserException("user.register.error"); @@ -72,7 +73,7 @@ public class SysRegisterService { * @return 结果 */ public void validateCaptcha(String username, String code, String uuid, HttpServletRequest request) { - String verifyKey = Constants.CAPTCHA_CODE_KEY + StringUtils.defaultString(uuid, ""); + String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.defaultString(uuid, ""); String captcha = RedisUtils.getCacheObject(verifyKey); RedisUtils.deleteObject(verifyKey); if (captcha == null) { diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java index 070d1daed..72dc42bb4 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java @@ -5,22 +5,24 @@ import cn.hutool.core.util.ObjectUtil; import com.baomidou.dynamic.datasource.annotation.DS; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.constant.CacheNames; import com.ruoyi.common.constant.UserConstants; import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.service.ConfigService; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.redis.RedisUtils; +import com.ruoyi.common.utils.redis.CacheUtils; +import com.ruoyi.common.utils.spring.SpringUtils; import com.ruoyi.system.domain.SysConfig; import com.ruoyi.system.mapper.SysConfigMapper; import com.ruoyi.system.service.ISysConfigService; import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.CachePut; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import java.util.Arrays; -import java.util.Collection; import java.util.List; import java.util.Map; @@ -66,16 +68,12 @@ public class SysConfigServiceImpl implements ISysConfigService, ConfigService { * @param configKey 参数key * @return 参数键值 */ + @Cacheable(cacheNames = CacheNames.SYS_CONFIG, key = "#configKey") @Override public String selectConfigByKey(String configKey) { - String configValue = RedisUtils.getCacheObject(getCacheKey(configKey)); - if (StringUtils.isNotEmpty(configValue)) { - return configValue; - } SysConfig retConfig = baseMapper.selectOne(new LambdaQueryWrapper() .eq(SysConfig::getConfigKey, configKey)); if (ObjectUtil.isNotNull(retConfig)) { - RedisUtils.setCacheObject(getCacheKey(configKey), retConfig.getConfigValue()); return retConfig.getConfigValue(); } return StringUtils.EMPTY; @@ -87,12 +85,12 @@ public class SysConfigServiceImpl implements ISysConfigService, ConfigService { * @return true开启,false关闭 */ @Override - public boolean selectCaptchaOnOff() { - String captchaOnOff = selectConfigByKey("sys.account.captchaOnOff"); - if (StringUtils.isEmpty(captchaOnOff)) { + public boolean selectCaptchaEnabled() { + String captchaEnabled = SpringUtils.getAopProxy(this).selectConfigByKey("sys.account.captchaEnabled"); + if (StringUtils.isEmpty(captchaEnabled)) { return true; } - return Convert.toBool(captchaOnOff); + return Convert.toBool(captchaEnabled); } /** @@ -119,13 +117,14 @@ public class SysConfigServiceImpl implements ISysConfigService, ConfigService { * @param config 参数配置信息 * @return 结果 */ + @CachePut(cacheNames = CacheNames.SYS_CONFIG, key = "#config.configKey") @Override - public int insertConfig(SysConfig config) { + public String insertConfig(SysConfig config) { int row = baseMapper.insert(config); if (row > 0) { - RedisUtils.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()); + return config.getConfigValue(); } - return row; + throw new ServiceException("操作失败"); } /** @@ -134,8 +133,9 @@ public class SysConfigServiceImpl implements ISysConfigService, ConfigService { * @param config 参数配置信息 * @return 结果 */ + @CachePut(cacheNames = CacheNames.SYS_CONFIG, key = "#config.configKey") @Override - public int updateConfig(SysConfig config) { + public String updateConfig(SysConfig config) { int row = 0; if (config.getConfigId() != null) { row = baseMapper.updateById(config); @@ -144,9 +144,9 @@ public class SysConfigServiceImpl implements ISysConfigService, ConfigService { .eq(SysConfig::getConfigKey, config.getConfigKey())); } if (row > 0) { - RedisUtils.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()); + return config.getConfigValue(); } - return row; + throw new ServiceException("操作失败"); } /** @@ -161,7 +161,7 @@ public class SysConfigServiceImpl implements ISysConfigService, ConfigService { if (StringUtils.equals(UserConstants.YES, config.getConfigType())) { throw new ServiceException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey())); } - RedisUtils.deleteObject(getCacheKey(config.getConfigKey())); + CacheUtils.evict(CacheNames.SYS_CONFIG, config.getConfigKey()); } baseMapper.deleteBatchIds(Arrays.asList(configIds)); } @@ -172,9 +172,8 @@ public class SysConfigServiceImpl implements ISysConfigService, ConfigService { @Override public void loadingConfigCache() { List configsList = selectConfigList(new SysConfig()); - for (SysConfig config : configsList) { - RedisUtils.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue()); - } + configsList.forEach(config -> + CacheUtils.put(CacheNames.SYS_CONFIG, config.getConfigKey(), config.getConfigValue())); } /** @@ -182,8 +181,7 @@ public class SysConfigServiceImpl implements ISysConfigService, ConfigService { */ @Override public void clearConfigCache() { - Collection keys = RedisUtils.keys(Constants.SYS_CONFIG_KEY + "*"); - RedisUtils.deleteObject(keys); + CacheUtils.clear(CacheNames.SYS_CONFIG); } /** @@ -211,11 +209,6 @@ public class SysConfigServiceImpl implements ISysConfigService, ConfigService { return UserConstants.UNIQUE; } - @Override - public SysConfig getOne(SysConfig config) { - return baseMapper.selectOne(new LambdaQueryWrapper<>(config)); - } - /** * 根据参数 key 获取参数值 * @@ -224,16 +217,7 @@ public class SysConfigServiceImpl implements ISysConfigService, ConfigService { */ @Override public String getConfigValue(String configKey) { - return selectConfigByKey(configKey); + return SpringUtils.getAopProxy(this).selectConfigByKey(configKey); } - /** - * 设置cache key - * - * @param configKey 参数键 - * @return 缓存键key - */ - private String getCacheKey(String configKey) { - return Constants.SYS_CONFIG_KEY + configKey; - } } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDataScopeServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDataScopeServiceImpl.java index d2c5d5cb0..44f8625ec 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDataScopeServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDataScopeServiceImpl.java @@ -5,6 +5,7 @@ import cn.hutool.core.convert.Convert; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.ruoyi.common.core.domain.entity.SysDept; import com.ruoyi.common.helper.DataBaseHelper; +import com.ruoyi.common.utils.StreamUtils; import com.ruoyi.system.domain.SysRoleDept; import com.ruoyi.system.mapper.SysDeptMapper; import com.ruoyi.system.mapper.SysRoleDeptMapper; @@ -13,7 +14,6 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import java.util.List; -import java.util.stream.Collectors; /** * 数据权限 实现 @@ -37,7 +37,7 @@ public class SysDataScopeServiceImpl implements ISysDataScopeService { .select(SysRoleDept::getDeptId) .eq(SysRoleDept::getRoleId, roleId)); if (CollUtil.isNotEmpty(list)) { - return list.stream().map(rd -> Convert.toStr(rd.getDeptId())).collect(Collectors.joining(",")); + return StreamUtils.join(list, rd -> Convert.toStr(rd.getDeptId())); } return null; } @@ -47,13 +47,13 @@ public class SysDataScopeServiceImpl implements ISysDataScopeService { List deptList = deptMapper.selectList(new LambdaQueryWrapper() .select(SysDept::getDeptId) .apply(DataBaseHelper.findInSet(deptId, "ancestors"))); - List ids = deptList.stream().map(SysDept::getDeptId).collect(Collectors.toList()); + List ids = StreamUtils.toList(deptList, SysDept::getDeptId); ids.add(deptId); List list = deptMapper.selectList(new LambdaQueryWrapper() .select(SysDept::getDeptId) .in(SysDept::getDeptId, ids)); if (CollUtil.isNotEmpty(list)) { - return list.stream().map(d -> Convert.toStr(d.getDeptId())).collect(Collectors.joining(",")); + return StreamUtils.join(list, d -> Convert.toStr(d.getDeptId())); } return null; } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java index 32e06d3d4..00b402467 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java @@ -58,6 +58,18 @@ public class SysDeptServiceImpl implements ISysDeptService { return baseMapper.selectDeptList(lqw); } + /** + * 查询部门树结构信息 + * + * @param dept 部门信息 + * @return 部门树信息集合 + */ + @Override + public List> selectDeptTreeList(SysDept dept) { + List depts = this.selectDeptList(dept); + return buildDeptTreeSelect(depts); + } + /** * 构建前端所需要下拉树结构 * @@ -96,7 +108,11 @@ public class SysDeptServiceImpl implements ISysDeptService { */ @Override public SysDept selectDeptById(Long deptId) { - return baseMapper.selectById(deptId); + SysDept dept = baseMapper.selectById(deptId); + SysDept parentDept = baseMapper.selectOne(new LambdaQueryWrapper() + .select(SysDept::getDeptName).eq(SysDept::getDeptId, dept.getParentId())); + dept.setParentName(ObjectUtil.isNotNull(parentDept) ? parentDept.getDeptName() : null); + return dept; } /** diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java index 03de7c5e4..6b80cf482 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java @@ -2,15 +2,17 @@ package com.ruoyi.system.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.constant.CacheNames; import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.domain.entity.SysDictData; import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.redis.RedisUtils; +import com.ruoyi.common.utils.redis.CacheUtils; import com.ruoyi.system.mapper.SysDictDataMapper; import com.ruoyi.system.service.ISysDictDataService; import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.CachePut; import org.springframework.stereotype.Service; import java.util.List; @@ -89,8 +91,7 @@ public class SysDictDataServiceImpl implements ISysDictDataService { for (Long dictCode : dictCodes) { SysDictData data = selectDictDataById(dictCode); baseMapper.deleteById(dictCode); - List dictDatas = baseMapper.selectDictDataByType(data.getDictType()); - RedisUtils.setCacheObject(getCacheKey(data.getDictType()), dictDatas); + CacheUtils.evict(CacheNames.SYS_DICT, data.getDictType()); } } @@ -100,14 +101,14 @@ public class SysDictDataServiceImpl implements ISysDictDataService { * @param data 字典数据信息 * @return 结果 */ + @CachePut(cacheNames = CacheNames.SYS_DICT, key = "#data.dictType") @Override - public int insertDictData(SysDictData data) { + public List insertDictData(SysDictData data) { int row = baseMapper.insert(data); if (row > 0) { - List dictDatas = baseMapper.selectDictDataByType(data.getDictType()); - RedisUtils.setCacheObject(getCacheKey(data.getDictType()), dictDatas); + return baseMapper.selectDictDataByType(data.getDictType()); } - return row; + throw new ServiceException("操作失败"); } /** @@ -116,23 +117,14 @@ public class SysDictDataServiceImpl implements ISysDictDataService { * @param data 字典数据信息 * @return 结果 */ + @CachePut(cacheNames = CacheNames.SYS_DICT, key = "#data.dictType") @Override - public int updateDictData(SysDictData data) { + public List updateDictData(SysDictData data) { int row = baseMapper.updateById(data); if (row > 0) { - List dictDatas = baseMapper.selectDictDataByType(data.getDictType()); - RedisUtils.setCacheObject(getCacheKey(data.getDictType()), dictDatas); + return baseMapper.selectDictDataByType(data.getDictType()); } - return row; + throw new ServiceException("操作失败"); } - /** - * 设置cache key - * - * @param configKey 参数键 - * @return 缓存键key - */ - String getCacheKey(String configKey) { - return Constants.SYS_DICT_KEY + configKey; - } } 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 61d178865..d7244116a 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,11 +1,13 @@ 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.Constants; +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; import com.ruoyi.common.core.domain.entity.SysDictData; @@ -13,12 +15,16 @@ import com.ruoyi.common.core.domain.entity.SysDictType; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.core.service.DictService; import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.StreamUtils; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.redis.RedisUtils; +import com.ruoyi.common.utils.redis.CacheUtils; +import com.ruoyi.common.utils.spring.SpringUtils; import com.ruoyi.system.mapper.SysDictDataMapper; import com.ruoyi.system.mapper.SysDictTypeMapper; import com.ruoyi.system.service.ISysDictTypeService; import lombok.RequiredArgsConstructor; +import org.springframework.cache.annotation.CachePut; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -83,17 +89,13 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService * @param dictType 字典类型 * @return 字典数据集合信息 */ + @Cacheable(cacheNames = CacheNames.SYS_DICT, key = "#dictType") @Override public List selectDictDataByType(String dictType) { - List dictDatas = RedisUtils.getCacheObject(getCacheKey(dictType)); + List dictDatas = dictDataMapper.selectDictDataByType(dictType); if (CollUtil.isNotEmpty(dictDatas)) { return dictDatas; } - dictDatas = dictDataMapper.selectDictDataByType(dictType); - if (CollUtil.isNotEmpty(dictDatas)) { - RedisUtils.setCacheObject(getCacheKey(dictType), dictDatas); - return dictDatas; - } return null; } @@ -114,6 +116,7 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService * @param dictType 字典类型 * @return 字典类型 */ + @Cacheable(cacheNames = CacheNames.SYS_DICT, key = "#dictType") @Override public SysDictType selectDictTypeByType(String dictType) { return baseMapper.selectById(new LambdaQueryWrapper().eq(SysDictType::getDictType, dictType)); @@ -132,7 +135,7 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService .eq(SysDictData::getDictType, dictType.getDictType()))) { throw new ServiceException(String.format("%1$s已分配,不能删除", dictType.getDictName())); } - RedisUtils.deleteObject(getCacheKey(dictType.getDictType())); + CacheUtils.evict(CacheNames.SYS_DICT, dictType.getDictType()); } baseMapper.deleteBatchIds(Arrays.asList(dictIds)); } @@ -144,13 +147,10 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService public void loadingDictCache() { List dictDataList = dictDataMapper.selectList( new LambdaQueryWrapper().eq(SysDictData::getStatus, UserConstants.DICT_NORMAL)); - Map> dictDataMap = dictDataList.stream().collect(Collectors.groupingBy(SysDictData::getDictType)); + Map> dictDataMap = StreamUtils.groupByKey(dictDataList, SysDictData::getDictType); dictDataMap.forEach((k,v) -> { - String dictKey = getCacheKey(k); - List dictList = v.stream() - .sorted(Comparator.comparing(SysDictData::getDictSort)) - .collect(Collectors.toList()); - RedisUtils.setCacheObject(dictKey, dictList); + List dictList = StreamUtils.sorted(v, Comparator.comparing(SysDictData::getDictSort)); + CacheUtils.put(CacheNames.SYS_DICT, k, dictList); }); } @@ -159,8 +159,7 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService */ @Override public void clearDictCache() { - Collection keys = RedisUtils.keys(Constants.SYS_DICT_KEY + "*"); - RedisUtils.deleteObject(keys); + CacheUtils.clear(CacheNames.SYS_DICT); } /** @@ -178,13 +177,14 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService * @param dict 字典类型信息 * @return 结果 */ + @CachePut(cacheNames = CacheNames.SYS_DICT, key = "#dict.dictType") @Override - public int insertDictType(SysDictType dict) { + public List insertDictType(SysDictType dict) { int row = baseMapper.insert(dict); if (row > 0) { - RedisUtils.setCacheObject(getCacheKey(dict.getDictType()), null); + return new ArrayList<>(); } - return row; + throw new ServiceException("操作失败"); } /** @@ -193,19 +193,20 @@ public class SysDictTypeServiceImpl implements ISysDictTypeService, DictService * @param dict 字典类型信息 * @return 结果 */ + @CachePut(cacheNames = CacheNames.SYS_DICT, key = "#dict.dictType") @Override @Transactional(rollbackFor = Exception.class) - public int updateDictType(SysDictType dict) { + public List updateDictType(SysDictType dict) { SysDictType oldDict = baseMapper.selectById(dict.getDictId()); dictDataMapper.update(null, new LambdaUpdateWrapper() .set(SysDictData::getDictType, dict.getDictType()) .eq(SysDictData::getDictType, oldDict.getDictType())); int row = baseMapper.updateById(dict); if (row > 0) { - List dictDatas = dictDataMapper.selectDictDataByType(dict.getDictType()); - RedisUtils.setCacheObject(getCacheKey(dict.getDictType()), dictDatas); + CacheUtils.evict(CacheNames.SYS_DICT, oldDict.getDictType()); + return dictDataMapper.selectDictDataByType(dict.getDictType()); } - return row; + throw new ServiceException("操作失败"); } /** @@ -233,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 = 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); } /** @@ -265,37 +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 = 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); } - /** - * 设置cache key - * - * @param configKey 参数键 - * @return 缓存键key - */ - String getCacheKey(String configKey) { - return Constants.SYS_DICT_KEY + configKey; - } } 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 6525d31e9..4d3406757 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; @@ -97,6 +98,24 @@ public class SysMenuServiceImpl implements ISysMenuService { return permsSet; } + /** + * 根据角色ID查询权限 + * + * @param roleId 角色ID + * @return 权限列表 + */ + @Override + public Set selectMenuPermsByRoleId(Long roleId) { + List perms = baseMapper.selectMenuPermsByRoleId(roleId); + Set permsSet = new HashSet<>(); + for (String perm : perms) { + if (StringUtils.isNotEmpty(perm)) { + permsSet.addAll(Arrays.asList(perm.trim().split(","))); + } + } + return permsSet; + } + /** * 根据用户ID查询菜单 * @@ -407,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())); } /** @@ -425,11 +438,9 @@ public class SysMenuServiceImpl implements ISysMenuService { /** * 内链域名特殊字符替换 - * - * @return */ public String innerLinkReplaceEach(String path) { - return StringUtils.replaceEach(path, new String[]{Constants.HTTP, Constants.HTTPS}, - new String[]{"", ""}); + return StringUtils.replaceEach(path, new String[]{Constants.HTTP, Constants.HTTPS, Constants.WWW, "."}, + new String[]{"", "", "", "/"}); } } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssConfigServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssConfigServiceImpl.java index 015c156ab..8ceff7cb5 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssConfigServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOssConfigServiceImpl.java @@ -7,13 +7,14 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.google.common.collect.Lists; +import com.ruoyi.common.constant.CacheNames; import com.ruoyi.common.constant.UserConstants; 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.JsonUtils; import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.redis.CacheUtils; import com.ruoyi.common.utils.redis.RedisUtils; import com.ruoyi.oss.constant.OssConstant; import com.ruoyi.oss.factory.OssFactory; @@ -54,7 +55,7 @@ public class SysOssConfigServiceImpl implements ISysOssConfigService { for (SysOssConfig config : list) { String configKey = config.getConfigKey(); if ("0".equals(config.getStatus())) { - RedisUtils.setCacheObject(OssConstant.CACHE_CONFIG_KEY, configKey); + RedisUtils.setCacheObject(OssConstant.DEFAULT_CONFIG_KEY, configKey); } setConfigCache(true, config); } @@ -120,16 +121,15 @@ public class SysOssConfigServiceImpl implements ISysOssConfigService { throw new ServiceException("系统内置, 不可删除!"); } } - List list = Lists.newArrayList(); + List list = CollUtil.newArrayList(); for (Long configId : ids) { SysOssConfig config = baseMapper.selectById(configId); list.add(config); } boolean flag = baseMapper.deleteBatchIds(ids) > 0; if (flag) { - list.stream().forEach(sysOssConfig -> { - RedisUtils.deleteObject(getCacheKey(sysOssConfig.getConfigKey())); - }); + list.forEach(sysOssConfig -> + CacheUtils.evict(CacheNames.SYS_OSS_CONFIG, sysOssConfig.getConfigKey())); } return flag; } @@ -159,21 +159,11 @@ public class SysOssConfigServiceImpl implements ISysOssConfigService { .set(SysOssConfig::getStatus, "1")); row += baseMapper.updateById(sysOssConfig); if (row > 0) { - RedisUtils.setCacheObject(OssConstant.CACHE_CONFIG_KEY, sysOssConfig.getConfigKey()); + RedisUtils.setCacheObject(OssConstant.DEFAULT_CONFIG_KEY, sysOssConfig.getConfigKey()); } return row; } - /** - * 设置cache key - * - * @param configKey 参数键 - * @return 缓存键key - */ - private String getCacheKey(String configKey) { - return OssConstant.SYS_OSS_KEY + configKey; - } - /** * 如果操作成功 则更新缓存 * @@ -183,10 +173,8 @@ public class SysOssConfigServiceImpl implements ISysOssConfigService { */ private boolean setConfigCache(boolean flag, SysOssConfig config) { if (flag) { - RedisUtils.setCacheObject( - getCacheKey(config.getConfigKey()), - JsonUtils.toJsonString(config)); - RedisUtils.publish(OssConstant.CACHE_CONFIG_KEY, config.getConfigKey(), msg -> { + CacheUtils.put(CacheNames.SYS_OSS_CONFIG, config.getConfigKey(), JsonUtils.toJsonString(config)); + RedisUtils.publish(OssConstant.DEFAULT_CONFIG_KEY, config.getConfigKey(), msg -> { log.info("发布刷新OSS配置 => " + msg); }); } 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 03a6cfca8..cd9bffb14 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,17 +1,21 @@ 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; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +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.redis.RedisUtils; -import com.ruoyi.oss.constant.OssConstant; +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; @@ -19,15 +23,19 @@ import com.ruoyi.system.domain.vo.SysOssVo; 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.time.Duration; +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); } @@ -51,13 +61,10 @@ public class SysOssServiceImpl implements ISysOssService { public List listByIds(Collection ossIds) { List list = new ArrayList<>(); for (Long id : ossIds) { - String key = OssConstant.SYS_OSS_KEY + id; - SysOssVo vo = RedisUtils.getCacheObject(key); - if (ObjectUtil.isNull(vo)) { - vo = baseMapper.selectVoById(id); - RedisUtils.setCacheObject(key, vo, Duration.ofDays(30)); + SysOssVo vo = SpringUtils.getAopProxy(this).getById(id); + if (ObjectUtil.isNotNull(vo)) { + list.add(this.matchingUrl(vo)); } - list.add(vo); } return list; } @@ -76,13 +83,32 @@ public class SysOssServiceImpl implements ISysOssService { return lqw; } + @Cacheable(cacheNames = CacheNames.SYS_OSS, key = "#ossId") @Override - public SysOss getById(Long ossId) { - return baseMapper.selectById(ossId); + public SysOssVo getById(Long ossId) { + return baseMapper.selectVoById(ossId); } @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(); @@ -100,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 @@ -116,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-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java index ed24ab4e9..4e63f17ea 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java @@ -18,6 +18,7 @@ import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.helper.DataBaseHelper; import com.ruoyi.common.helper.LoginHelper; +import com.ruoyi.common.utils.StreamUtils; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.system.domain.SysPost; import com.ruoyi.system.domain.SysUserPost; @@ -33,7 +34,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; /** * 用户 业务层处理 @@ -83,7 +83,7 @@ public class SysUserServiceImpl implements ISysUserService { List deptList = deptMapper.selectList(new LambdaQueryWrapper() .select(SysDept::getDeptId) .apply(DataBaseHelper.findInSet(user.getDeptId(), "ancestors"))); - List ids = deptList.stream().map(SysDept::getDeptId).collect(Collectors.toList()); + List ids = StreamUtils.toList(deptList, SysDept::getDeptId); ids.add(user.getDeptId()); w.in("u.dept_id", ids); }); @@ -172,7 +172,7 @@ public class SysUserServiceImpl implements ISysUserService { if (CollUtil.isEmpty(list)) { return StringUtils.EMPTY; } - return list.stream().map(SysRole::getRoleName).collect(Collectors.joining(",")); + return StreamUtils.join(list, SysRole::getRoleName); } /** @@ -187,18 +187,20 @@ public class SysUserServiceImpl implements ISysUserService { if (CollUtil.isEmpty(list)) { return StringUtils.EMPTY; } - return list.stream().map(SysPost::getPostName).collect(Collectors.joining(",")); + return StreamUtils.join(list, SysPost::getPostName); } /** * 校验用户名称是否唯一 * - * @param userName 用户名称 + * @param user 用户信息 * @return 结果 */ @Override - public String checkUserNameUnique(String userName) { - boolean exist = baseMapper.exists(new LambdaQueryWrapper().eq(SysUser::getUserName, userName)); + public String checkUserNameUnique(SysUser user) { + boolean exist = baseMapper.exists(new LambdaQueryWrapper() + .eq(SysUser::getUserName, user.getUserName()) + .ne(ObjectUtil.isNotNull(user.getUserId()), SysUser::getUserId, user.getUserId())); if (exist) { return UserConstants.NOT_UNIQUE; } diff --git a/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml index 2f69197b3..d308d8d0b 100644 --- a/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml @@ -95,4 +95,11 @@ and sur.user_id = #{userId} + + diff --git a/ruoyi-ui/.env.staging b/ruoyi-ui/.env.staging deleted file mode 100644 index 903abe658..000000000 --- a/ruoyi-ui/.env.staging +++ /dev/null @@ -1,19 +0,0 @@ -# 页面标题 -VUE_APP_TITLE = RuoYi-Vue-Plus后台管理系统 - -NODE_ENV = production - -# 测试环境配置 -ENV = 'staging' - -# 应用访问路径 例如使用前缀 /admin/ -VUE_APP_CONTEXT_PATH = '/' - -# 监控地址 -VUE_APP_MONITRO_ADMIN = '/admin/login' - -# 监控地址 -VUE_APP_XXL_JOB_ADMIN = '/xxl-job-admin' - -# 若依管理系统/测试环境 -VUE_APP_BASE_API = '/stage-api' diff --git a/ruoyi-ui/bin/package.bat b/ruoyi-ui/bin/package.bat index 9f6e5f4db..2f22a4ada 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 3e209d772..0318c525d 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/package.json b/ruoyi-ui/package.json index c9486724f..48ba1f9a4 100644 --- a/ruoyi-ui/package.json +++ b/ruoyi-ui/package.json @@ -1,13 +1,12 @@ { "name": "ruoyi-vue-plus", - "version": "4.2.0", + "version": "4.4.0", "description": "RuoYi-Vue-Plus后台管理系统", "author": "LionLi", "license": "MIT", "scripts": { "dev": "vue-cli-service serve", "build:prod": "vue-cli-service build", - "build:stage": "vue-cli-service build --mode staging", "preview": "node build/index.js --preview", "lint": "eslint --ext .js,.vue src" }, @@ -39,9 +38,9 @@ "@riophae/vue-treeselect": "0.4.0", "axios": "0.24.0", "clipboard": "2.0.8", - "core-js": "3.19.1", + "core-js": "3.25.3", "echarts": "4.9.0", - "element-ui": "2.15.8", + "element-ui": "2.15.10", "file-saver": "2.0.5", "fuse.js": "6.4.3", "highlight.js": "9.18.5", diff --git a/ruoyi-ui/src/App.vue b/ruoyi-ui/src/App.vue index 391d951c4..29de49f15 100644 --- a/ruoyi-ui/src/App.vue +++ b/ruoyi-ui/src/App.vue @@ -1,12 +1,16 @@ + diff --git a/ruoyi-ui/src/api/monitor/cache.js b/ruoyi-ui/src/api/monitor/cache.js index 2ffaf7a3f..5cf051780 100644 --- a/ruoyi-ui/src/api/monitor/cache.js +++ b/ruoyi-ui/src/api/monitor/cache.js @@ -1,9 +1,57 @@ -import request from '@/utils/request' - -// 查询缓存详细 -export function getCache() { - return request({ - url: '/monitor/cache', - method: 'get' - }) -} +import request from '@/utils/request' + +// 查询缓存详细 +export function getCache() { + return request({ + url: '/monitor/cache', + method: 'get' + }) +} + +// 查询缓存名称列表 +export function listCacheName() { + return request({ + url: '/monitor/cache/getNames', + method: 'get' + }) +} + +// 查询缓存键名列表 +export function listCacheKey(cacheName) { + return request({ + url: '/monitor/cache/getKeys/' + cacheName, + method: 'get' + }) +} + +// 查询缓存内容 +export function getCacheValue(cacheName, cacheKey) { + return request({ + url: '/monitor/cache/getValue/' + cacheName + '/' + cacheKey, + method: 'get' + }) +} + +// 清理指定名称缓存 +export function clearCacheName(cacheName) { + return request({ + url: '/monitor/cache/clearCacheName/' + cacheName, + method: 'delete' + }) +} + +// 清理指定键名缓存 +export function clearCacheKey(cacheName, cacheKey) { + return request({ + url: '/monitor/cache/clearCacheKey/'+ cacheName + "/" + cacheKey, + method: 'delete' + }) +} + +// 清理全部缓存 +export function clearCacheAll() { + return request({ + url: '/monitor/cache/clearCacheAll', + method: 'delete' + }) +} diff --git a/ruoyi-ui/src/api/monitor/logininfor.js b/ruoyi-ui/src/api/monitor/logininfor.js index 26a46eb56..4d112b78a 100644 --- a/ruoyi-ui/src/api/monitor/logininfor.js +++ b/ruoyi-ui/src/api/monitor/logininfor.js @@ -17,6 +17,14 @@ export function delLogininfor(infoId) { }) } +// 解锁用户登录状态 +export function unlockLogininfor(userName) { + return request({ + url: '/monitor/logininfor/unlock/' + userName, + method: 'get' + }) +} + // 清空登录日志 export function cleanLogininfor() { return request({ diff --git a/ruoyi-ui/src/api/system/dept.js b/ruoyi-ui/src/api/system/dept.js index 2804676ff..331c4b2c1 100644 --- a/ruoyi-ui/src/api/system/dept.js +++ b/ruoyi-ui/src/api/system/dept.js @@ -25,22 +25,6 @@ export function getDept(deptId) { }) } -// 查询部门下拉树结构 -export function treeselect() { - return request({ - url: '/system/dept/treeselect', - method: 'get' - }) -} - -// 根据角色ID查询部门树结构 -export function roleDeptTreeselect(roleId) { - return request({ - url: '/system/dept/roleDeptTreeselect/' + roleId, - method: 'get' - }) -} - // 新增部门 export function addDept(data) { return request({ @@ -65,4 +49,4 @@ export function delDept(deptId) { url: '/system/dept/' + deptId, method: 'delete' }) -} \ No newline at end of file +} diff --git a/ruoyi-ui/src/api/system/ossConfig.js b/ruoyi-ui/src/api/system/ossConfig.js index 175325e87..f29076283 100644 --- a/ruoyi-ui/src/api/system/ossConfig.js +++ b/ruoyi-ui/src/api/system/ossConfig.js @@ -43,7 +43,7 @@ export function delOssConfig(ossConfigId) { }) } -// 用户状态修改 +// 对象存储状态修改 export function changeOssConfigStatus(ossConfigId, status, configKey) { const data = { ossConfigId, diff --git a/ruoyi-ui/src/api/system/role.js b/ruoyi-ui/src/api/system/role.js index 888538e55..f13e6f404 100644 --- a/ruoyi-ui/src/api/system/role.js +++ b/ruoyi-ui/src/api/system/role.js @@ -109,3 +109,11 @@ export function authUserSelectAll(data) { params: data }) } + +// 根据角色ID查询部门树结构 +export function deptTreeSelect(roleId) { + return request({ + url: '/system/role/deptTree/' + roleId, + method: 'get' + }) +} diff --git a/ruoyi-ui/src/api/system/user.js b/ruoyi-ui/src/api/system/user.js index 4fd752b4b..f2f76ef9f 100644 --- a/ruoyi-ui/src/api/system/user.js +++ b/ruoyi-ui/src/api/system/user.js @@ -125,3 +125,11 @@ export function updateAuthRole(data) { params: data }) } + +// 查询部门下拉树结构 +export function deptTreeSelect() { + return request({ + url: '/system/user/deptTree', + method: 'get' + }) +} diff --git a/ruoyi-ui/src/assets/icons/svg/code.svg b/ruoyi-ui/src/assets/icons/svg/code.svg index ed4d23cf4..5f9c5abd5 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/redis-list.svg b/ruoyi-ui/src/assets/icons/svg/redis-list.svg new file mode 100644 index 000000000..98a15b2a6 --- /dev/null +++ b/ruoyi-ui/src/assets/icons/svg/redis-list.svg @@ -0,0 +1,2 @@ + \ 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 ca37b001e..eb287e36c 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 dba28cf6f..5992593e0 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 c813067ef..48e0e3573 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 e9608771a..16a4740f4 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 { @@ -264,9 +263,10 @@ } .avatar-upload-preview { - position: absolute; + position: relative; top: 50%; - transform: translate(50%, -50%); + left: 50%; + transform: translate(-50%, -50%); width: 200px; height: 200px; border-radius: 50%; diff --git a/ruoyi-ui/src/assets/styles/transition.scss b/ruoyi-ui/src/assets/styles/transition.scss index 4cb27cc81..eb4989554 100644 --- a/ruoyi-ui/src/assets/styles/transition.scss +++ b/ruoyi-ui/src/assets/styles/transition.scss @@ -12,11 +12,16 @@ } /* fade-transform */ +.fade-transform--move, .fade-transform-leave-active, .fade-transform-enter-active { transition: all .5s; } +.fade-transform-leave-active { + position: absolute; +} + .fade-transform-enter { opacity: 0; transform: translateX(-30px); diff --git a/ruoyi-ui/src/components/DictData/index.js b/ruoyi-ui/src/components/DictData/index.js index 24e3e9c83..d43d81657 100644 --- a/ruoyi-ui/src/components/DictData/index.js +++ b/ruoyi-ui/src/components/DictData/index.js @@ -1,7 +1,23 @@ import Vue from 'vue' +import store from '@/store' import DataDict from '@/utils/dict' import { getDicts as getDicts } from '@/api/system/dict/data' +function searchDictByKey(dict, key) { + if (key == null && key == "") { + return null + } + try { + for (let i = 0; i < dict.length; i++) { + if (dict[i].key == key) { + return dict[i].value + } + } + } catch (e) { + return null + } +} + function install() { Vue.use(DataDict, { metas: { @@ -9,7 +25,19 @@ function install() { labelField: 'dictLabel', valueField: 'dictValue', request(dictMeta) { - return getDicts(dictMeta.type).then(res => res.data) + const storeDict = searchDictByKey(store.getters.dict, dictMeta.type) + if (storeDict) { + return new Promise(resolve => { resolve(storeDict) }) + } else { + return new Promise((resolve, reject) => { + getDicts(dictMeta.type).then(res => { + store.dispatch('dict/setDict', { key: dictMeta.type, value: res.data }) + resolve(res.data) + }).catch(error => { + reject(error) + }) + }) + } }, }, }, diff --git a/ruoyi-ui/src/components/FileUpload/index.vue b/ruoyi-ui/src/components/FileUpload/index.vue index e999f14f8..2e33c1b77 100644 --- a/ruoyi-ui/src/components/FileUpload/index.vue +++ b/ruoyi-ui/src/components/FileUpload/index.vue @@ -12,7 +12,7 @@ :show-file-list="false" :headers="headers" class="upload-file-uploader" - ref="upload" + ref="fileUpload" > 选取文件 @@ -74,7 +74,7 @@ export default { number: 0, uploadList: [], baseUrl: process.env.VUE_APP_BASE_API, - uploadFileUrl: process.env.VUE_APP_BASE_API + "/system/oss/upload", // 上传的图片服务器地址 + uploadFileUrl: process.env.VUE_APP_BASE_API + "/system/oss/upload", // 上传文件服务器地址 headers: { Authorization: "Bearer " + getToken(), }, @@ -124,15 +124,9 @@ export default { handleBeforeUpload(file) { // 校检文件类型 if (this.fileType) { - let fileExtension = ""; - if (file.name.lastIndexOf(".") > -1) { - fileExtension = file.name.slice(file.name.lastIndexOf(".") + 1); - } - const isTypeOk = this.fileType.some((type) => { - if (file.type.indexOf(type) > -1) return true; - if (fileExtension && fileExtension.indexOf(type) > -1) return true; - return false; - }); + const fileName = file.name.split('.'); + const fileExt = fileName[fileName.length - 1]; + const isTypeOk = this.fileType.indexOf(fileExt) >= 0; if (!isTypeOk) { this.$modal.msgError(`文件格式不正确, 请上传${this.fileType.join("/")}格式文件!`); return false; @@ -156,23 +150,20 @@ export default { }, // 上传失败 handleUploadError(err) { - this.$modal.msgError("上传图片失败,请重试"); - this.$modal.closeLoading() + this.$modal.msgError("上传文件失败,请重试"); + this.$modal.closeLoading(); }, // 上传成功回调 handleUploadSuccess(res, file) { if (res.code === 200) { this.uploadList.push({ name: res.data.fileName, url: res.data.url, ossId: res.data.ossId }); - if (this.uploadList.length === this.number) { - this.fileList = this.fileList.concat(this.uploadList); - this.uploadList = []; - this.number = 0; - this.$emit("input", this.listToString(this.fileList)); - this.$modal.closeLoading(); - } + this.uploadedSuccessfully(); } else { - this.$modal.msgError(res.msg); + this.number--; this.$modal.closeLoading(); + this.$modal.msgError(res.msg); + this.$refs.fileUpload.handleRemove(file); + this.uploadedSuccessfully(); } }, // 删除文件 @@ -182,6 +173,16 @@ export default { this.fileList.splice(index, 1); this.$emit("input", this.listToString(this.fileList)); }, + // 上传结束处理 + uploadedSuccessfully() { + if (this.number > 0 && this.uploadList.length === this.number) { + this.fileList = this.fileList.concat(this.uploadList); + this.uploadList = []; + this.number = 0; + this.$emit("input", this.listToString(this.fileList)); + this.$modal.closeLoading(); + } + }, // 获取文件名称 getFileName(name) { // 如果是url那么取最后的名字 如果不是直接返回 diff --git a/ruoyi-ui/src/components/ImagePreview/index.vue b/ruoyi-ui/src/components/ImagePreview/index.vue index 671eda323..cd996262a 100644 --- a/ruoyi-ui/src/components/ImagePreview/index.vue +++ b/ruoyi-ui/src/components/ImagePreview/index.vue @@ -18,7 +18,7 @@ export default { props: { src: { type: String, - required: true + default: "" }, width: { type: [Number, String], @@ -31,10 +31,16 @@ export default { }, computed: { realSrc() { + if (!this.src) { + return; + } let real_src = this.src.split(",")[0]; return real_src; }, realSrcList() { + if (!this.src) { + return; + } let real_src_list = this.src.split(","); let srcList = []; real_src_list.forEach(item => { diff --git a/ruoyi-ui/src/components/ImageUpload/index.vue b/ruoyi-ui/src/components/ImageUpload/index.vue index 62199795d..9c92e86bc 100644 --- a/ruoyi-ui/src/components/ImageUpload/index.vue +++ b/ruoyi-ui/src/components/ImageUpload/index.vue @@ -9,8 +9,8 @@ :limit="limit" :on-error="handleUploadError" :on-exceed="handleExceed" - name="file" - :on-remove="handleRemove" + ref="imageUpload" + :on-remove="handleDelete" :show-file-list="true" :headers="headers" :file-list="fileList" @@ -120,32 +120,6 @@ export default { }, }, methods: { - // 删除图片 - handleRemove(file, fileList) { - const findex = this.fileList.map(f => f.name).indexOf(file.name); - if(findex > -1) { - let ossId = this.fileList[findex].ossId; - delOss(ossId); - this.fileList.splice(findex, 1); - this.$emit("input", this.listToString(this.fileList)); - } - }, - // 上传成功回调 - handleUploadSuccess(res) { - if (res.code == 200) { - this.uploadList.push({ name: res.data.fileName, url: res.data.url, ossId: res.data.ossId }); - if (this.uploadList.length === this.number) { - this.fileList = this.fileList.concat(this.uploadList); - this.uploadList = []; - this.number = 0; - this.$emit("input", this.listToString(this.fileList)); - this.$modal.closeLoading(); - } - } else { - this.$modal.msgError(res.msg); - this.$modal.closeLoading(); - } - }, // 上传前loading加载 handleBeforeUpload(file) { let isImg = false; @@ -181,11 +155,44 @@ export default { handleExceed() { this.$modal.msgError(`上传文件数量不能超过 ${this.limit} 个!`); }, + // 上传成功回调 + handleUploadSuccess(res, file) { + if (res.code === 200) { + this.uploadList.push({ name: res.data.fileName, url: res.data.url, ossId: res.data.ossId }); + this.uploadedSuccessfully(); + } else { + this.number--; + this.$modal.closeLoading(); + this.$modal.msgError(res.msg); + this.$refs.imageUpload.handleRemove(file); + this.uploadedSuccessfully(); + } + }, + // 删除图片 + handleDelete(file) { + const findex = this.fileList.map(f => f.name).indexOf(file.name); + if(findex > -1) { + let ossId = this.fileList[findex].ossId; + delOss(ossId); + this.fileList.splice(findex, 1); + this.$emit("input", this.listToString(this.fileList)); + } + }, // 上传失败 handleUploadError(res) { this.$modal.msgError("上传图片失败,请重试"); this.$modal.closeLoading(); }, + // 上传结束处理 + uploadedSuccessfully() { + if (this.number > 0 && this.uploadList.length === this.number) { + this.fileList = this.fileList.concat(this.uploadList); + this.uploadList = []; + this.number = 0; + this.$emit("input", this.listToString(this.fileList)); + this.$modal.closeLoading(); + } + }, // 预览 handlePictureCardPreview(file) { this.dialogImageUrl = file.url; @@ -196,10 +203,12 @@ export default { let strs = ""; separator = separator || ","; for (let i in list) { - strs += list[i].ossId + separator; + if (list[i].ossId) { + strs += list[i].ossId + separator; + } } return strs != "" ? strs.substr(0, strs.length - 1) : ""; - }, + } } }; diff --git a/ruoyi-ui/src/components/RightPanel/index.vue b/ruoyi-ui/src/components/RightPanel/index.vue index fbf27eb4f..2d6122bc0 100644 --- a/ruoyi-ui/src/components/RightPanel/index.vue +++ b/ruoyi-ui/src/components/RightPanel/index.vue @@ -1,5 +1,5 @@ - -