Explorar o código

!86 同步dev分支
Merge pull request !86 from 疯狂的狮子Li/dev

疯狂的狮子Li %!s(int64=3) %!d(string=hai) anos
pai
achega
c2efaa5c3c
Modificáronse 100 ficheiros con 1121 adicións e 555 borrados
  1. 0 3
      .editorconfig
  2. 1 1
      README.md
  3. 6 1
      docker/deploy.sh
  4. 10 9
      docker/docker-compose.yml
  5. 1 0
      docker/nginx/nginx.conf
  6. 2 0
      docker/redis/redis.conf
  7. 12 12
      pom.xml
  8. 0 1
      ruoyi-admin/Dockerfile
  9. 1 1
      ruoyi-admin/pom.xml
  10. 16 57
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java
  11. 4 7
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java
  12. 1 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java
  13. 1 8
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
  14. 2 1
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssConfigController.java
  15. 2 1
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssController.java
  16. 8 9
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java
  17. 2 2
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java
  18. 2 8
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
  19. 1 1
      ruoyi-admin/src/main/resources/application-dev.yml
  20. 1 1
      ruoyi-admin/src/main/resources/application-prod.yml
  21. 11 12
      ruoyi-admin/src/main/resources/application.yml
  22. 13 13
      ruoyi-admin/src/main/resources/spy.properties
  23. 1 1
      ruoyi-common/pom.xml
  24. 1 1
      ruoyi-common/src/main/java/com/ruoyi/common/captcha/UnsignedMathGenerator.java
  25. 4 0
      ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java
  26. 51 0
      ruoyi-common/src/main/java/com/ruoyi/common/convert/ExcelBigNumberConvert.java
  27. 22 22
      ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java
  28. 5 0
      ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
  29. 6 21
      ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/cache/MybatisPlusRedisCache.java
  30. 1 2
      ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/core/BaseMapperPlus.java
  31. 37 34
      ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/core/IServicePlus.java
  32. 64 26
      ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/core/ServicePlusImpl.java
  33. 31 4
      ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/methods/InsertAll.java
  34. 38 1
      ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java
  35. 9 0
      ruoyi-common/src/main/java/com/ruoyi/common/core/validate/QueryGroup.java
  36. 35 0
      ruoyi-common/src/main/java/com/ruoyi/common/enums/CaptchaCategory.java
  37. 29 0
      ruoyi-common/src/main/java/com/ruoyi/common/enums/CaptchaType.java
  38. 26 0
      ruoyi-common/src/main/java/com/ruoyi/common/enums/ThreadPoolRejectedPolicy.java
  39. 9 3
      ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java
  40. 11 0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/BeanCopyUtils.java
  41. 5 7
      ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java
  42. 5 12
      ruoyi-common/src/main/java/com/ruoyi/common/utils/JsonUtils.java
  43. 30 17
      ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java
  44. 258 0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/RedisUtils.java
  45. 20 6
      ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java
  46. 3 0
      ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
  47. 1 1
      ruoyi-demo/pom.xml
  48. 7 0
      ruoyi-demo/src/main/java/com/ruoyi/demo/controller/FeignTestController.java
  49. 6 0
      ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisCacheController.java
  50. 6 0
      ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisLockController.java
  51. 42 0
      ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisPubSubController.java
  52. 24 2
      ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestBatchController.java
  53. 6 1
      ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestDemoController.java
  54. 4 0
      ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestI18nController.java
  55. 2 1
      ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestTreeController.java
  56. 0 3
      ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestDemo.java
  57. 1 0
      ruoyi-demo/src/main/java/com/ruoyi/demo/domain/vo/TestDemoVo.java
  58. 3 1
      ruoyi-demo/src/main/java/com/ruoyi/demo/feign/FeignTestService.java
  59. 2 0
      ruoyi-demo/src/main/java/com/ruoyi/demo/feign/fallback/FeignTestFallback.java
  60. 1 1
      ruoyi-extend/pom.xml
  61. 1 1
      ruoyi-extend/ruoyi-monitor-admin/pom.xml
  62. 1 1
      ruoyi-framework/pom.xml
  63. 2 4
      ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java
  64. 2 2
      ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java
  65. 16 9
      ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java
  66. 20 26
      ruoyi-framework/src/main/java/com/ruoyi/framework/config/JacksonConfig.java
  67. 5 5
      ruoyi-framework/src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java
  68. 5 1
      ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java
  69. 2 16
      ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java
  70. 4 2
      ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/CaptchaProperties.java
  71. 2 1
      ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/ThreadPoolProperties.java
  72. 3 4
      ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java
  73. 6 10
      ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java
  74. 3 6
      ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java
  75. 3 10
      ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java
  76. 4 7
      ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java
  77. 1 1
      ruoyi-generator/pom.xml
  78. 8 0
      ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java
  79. 22 29
      ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java
  80. 3 2
      ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java
  81. 3 1
      ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml
  82. 3 2
      ruoyi-generator/src/main/resources/vm/java/controller.java.vm
  83. 5 15
      ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm
  84. 6 17
      ruoyi-generator/src/main/resources/vm/vue/index.vue.vm
  85. 1 1
      ruoyi-oss/pom.xml
  86. 18 22
      ruoyi-oss/src/main/java/com/ruoyi/oss/factory/OssFactory.java
  87. 2 3
      ruoyi-oss/src/main/java/com/ruoyi/oss/service/abstractd/AbstractCloudStorageStrategy.java
  88. 4 4
      ruoyi-oss/src/main/java/com/ruoyi/oss/service/impl/AliyunCloudStorageStrategy.java
  89. 4 4
      ruoyi-oss/src/main/java/com/ruoyi/oss/service/impl/MinioCloudStorageStrategy.java
  90. 4 4
      ruoyi-oss/src/main/java/com/ruoyi/oss/service/impl/QcloudCloudStorageStrategy.java
  91. 3 3
      ruoyi-oss/src/main/java/com/ruoyi/oss/service/impl/QiniuCloudStorageStrategy.java
  92. 1 1
      ruoyi-quartz/pom.xml
  93. 8 0
      ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java
  94. 8 8
      ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobServiceImpl.java
  95. 1 1
      ruoyi-system/pom.xml
  96. 8 1
      ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java
  97. 1 1
      ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java
  98. 8 1
      ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java
  99. 7 0
      ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
  100. 10 14
      ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java

+ 0 - 3
.editorconfig

@@ -10,9 +10,6 @@ end_of_line = lf
 trim_trailing_whitespace = true
 insert_final_newline = true
 
-[*.java]
-indent_style = tab
-
 [*.{json,yml}]
 indent_size = 2
 

+ 1 - 1
README.md

@@ -4,7 +4,7 @@
 [![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)
 <br>
-[![RuoYi-Vue-Plus](https://img.shields.io/badge/RuoYi_Vue_Plus-3.0.0-success.svg)](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus)
+[![RuoYi-Vue-Plus](https://img.shields.io/badge/RuoYi_Vue_Plus-3.1.0-success.svg)](https://gitee.com/JavaLionLi/RuoYi-Vue-Plus)
 [![Spring Boot](https://img.shields.io/badge/Spring%20Boot-2.5-blue.svg)]()
 [![JDK-8+](https://img.shields.io/badge/JDK-8+-green.svg)]()
 [![JDK-11](https://img.shields.io/badge/JDK-11-green.svg)]()

+ 6 - 1
docker/deploy.sh

@@ -22,11 +22,16 @@ port(){
 
 ##放置挂载文件
 mount(){
-	#挂载配置文件
+	#挂载 nginx 配置文件
 	if test ! -f "/docker/nginx/conf/nginx.conf" ;then
 		mkdir -p /docker/nginx/conf
 		cp nginx/nginx.conf /docker/nginx/conf/nginx.conf
 	fi
+	#挂载 redis 配置文件
+	if test ! -f "/docker/redis/conf/redis.conf" ;then
+		mkdir -p /docker/redis/conf
+		cp redis/redis.conf /docker/redis/conf/redis.conf
+	fi
 }
 
 #启动基础模块

+ 10 - 9
docker/docker-compose.yml

@@ -65,10 +65,10 @@ services:
       TZ: Asia/Shanghai
     volumes:
       # 配置文件
-      - /docker/redis/conf/redis.conf:/redis.conf:rw
+      - /docker/redis/conf:/redis/config:rw
       # 数据文件
-      - /docker/redis/data:/data:rw
-    command: "redis-server --appendonly yes"
+      - /docker/redis/data:/redis/data:rw
+    command: "redis-server /redis/config/redis.conf --appendonly yes"
     privileged: true
     restart: always
     networks:
@@ -77,7 +77,7 @@ services:
 
   minio:
     image: minio/minio:RELEASE.2021-07-08T01-15-01Z
-    hostname: "minio"
+    container_name: minio
     ports:
       # api 端口
       - 9000:9000
@@ -103,14 +103,14 @@ services:
         ipv4_address: 172.30.0.54
 
   ruoyi-server1:
-    image: "ruoyi/ruoyi-server:3.0.0"
+    image: "ruoyi/ruoyi-server:3.1.0"
+    container_name: ruoyi-server1
     environment:
       # 时区上海
       TZ: Asia/Shanghai
     volumes:
       # 配置文件
       - /docker/server1/logs/:/ruoyi/server/logs/
-      - /docker/ruoyi/uploadPath/:/ruoyi/server/ruoyi/uploadPath/
     privileged: true
     restart: always
     networks:
@@ -118,14 +118,14 @@ services:
         ipv4_address: 172.30.0.60
 
   ruoyi-server2:
-    image: "ruoyi/ruoyi-server:3.0.0"
+    image: "ruoyi/ruoyi-server:3.1.0"
+    container_name: ruoyi-server2
     environment:
       # 时区上海
       TZ: Asia/Shanghai
     volumes:
       # 配置文件
       - /docker/server2/logs/:/ruoyi/server/logs/
-      - /docker/ruoyi/uploadPath/:/ruoyi/server/ruoyi/uploadPath/
     privileged: true
     restart: always
     networks:
@@ -133,7 +133,8 @@ services:
         ipv4_address: 172.30.0.61
 
   ruoyi-monitor-admin:
-    image: "ruoyi/ruoyi-monitor-admin:3.0.0"
+    image: "ruoyi/ruoyi-monitor-admin:3.1.0"
+    container_name: ruoyi-monitor-admin
     environment:
       # 时区上海
       TZ: Asia/Shanghai

+ 1 - 0
docker/nginx/nginx.conf

@@ -22,6 +22,7 @@ http {
     access_log  /var/log/nginx/access.log  main;
 
 	upstream server {
+	    ip_hash;
 		server 172.30.0.60:8080;
 		server 172.30.0.61:8080;
 	}

+ 2 - 0
docker/redis/redis.conf

@@ -0,0 +1,2 @@
+# redis 密码
+# requirepass 123456

+ 12 - 12
pom.xml

@@ -6,41 +6,41 @@
 
     <groupId>com.ruoyi</groupId>
     <artifactId>ruoyi-vue-plus</artifactId>
-    <version>3.0.0</version>
+    <version>3.1.0</version>
 
     <name>RuoYi-Vue-Plus</name>
     <url>https://gitee.com/JavaLionLi/RuoYi-Vue-Plus</url>
     <description>RuoYi-Vue-Plus后台管理系统</description>
 
     <properties>
-        <ruoyi-vue-plus.version>3.0.0</ruoyi-vue-plus.version>
-        <spring-boot.version>2.5.3</spring-boot.version>
+        <ruoyi-vue-plus.version>3.1.0</ruoyi-vue-plus.version>
+        <spring-boot.version>2.5.4</spring-boot.version>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
         <java.version>1.8</java.version>
-        <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
+        <maven-jar-plugin.version>3.2.0</maven-jar-plugin.version>
         <druid.version>1.2.6</druid.version>
         <knife4j.version>3.0.3</knife4j.version>
         <poi.version>4.1.2</poi.version>
         <easyexcel.version>2.2.10</easyexcel.version>
         <velocity.version>1.7</velocity.version>
         <jwt.version>0.9.1</jwt.version>
-        <mybatis-plus.version>3.4.3</mybatis-plus.version>
+        <mybatis-plus.version>3.4.3.3</mybatis-plus.version>
         <p6spy.version>3.9.1</p6spy.version>
-        <hutool.version>5.7.7</hutool.version>
+        <hutool.version>5.7.11</hutool.version>
         <feign.version>3.0.3</feign.version>
-        <feign-okhttp.version>11.2</feign-okhttp.version>
+        <feign-okhttp.version>11.6</feign-okhttp.version>
         <okhttp.version>4.9.1</okhttp.version>
-        <spring-boot-admin.version>2.5.0</spring-boot-admin.version>
-        <redisson.version>3.16.1</redisson.version>
+        <spring-boot-admin.version>2.5.1</spring-boot-admin.version>
+        <redisson.version>3.16.2</redisson.version>
         <lock4j.version>2.2.1</lock4j.version>
         <dynamic-ds.version>3.4.1</dynamic-ds.version>
 
         <!-- OSS 配置 -->
         <qiniu.version>7.8.0</qiniu.version>
-        <aliyun.oss.version>3.13.0</aliyun.oss.version>
-        <qcloud.cos.version>5.6.47</qcloud.cos.version>
-        <minio.version>8.2.0</minio.version>
+        <aliyun.oss.version>3.13.1</aliyun.oss.version>
+        <qcloud.cos.version>5.6.51</qcloud.cos.version>
+        <minio.version>8.3.0</minio.version>
 
         <!-- docker 配置 -->
         <docker.registry.url>localhost</docker.registry.url>

+ 0 - 1
ruoyi-admin/Dockerfile

@@ -4,7 +4,6 @@ MAINTAINER Lion Li
 
 RUN mkdir -p /ruoyi/server
 RUN mkdir -p /ruoyi/server/logs
-RUN mkdir -p /ruoyi/server/ruoyi/uploadPath
 
 WORKDIR /ruoyi/server
 

+ 1 - 1
ruoyi-admin/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi-vue-plus</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>3.0.0</version>
+        <version>3.1.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <packaging>jar</packaging>

+ 16 - 57
ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java

@@ -1,25 +1,22 @@
 package com.ruoyi.web.controller.common;
 
 import cn.hutool.captcha.AbstractCaptcha;
-import cn.hutool.captcha.CircleCaptcha;
-import cn.hutool.captcha.LineCaptcha;
-import cn.hutool.captcha.ShearCaptcha;
 import cn.hutool.captcha.generator.CodeGenerator;
-import cn.hutool.captcha.generator.RandomGenerator;
 import cn.hutool.core.convert.Convert;
 import cn.hutool.core.util.IdUtil;
-import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.core.domain.AjaxResult;
-import com.ruoyi.common.core.redis.RedisCache;
-import com.ruoyi.framework.captcha.UnsignedMathGenerator;
+import com.ruoyi.common.enums.CaptchaType;
+import com.ruoyi.common.utils.RedisUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.reflect.ReflectUtils;
+import com.ruoyi.common.utils.spring.SpringUtils;
 import com.ruoyi.framework.config.properties.CaptchaProperties;
 import com.ruoyi.system.service.ISysConfigService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RestController;
 
-import javax.annotation.Resource;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
@@ -32,19 +29,6 @@ import java.util.concurrent.TimeUnit;
 @RestController
 public class CaptchaController {
 
-	// 圆圈干扰验证码
-	@Resource(name = "CircleCaptcha")
-	private CircleCaptcha circleCaptcha;
-	// 线段干扰的验证码
-	@Resource(name = "LineCaptcha")
-	private LineCaptcha lineCaptcha;
-	// 扭曲干扰验证码
-	@Resource(name = "ShearCaptcha")
-	private ShearCaptcha shearCaptcha;
-
-	@Autowired
-	private RedisCache redisCache;
-
 	@Autowired
 	private CaptchaProperties captchaProperties;
 
@@ -65,41 +49,16 @@ public class CaptchaController {
 		// 保存验证码信息
 		String uuid = IdUtil.simpleUUID();
 		String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
-		String code = null;
 		// 生成验证码
-		CodeGenerator codeGenerator;
-		AbstractCaptcha captcha;
-		switch (captchaProperties.getType()) {
-			case "math":
-				codeGenerator = new UnsignedMathGenerator(captchaProperties.getNumberLength());
-				break;
-			case "char":
-				codeGenerator = new RandomGenerator(captchaProperties.getCharLength());
-				break;
-			default:
-				throw new IllegalArgumentException("验证码类型异常");
-		}
-		switch (captchaProperties.getCategory()) {
-			case "line":
-				captcha = lineCaptcha;
-				break;
-			case "circle":
-				captcha = circleCaptcha;
-				break;
-			case "shear":
-				captcha = shearCaptcha;
-				break;
-			default:
-				throw new IllegalArgumentException("验证码类别异常");
-		}
+		CaptchaType captchaType = captchaProperties.getType();
+		boolean isMath = CaptchaType.MATH == captchaType;
+		Integer length = isMath ? captchaProperties.getNumberLength() : captchaProperties.getCharLength();
+		CodeGenerator codeGenerator = ReflectUtils.newInstance(captchaType.getClazz(), length);
+		AbstractCaptcha captcha = SpringUtils.getBean(captchaProperties.getCategory().getClazz());
 		captcha.setGenerator(codeGenerator);
 		captcha.createCode();
-		if ("math".equals(captchaProperties.getType())) {
-			code = getCodeResult(captcha.getCode());
-		} else if ("char".equals(captchaProperties.getType())) {
-			code = captcha.getCode();
-		}
-		redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
+		String code = isMath ? getCodeResult(captcha.getCode()) : captcha.getCode();
+		RedisUtils.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
 		ajax.put("uuid", uuid);
 		ajax.put("img", captcha.getImageBase64());
 		return AjaxResult.success(ajax);
@@ -112,13 +71,13 @@ public class CaptchaController {
 		int b = Convert.toInt(StringUtils.substring(capStr, numberLength + 1, numberLength + 1 + numberLength).trim());
 		switch (operator) {
 			case '*':
-				return a * b + "";
+				return Convert.toStr(a * b);
 			case '+':
-				return a + b + "";
+				return Convert.toStr(a + b);
 			case '-':
-				return a - b + "";
+				return Convert.toStr(a - b);
 			default:
-				return "";
+				return StringUtils.EMPTY;
 		}
 	}
 

+ 4 - 7
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java

@@ -6,9 +6,9 @@ import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.core.domain.model.LoginUser;
 import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.core.redis.RedisCache;
 import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.common.utils.PageUtils;
+import com.ruoyi.common.utils.RedisUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.system.domain.SysUserOnline;
 import com.ruoyi.system.service.ISysUserOnlineService;
@@ -33,18 +33,15 @@ public class SysUserOnlineController extends BaseController
     @Autowired
     private ISysUserOnlineService userOnlineService;
 
-    @Autowired
-    private RedisCache redisCache;
-
     @PreAuthorize("@ss.hasPermi('monitor:online:list')")
     @GetMapping("/list")
     public TableDataInfo list(String ipaddr, String userName)
     {
-        Collection<String> keys = redisCache.keys(Constants.LOGIN_TOKEN_KEY + "*");
+        Collection<String> keys = RedisUtils.keys(Constants.LOGIN_TOKEN_KEY + "*");
         List<SysUserOnline> userOnlineList = new ArrayList<SysUserOnline>();
         for (String key : keys)
         {
-            LoginUser user = redisCache.getCacheObject(key);
+            LoginUser user = RedisUtils.getCacheObject(key);
             if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName))
             {
                 if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername()))
@@ -84,7 +81,7 @@ public class SysUserOnlineController extends BaseController
     @DeleteMapping("/{tokenId}")
     public AjaxResult forceLogout(@PathVariable String tokenId)
     {
-        redisCache.deleteObject(Constants.LOGIN_TOKEN_KEY + tokenId);
+        RedisUtils.deleteObject(Constants.LOGIN_TOKEN_KEY + tokenId);
         return AjaxResult.success();
     }
 }

+ 1 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java

@@ -70,6 +70,7 @@ public class SysDeptController extends BaseController
     @GetMapping(value = "/{deptId}")
     public AjaxResult getInfo(@PathVariable Long deptId)
     {
+        deptService.checkDeptDataScope(deptId);
         return AjaxResult.success(deptService.selectDeptById(deptId));
     }
 

+ 1 - 8
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java

@@ -5,12 +5,9 @@ import com.ruoyi.common.core.domain.AjaxResult;
 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.utils.SecurityUtils;
-import com.ruoyi.common.utils.ServletUtils;
 import com.ruoyi.framework.web.service.SysLoginService;
 import com.ruoyi.framework.web.service.SysPermissionService;
-import com.ruoyi.framework.web.service.TokenService;
 import com.ruoyi.system.service.ISysMenuService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -40,9 +37,6 @@ public class SysLoginController
     @Autowired
     private SysPermissionService permissionService;
 
-    @Autowired
-    private TokenService tokenService;
-
     /**
      * 登录方法
      *
@@ -68,8 +62,7 @@ public class SysLoginController
     @GetMapping("getInfo")
     public AjaxResult getInfo()
     {
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        SysUser user = loginUser.getUser();
+        SysUser user = SecurityUtils.getLoginUser().getUser();
         // 角色集合
         Set<String> roles = permissionService.getRolePermission(user);
         // 权限集合

+ 2 - 1
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssConfigController.java

@@ -7,6 +7,7 @@ import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.core.validate.AddGroup;
 import com.ruoyi.common.core.validate.EditGroup;
+import com.ruoyi.common.core.validate.QueryGroup;
 import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.system.domain.bo.SysOssConfigBo;
 import com.ruoyi.system.domain.vo.SysOssConfigVo;
@@ -45,7 +46,7 @@ public class SysOssConfigController extends BaseController {
 	@ApiOperation("查询云存储配置列表")
 	@PreAuthorize("@ss.hasPermi('system:oss:list')")
 	@GetMapping("/list")
-	public TableDataInfo<SysOssConfigVo> list(@Validated SysOssConfigBo bo) {
+	public TableDataInfo<SysOssConfigVo> list(@Validated(QueryGroup.class) SysOssConfigBo bo) {
 		return iSysOssConfigService.queryPageList(bo);
 	}
 

+ 2 - 1
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysOssController.java

@@ -10,6 +10,7 @@ import com.ruoyi.common.annotation.RepeatSubmit;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.core.validate.QueryGroup;
 import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.JsonUtils;
@@ -63,7 +64,7 @@ public class SysOssController extends BaseController {
 	@ApiOperation("查询OSS云存储列表")
 	@PreAuthorize("@ss.hasPermi('system:oss:list')")
 	@GetMapping("/list")
-	public TableDataInfo<SysOssVo> list(@Validated SysOssBo bo) {
+	public TableDataInfo<SysOssVo> list(@Validated(QueryGroup.class) SysOssBo bo) {
 		return iSysOssService.queryPageList(bo);
 	}
 

+ 8 - 9
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java

@@ -8,7 +8,6 @@ import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.core.domain.model.LoginUser;
 import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.common.utils.SecurityUtils;
-import com.ruoyi.common.utils.ServletUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.framework.web.service.TokenService;
 import com.ruoyi.system.domain.SysOss;
@@ -46,7 +45,7 @@ public class SysProfileController extends BaseController
     @GetMapping
     public AjaxResult profile()
     {
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        LoginUser loginUser = getLoginUser();
         SysUser user = loginUser.getUser();
 		Map<String,Object> ajax = new HashMap<>();
 		ajax.put("user", user);
@@ -72,17 +71,17 @@ public class SysProfileController extends BaseController
         {
             return AjaxResult.error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
         }
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        LoginUser loginUser = getLoginUser();
         SysUser sysUser = loginUser.getUser();
         user.setUserId(sysUser.getUserId());
         user.setPassword(null);
         if (userService.updateUserProfile(user) > 0)
         {
             // 更新缓存用户信息
-            loginUser.getUser().setNickName(user.getNickName());
-            loginUser.getUser().setPhonenumber(user.getPhonenumber());
-            loginUser.getUser().setEmail(user.getEmail());
-            loginUser.getUser().setSex(user.getSex());
+            sysUser.setNickName(user.getNickName());
+            sysUser.setPhonenumber(user.getPhonenumber());
+            sysUser.setEmail(user.getEmail());
+            sysUser.setSex(user.getSex());
             tokenService.setLoginUser(loginUser);
             return AjaxResult.success();
         }
@@ -96,7 +95,7 @@ public class SysProfileController extends BaseController
     @PutMapping("/updatePwd")
     public AjaxResult updatePwd(String oldPassword, String newPassword)
     {
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        LoginUser loginUser = getLoginUser();
         String userName = loginUser.getUsername();
         String password = loginUser.getPassword();
         if (!SecurityUtils.matchesPassword(oldPassword, password))
@@ -126,7 +125,7 @@ public class SysProfileController extends BaseController
     {
         if (!file.isEmpty())
         {
-            LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+            LoginUser loginUser = getLoginUser();
 			SysOss oss = iSysOssService.upload(file);
 			String avatar = oss.getUrl();
             if (userService.updateUserAvatar(loginUser.getUsername(), avatar))

+ 2 - 2
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java

@@ -9,7 +9,6 @@ import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.core.domain.model.LoginUser;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.enums.BusinessType;
-import com.ruoyi.common.utils.ServletUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.framework.web.service.SysPermissionService;
@@ -69,6 +68,7 @@ public class SysRoleController extends BaseController
     @GetMapping(value = "/{roleId}")
     public AjaxResult getInfo(@PathVariable Long roleId)
     {
+        roleService.checkRoleDataScope(roleId);
         return AjaxResult.success(roleService.selectRoleById(roleId));
     }
 
@@ -115,7 +115,7 @@ public class SysRoleController extends BaseController
         if (roleService.updateRole(role) > 0)
         {
             // 更新缓存用户权限
-            LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+            LoginUser loginUser = getLoginUser();
             if (StringUtils.isNotNull(loginUser.getUser()) && !loginUser.getUser().isAdmin())
             {
                 loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser()));

+ 2 - 8
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java

@@ -10,14 +10,11 @@ import com.ruoyi.common.core.domain.AjaxResult;
 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;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.common.utils.SecurityUtils;
-import com.ruoyi.common.utils.ServletUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
-import com.ruoyi.framework.web.service.TokenService;
 import com.ruoyi.system.domain.vo.SysUserExportVo;
 import com.ruoyi.system.domain.vo.SysUserImportVo;
 import com.ruoyi.system.service.ISysPostService;
@@ -54,9 +51,6 @@ public class SysUserController extends BaseController
     @Autowired
     private ISysPostService postService;
 
-    @Autowired
-    private TokenService tokenService;
-
     /**
      * 获取用户列表
      */
@@ -92,8 +86,7 @@ public class SysUserController extends BaseController
     {
 		List<SysUserImportVo> userListVo = ExcelUtil.importExcel(file.getInputStream(), SysUserImportVo.class);
 		List<SysUser> userList = BeanUtil.copyToList(userListVo, SysUser.class);
-		LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
-        String operName = loginUser.getUsername();
+        String operName = getUsername();
         String message = userService.importUser(userList, updateSupport, operName);
         return AjaxResult.success(message);
     }
@@ -111,6 +104,7 @@ public class SysUserController extends BaseController
     @GetMapping(value = { "/", "/{userId}" })
     public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId)
     {
+		userService.checkUserDataScope(userId);
         Map<String, Object> ajax = new HashMap<>();
         List<SysRole> roles = roleService.selectRoleAll();
         ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));

+ 1 - 1
ruoyi-admin/src/main/resources/application-dev.yml

@@ -38,7 +38,7 @@ spring:
         # 配置一个连接在池中最大生存的时间,单位是毫秒
         maxEvictableIdleTimeMillis: 900000
         # 配置检测连接是否有效
-        validationQuery: SELECT 1 FROM DUAL
+        validationQuery: SELECT 1
         testWhileIdle: true
         testOnBorrow: false
         testOnReturn: false

+ 1 - 1
ruoyi-admin/src/main/resources/application-prod.yml

@@ -38,7 +38,7 @@ spring:
         # 配置一个连接在池中最大生存的时间,单位是毫秒
         maxEvictableIdleTimeMillis: 900000
         # 配置检测连接是否有效
-        validationQuery: SELECT 1 FROM DUAL
+        validationQuery: SELECT 1
         testWhileIdle: true
         testOnBorrow: false
         testOnReturn: false

+ 11 - 12
ruoyi-admin/src/main/resources/application.yml

@@ -12,10 +12,11 @@ ruoyi:
   addressEnabled: true
 
 captcha:
+  # 页面 <参数设置> 可开启关闭 验证码校验
   # 验证码类型 math 数组计算 char 字符验证
-  type: math
+  type: MATH
   # line 线段干扰 circle 圆圈干扰 shear 扭曲干扰
-  category: circle
+  category: CIRCLE
   # 数字验证码位数
   numberLength: 1
   # 字符验证码长度
@@ -133,8 +134,6 @@ mybatis-plus:
   # REUSE:该执行器类型会复用预处理语句(PreparedStatement)
   # BATCH:该执行器类型会批量执行所有的更新语句
   executorType: SIMPLE
-  # 指定外部化 MyBatis Properties 配置,通过该配置可以抽离配置,实现不同环境的配置部署
-  configurationProperties: null
   configuration:
     # 自动驼峰命名规则(camel case)映射
     # 如果您的数据库命名符合规则无需使用 @TableField 注解指定数据库字段名
@@ -199,11 +198,11 @@ mybatis-plus:
       # NOT_EMPTY 非空判断(只对字符串类型字段,其他类型字段依然为非NULL判断)
       # DEFAULT 默认的,一般只用于注解里
       # NEVER 不加入 SQL
-      insertStrategy: NOT_EMPTY
+      insertStrategy: NOT_NULL
       # 字段验证策略之 update,在 update 的时候的字段验证策略
-      updateStrategy: NOT_EMPTY
+      updateStrategy: NOT_NULL
       # 字段验证策略之 select,在 select 的时候的字段验证策略既 wrapper 根据内部 entity 生成的 where 条件
-      selectStrategy: NOT_EMPTY
+      where-strategy: NOT_NULL
 
 # Swagger配置
 swagger:
@@ -245,11 +244,11 @@ thread-pool:
   # 线程池维护线程所允许的空闲时间
   keepAliveSeconds: 300
   # 线程池对拒绝任务(无线程可用)的处理策略
-  # CallerRunsPolicy 等待
-  # DiscardOldestPolicy 放弃最旧的
-  # DiscardPolicy 丢弃
-  # AbortPolicy 中止
-  rejectedExecutionHandler: CallerRunsPolicy
+  # CALLER_RUNS_POLICY 等待
+  # DISCARD_OLDEST_POLICY 放弃最旧的
+  # DISCARD_POLICY 丢弃
+  # ABORT_POLICY 中止
+  rejectedExecutionHandler: CALLER_RUNS_POLICY
 
 # feign 相关配置
 feign:

+ 13 - 13
ruoyi-admin/src/main/resources/spy.properties

@@ -1,26 +1,26 @@
-# p6spy 性能分析插件配置文件
+# p6spy 鎬ц兘鍒嗘瀽鎻掍欢閰嶇疆鏂囦欢
 modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
-# 自定义日志打印
+# 鑷�畾涔夋棩蹇楁墦鍗�
 logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
-#日志输出到控制台
+#鏃ュ織杈撳嚭鍒版帶鍒跺彴
 appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
-# 使用日志系统记录 sql
+# 浣跨敤鏃ュ織绯荤粺璁板綍 sql
 #appender=com.p6spy.engine.spy.appender.Slf4JLogger
-# 设置 p6spy driver 代理
+# 璁剧疆 p6spy driver 浠g悊
 #deregisterdrivers=true
-# 取消JDBC URL前缀
+# 鍙栨秷JDBC URL鍓嶇紑
 useprefix=true
-# 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
+# 閰嶇疆璁板綍 Log 渚嬪�,鍙�幓鎺夌殑缁撴灉闆嗘湁error,info,batch,debug,statement,commit,rollback,result,resultset.
 excludecategories=info,debug,result,commit,resultset
-# 日期格式
+# 鏃ユ湡鏍煎紡
 dateformat=yyyy-MM-dd HH:mm:ss
-# 实际驱动可多个
+# 瀹為檯椹卞姩鍙��涓�
 #driverlist=org.h2.Driver
-# 是否开启慢SQL记录
+# 鏄�惁寮€鍚�參SQL璁板綍
 outagedetection=true
-# 慢SQL记录标准 2 秒
+# 鎱�QL璁板綍鏍囧噯 2 绉�
 outagedetectioninterval=2
-# 是否过滤 Log
+# 鏄�惁杩囨护 Log
 filter=true
-# 过滤 Log 时所排除的表名列表,以逗号分隔
+# 杩囨护 Log 鏃舵墍鎺掗櫎鐨勮〃鍚嶅垪琛�紝浠ラ€楀彿鍒嗛殧
 exclude=QRTZ_

+ 1 - 1
ruoyi-common/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi-vue-plus</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>3.0.0</version>
+        <version>3.1.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 1 - 1
ruoyi-framework/src/main/java/com/ruoyi/framework/captcha/UnsignedMathGenerator.java → ruoyi-common/src/main/java/com/ruoyi/common/captcha/UnsignedMathGenerator.java

@@ -1,4 +1,4 @@
-package com.ruoyi.framework.captcha;
+package com.ruoyi.common.captcha;
 
 import cn.hutool.captcha.generator.CodeGenerator;
 import cn.hutool.core.math.Calculator;

+ 4 - 0
ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java

@@ -139,4 +139,8 @@ public class Constants
 	 */
 	public static final String LOOKUP_RMI = "rmi://";
 
+	/**
+	 * LDAP 远程方法调用
+	 */
+	public static final String LOOKUP_LDAP = "ldap://";
 }

+ 51 - 0
ruoyi-common/src/main/java/com/ruoyi/common/convert/ExcelBigNumberConvert.java

@@ -0,0 +1,51 @@
+package com.ruoyi.common.convert;
+
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.excel.converters.Converter;
+import com.alibaba.excel.enums.CellDataTypeEnum;
+import com.alibaba.excel.metadata.CellData;
+import com.alibaba.excel.metadata.GlobalConfiguration;
+import com.alibaba.excel.metadata.property.ExcelContentProperty;
+import lombok.extern.slf4j.Slf4j;
+
+import java.math.BigDecimal;
+
+/**
+ * 大数值转换
+ * Excel 数值长度位15位 大于15位的数值转换位字符串
+ *
+ * @author Lion Li
+ */
+@Slf4j
+public class ExcelBigNumberConvert implements Converter<Long> {
+
+	@Override
+	public Class<Long> supportJavaTypeKey() {
+		return Long.class;
+	}
+
+	@Override
+	public CellDataTypeEnum supportExcelTypeKey() {
+		return CellDataTypeEnum.STRING;
+	}
+
+	@Override
+	public Long convertToJavaData(CellData cellData, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
+		return Convert.toLong(cellData.getData());
+	}
+
+	@Override
+	public CellData<Object> convertToExcelData(Long object, ExcelContentProperty contentProperty, GlobalConfiguration globalConfiguration) {
+		if (ObjectUtil.isNotNull(object)) {
+			String str = Convert.toStr(object);
+			if (str.length() > 15) {
+				return new CellData<>(str);
+			}
+		}
+		CellData<Object> cellData = new CellData<>(new BigDecimal(object));
+		cellData.setType(CellDataTypeEnum.NUMBER);
+		return cellData;
+	}
+
+}

+ 22 - 22
ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java

@@ -17,28 +17,6 @@ public class BaseController
     protected final Logger logger = LoggerFactory.getLogger(this.getClass());
 
     /**
-     * 响应返回结果
-     *
-     * @param rows 影响行数
-     * @return 操作结果
-     */
-    protected AjaxResult<Void> toAjax(int rows)
-    {
-        return rows > 0 ? AjaxResult.success() : AjaxResult.error();
-    }
-
-    /**
-     * 响应返回结果
-     *
-     * @param result 结果
-     * @return 操作结果
-     */
-    protected AjaxResult<Void> toAjax(boolean result)
-    {
-        return result ? success() : error();
-    }
-
-    /**
      * 返回成功
      */
     public AjaxResult<Void> success()
@@ -71,6 +49,28 @@ public class BaseController
     }
 
     /**
+     * 响应返回结果
+     * 
+     * @param rows 影响行数
+     * @return 操作结果
+     */
+    protected AjaxResult<Void> toAjax(int rows)
+    {
+        return rows > 0 ? AjaxResult.success() : AjaxResult.error();
+    }
+
+    /**
+     * 响应返回结果
+     *
+     * @param result 结果
+     * @return 操作结果
+     */
+    protected AjaxResult<Void> toAjax(boolean result)
+    {
+        return result ? success() : error();
+    }
+
+    /**
      * 页面跳转
      */
     public String redirect(String url)

+ 5 - 0
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java

@@ -78,6 +78,11 @@ public class SysUser implements Serializable {
 	/**
 	 * 密码
 	 */
+	@TableField(
+			insertStrategy = FieldStrategy.NOT_EMPTY,
+			updateStrategy = FieldStrategy.NOT_EMPTY,
+			whereStrategy = FieldStrategy.NOT_EMPTY
+	)
 	private String password;
 
 	@JsonIgnore

+ 6 - 21
ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/cache/MybatisPlusRedisCache.java

@@ -1,7 +1,7 @@
 package com.ruoyi.common.core.mybatisplus.cache;
 
 import cn.hutool.extra.spring.SpringUtil;
-import com.ruoyi.common.core.redis.RedisCache;
+import com.ruoyi.common.utils.RedisUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.ibatis.cache.Cache;
 import org.springframework.data.redis.connection.RedisServerCommands;
@@ -25,8 +25,6 @@ public class MybatisPlusRedisCache implements Cache {
 
 	private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true);
 
-	private RedisCache redisCache;
-
 	private String id;
 
 	public MybatisPlusRedisCache(final String id) {
@@ -43,23 +41,16 @@ public class MybatisPlusRedisCache implements Cache {
 
 	@Override
 	public void putObject(Object key, Object value) {
-		if (redisCache == null) {
-			redisCache = SpringUtil.getBean(RedisCache.class);
-		}
 		if (value != null) {
-			redisCache.setCacheObject(key.toString(), value);
+			RedisUtils.setCacheObject(key.toString(), value);
 		}
 	}
 
 	@Override
 	public Object getObject(Object key) {
-		if (redisCache == null) {
-			//由于启动期间注入失败,只能运行期间注入,这段代码可以删除
-			redisCache = SpringUtil.getBean(RedisCache.class);
-		}
 		try {
 			if (key != null) {
-				return redisCache.getCacheObject(key.toString());
+				return RedisUtils.getCacheObject(key.toString());
 			}
 		} catch (Exception e) {
 			e.printStackTrace();
@@ -70,11 +61,8 @@ public class MybatisPlusRedisCache implements Cache {
 
 	@Override
 	public Object removeObject(Object key) {
-		if (redisCache == null) {
-			redisCache = SpringUtil.getBean(RedisCache.class);
-		}
 		if (key != null) {
-			redisCache.deleteObject(key.toString());
+			RedisUtils.deleteObject(key.toString());
 		}
 		return null;
 	}
@@ -82,12 +70,9 @@ public class MybatisPlusRedisCache implements Cache {
 	@Override
 	public void clear() {
 		log.debug("清空缓存");
-		if (redisCache == null) {
-			redisCache = SpringUtil.getBean(RedisCache.class);
-		}
-		Collection<String> keys = redisCache.keys("*:" + this.id + "*");
+		Collection<String> keys = RedisUtils.keys("*:" + this.id + "*");
 		if (!CollectionUtils.isEmpty(keys)) {
-			redisCache.deleteObject(keys);
+			RedisUtils.deleteObject(keys);
 		}
 	}
 

+ 1 - 2
ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/core/BaseMapperPlus.java

@@ -14,8 +14,7 @@ import java.util.Collection;
 public interface BaseMapperPlus<T> extends BaseMapper<T> {
 
 	/**
-	 * 单sql批量插入( 全量填充 无视数据库默认值 )
-	 * 适用于无脑插入
+	 * 单sql批量插入( 全量填充 )
 	 */
 	int insertAll(@Param("list") Collection<T> batchList);
 

+ 37 - 34
ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/core/IServicePlus.java

@@ -15,45 +15,46 @@ import java.util.function.Function;
 /**
  * 自定义 Service 接口, 实现 数据库实体与 vo 对象转换返回
  *
+ * @param <T> 数据实体类
+ * @param <V> vo类
  * @author Lion Li
- * @since 2021-05-13
  */
-public interface IServicePlus<T, K> extends IService<T> {
+public interface IServicePlus<T, V> extends IService<T> {
 
 	/**
 	 * @param id          主键id
 	 * @param copyOptions copy条件
-	 * @return K对象
+	 * @return V对象
 	 */
-	K getVoById(Serializable id, CopyOptions copyOptions);
+	V getVoById(Serializable id, CopyOptions copyOptions);
 
-	default K getVoById(Serializable id) {
+	default V getVoById(Serializable id) {
 		return getVoById(id, new CopyOptions());
 	}
 
 	/**
 	 * @param convertor 自定义转换器
 	 */
-	default K getVoById(Serializable id, Function<T, K> convertor) {
+	default V getVoById(Serializable id, Function<T, V> convertor) {
 		return convertor.apply(getById(id));
 	}
 
 	/**
 	 * @param idList      id列表
 	 * @param copyOptions copy条件
-	 * @return K对象
+	 * @return V对象
 	 */
-	List<K> listVoByIds(Collection<? extends Serializable> idList, CopyOptions copyOptions);
+	List<V> listVoByIds(Collection<? extends Serializable> idList, CopyOptions copyOptions);
 
-	default List<K> listVoByIds(Collection<? extends Serializable> idList) {
+	default List<V> listVoByIds(Collection<? extends Serializable> idList) {
 		return listVoByIds(idList, new CopyOptions());
 	}
 
 	/**
 	 * @param convertor 自定义转换器
 	 */
-	default List<K> listVoByIds(Collection<? extends Serializable> idList,
-								Function<Collection<T>, List<K>> convertor) {
+	default List<V> listVoByIds(Collection<? extends Serializable> idList,
+								Function<Collection<T>, List<V>> convertor) {
 		List<T> list = getBaseMapper().selectBatchIds(idList);
 		if (list == null) {
 			return null;
@@ -64,19 +65,19 @@ public interface IServicePlus<T, K> extends IService<T> {
 	/**
 	 * @param columnMap   表字段 map 对象
 	 * @param copyOptions copy条件
-	 * @return K对象
+	 * @return V对象
 	 */
-	List<K> listVoByMap(Map<String, Object> columnMap, CopyOptions copyOptions);
+	List<V> listVoByMap(Map<String, Object> columnMap, CopyOptions copyOptions);
 
-	default List<K> listVoByMap(Map<String, Object> columnMap) {
+	default List<V> listVoByMap(Map<String, Object> columnMap) {
 		return listVoByMap(columnMap, new CopyOptions());
 	}
 
 	/**
 	 * @param convertor 自定义转换器
 	 */
-	default List<K> listVoByMap(Map<String, Object> columnMap,
-								Function<Collection<T>, List<K>> convertor) {
+	default List<V> listVoByMap(Map<String, Object> columnMap,
+								Function<Collection<T>, List<V>> convertor) {
 		List<T> list = getBaseMapper().selectByMap(columnMap);
 		if (list == null) {
 			return null;
@@ -87,36 +88,36 @@ public interface IServicePlus<T, K> extends IService<T> {
 	/**
 	 * @param queryWrapper 查询条件
 	 * @param copyOptions  copy条件
-	 * @return K对象
+	 * @return V对象
 	 */
-	K getVoOne(Wrapper<T> queryWrapper, CopyOptions copyOptions);
+	V getVoOne(Wrapper<T> queryWrapper, CopyOptions copyOptions);
 
-	default K getVoOne(Wrapper<T> queryWrapper) {
+	default V getVoOne(Wrapper<T> queryWrapper) {
 		return getVoOne(queryWrapper, new CopyOptions());
 	}
 
 	/**
 	 * @param convertor 自定义转换器
 	 */
-	default K getVoOne(Wrapper<T> queryWrapper, Function<T, K> convertor) {
+	default V getVoOne(Wrapper<T> queryWrapper, Function<T, V> convertor) {
 		return convertor.apply(getOne(queryWrapper, true));
 	}
 
 	/**
 	 * @param queryWrapper 查询条件
 	 * @param copyOptions  copy条件
-	 * @return K对象
+	 * @return V对象
 	 */
-	List<K> listVo(Wrapper<T> queryWrapper, CopyOptions copyOptions);
+	List<V> listVo(Wrapper<T> queryWrapper, CopyOptions copyOptions);
 
-	default List<K> listVo(Wrapper<T> queryWrapper) {
+	default List<V> listVo(Wrapper<T> queryWrapper) {
 		return listVo(queryWrapper, new CopyOptions());
 	}
 
 	/**
 	 * @param convertor 自定义转换器
 	 */
-	default List<K> listVo(Wrapper<T> queryWrapper, Function<Collection<T>, List<K>> convertor) {
+	default List<V> listVo(Wrapper<T> queryWrapper, Function<Collection<T>, List<V>> convertor) {
 		List<T> list = getBaseMapper().selectList(queryWrapper);
 		if (list == null) {
 			return null;
@@ -124,14 +125,14 @@ public interface IServicePlus<T, K> extends IService<T> {
 		return convertor.apply(list);
 	}
 
-	default List<K> listVo() {
+	default List<V> listVo() {
 		return listVo(Wrappers.emptyWrapper());
 	}
 
 	/**
 	 * @param convertor 自定义转换器
 	 */
-	default List<K> listVo(Function<Collection<T>, List<K>> convertor) {
+	default List<V> listVo(Function<Collection<T>, List<V>> convertor) {
 		return listVo(Wrappers.emptyWrapper(), convertor);
 	}
 
@@ -139,34 +140,36 @@ public interface IServicePlus<T, K> extends IService<T> {
 	 * @param page         分页对象
 	 * @param queryWrapper 查询条件
 	 * @param copyOptions  copy条件
-	 * @return K对象
+	 * @return V对象
 	 */
-	PagePlus<T, K> pageVo(PagePlus<T, K> page, Wrapper<T> queryWrapper, CopyOptions copyOptions);
+	PagePlus<T, V> pageVo(PagePlus<T, V> page, Wrapper<T> queryWrapper, CopyOptions copyOptions);
 
-	default PagePlus<T, K> pageVo(PagePlus<T, K> page, Wrapper<T> queryWrapper) {
+	default PagePlus<T, V> pageVo(PagePlus<T, V> page, Wrapper<T> queryWrapper) {
 		return pageVo(page, queryWrapper, new CopyOptions());
 	}
 
 	/**
 	 * @param convertor 自定义转换器
 	 */
-	default PagePlus<T, K> pageVo(PagePlus<T, K> page, Wrapper<T> queryWrapper,
-								  Function<Collection<T>, List<K>> convertor) {
-		PagePlus<T, K> result = getBaseMapper().selectPage(page, queryWrapper);
+	default PagePlus<T, V> pageVo(PagePlus<T, V> page, Wrapper<T> queryWrapper,
+								  Function<Collection<T>, List<V>> convertor) {
+		PagePlus<T, V> result = getBaseMapper().selectPage(page, queryWrapper);
 		return result.setRecordsVo(convertor.apply(result.getRecords()));
 	}
 
-	default PagePlus<T, K> pageVo(PagePlus<T, K> page) {
+	default PagePlus<T, V> pageVo(PagePlus<T, V> page) {
 		return pageVo(page, Wrappers.emptyWrapper());
 	}
 
 	/**
 	 * @param convertor 自定义转换器
 	 */
-	default PagePlus<T, K> pageVo(PagePlus<T, K> page, Function<Collection<T>, List<K>> convertor) {
+	default PagePlus<T, V> pageVo(PagePlus<T, V> page, Function<Collection<T>, List<V>> convertor) {
 		return pageVo(page, Wrappers.emptyWrapper(), convertor);
 	}
 
 	boolean saveAll(Collection<T> entityList);
+
+	boolean saveOrUpdateAll(Collection<T> entityList);
 }
 

+ 64 - 26
ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/core/ServicePlusImpl.java

@@ -1,16 +1,22 @@
 package com.ruoyi.common.core.mybatisplus.core;
 
 import cn.hutool.core.bean.copier.CopyOptions;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.core.conditions.Wrapper;
-import com.baomidou.mybatisplus.core.toolkit.ClassUtils;
+import com.baomidou.mybatisplus.core.metadata.TableInfo;
+import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
+import com.baomidou.mybatisplus.core.toolkit.Assert;
+import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ruoyi.common.core.page.PagePlus;
 import com.ruoyi.common.utils.BeanCopyUtils;
+import com.ruoyi.common.utils.reflect.ReflectUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.core.ResolvableType;
 
 import java.io.Serializable;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
@@ -18,11 +24,14 @@ import java.util.Map;
 /**
  * IServicePlus 实现类
  *
+ * @param <M> Mapper类
+ * @param <T> 数据实体类
+ * @param <V> vo类
  * @author Lion Li
  */
 @Slf4j
 @SuppressWarnings("unchecked")
-public class ServicePlusImpl<M extends BaseMapperPlus<T>, T, K> extends ServiceImpl<M, T> implements IServicePlus<T, K> {
+public class ServicePlusImpl<M extends BaseMapperPlus<T>, T, V> extends ServiceImpl<M, T> implements IServicePlus<T, V> {
 
 	@Autowired
 	protected M baseMapper;
@@ -40,31 +49,26 @@ public class ServicePlusImpl<M extends BaseMapperPlus<T>, T, K> extends ServiceI
 		return entityClass;
 	}
 
-	protected Class<T> mapperClass = currentMapperClass();
+	protected Class<M> mapperClass = currentMapperClass();
 
-	protected Class<K> voClass = currentVoClass();
+	protected Class<V> voClass = currentVoClass();
 
-	public Class<K> getVoClass() {
+	public Class<V> getVoClass() {
 		return voClass;
 	}
 
 	@Override
-	protected Class<T> currentMapperClass() {
-		return (Class<T>) this.getResolvableType().as(ServicePlusImpl.class).getGeneric(0).getType();
+	protected Class<M> currentMapperClass() {
+		return (Class<M>) ReflectionKit.getSuperClassGenericType(this.getClass(), ServicePlusImpl.class, 0);
 	}
 
 	@Override
 	protected Class<T> currentModelClass() {
-		return (Class<T>) this.getResolvableType().as(ServicePlusImpl.class).getGeneric(1).getType();
+		return (Class<T>) ReflectionKit.getSuperClassGenericType(this.getClass(), ServicePlusImpl.class, 1);
 	}
 
-	protected Class<K> currentVoClass() {
-		return (Class<K>) this.getResolvableType().as(ServicePlusImpl.class).getGeneric(2).getType();
-	}
-
-	@Override
-	protected ResolvableType getResolvableType() {
-		return ResolvableType.forClass(ClassUtils.getUserClass(getClass()));
+	protected Class<V> currentVoClass() {
+		return (Class<V>) ReflectionKit.getSuperClassGenericType(this.getClass(), ServicePlusImpl.class, 2);
 	}
 
 	/**
@@ -113,21 +117,55 @@ public class ServicePlusImpl<M extends BaseMapperPlus<T>, T, K> extends ServiceI
 	}
 
 	/**
-	 * 单sql批量插入( 全量填充 无视数据库默认值 )
-	 * 适用于无脑插入
+	 * 单sql批量插入( 全量填充 )
 	 */
 	@Override
 	public boolean saveAll(Collection<T> entityList) {
+		if (CollUtil.isEmpty(entityList)) {
+			return false;
+		}
 		return baseMapper.insertAll(entityList) == entityList.size();
 	}
 
 	/**
+	 * 全量保存或更新 ( 按主键区分 )
+	 */
+	@Override
+	public boolean saveOrUpdateAll(Collection<T> entityList) {
+		if (CollUtil.isEmpty(entityList)) {
+			return false;
+		}
+		TableInfo tableInfo = TableInfoHelper.getTableInfo(entityClass);
+		Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!");
+		String keyProperty = tableInfo.getKeyProperty();
+		Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!");
+		List<T> addList = new ArrayList<>();
+		List<T> updateList = new ArrayList<>();
+		int row = 0;
+		for (T entity : entityList) {
+			Object id = ReflectUtils.invokeGetter(entity, keyProperty);
+			if (ObjectUtil.isNull(id)) {
+				addList.add(entity);
+			} else {
+				updateList.add(entity);
+			}
+		}
+		if (CollUtil.isNotEmpty(updateList) && updateBatchById(updateList)) {
+			row += updateList.size();
+		}
+        if (CollUtil.isNotEmpty(addList)) {
+            row += baseMapper.insertAll(addList);
+        }
+		return row == entityList.size();
+	}
+
+	/**
 	 * 根据 ID 查询
 	 *
 	 * @param id 主键ID
 	 */
 	@Override
-	public K getVoById(Serializable id, CopyOptions copyOptions) {
+	public V getVoById(Serializable id, CopyOptions copyOptions) {
 		T t = getBaseMapper().selectById(id);
 		return BeanCopyUtils.oneCopy(t, copyOptions, voClass);
 	}
@@ -138,7 +176,7 @@ public class ServicePlusImpl<M extends BaseMapperPlus<T>, T, K> extends ServiceI
 	 * @param idList 主键ID列表
 	 */
 	@Override
-	public List<K> listVoByIds(Collection<? extends Serializable> idList, CopyOptions copyOptions) {
+	public List<V> listVoByIds(Collection<? extends Serializable> idList, CopyOptions copyOptions) {
 		List<T> list = getBaseMapper().selectBatchIds(idList);
 		if (list == null) {
 			return null;
@@ -152,7 +190,7 @@ public class ServicePlusImpl<M extends BaseMapperPlus<T>, T, K> extends ServiceI
 	 * @param columnMap 表字段 map 对象
 	 */
 	@Override
-	public List<K> listVoByMap(Map<String, Object> columnMap, CopyOptions copyOptions) {
+	public List<V> listVoByMap(Map<String, Object> columnMap, CopyOptions copyOptions) {
 		List<T> list = getBaseMapper().selectByMap(columnMap);
 		if (list == null) {
 			return null;
@@ -167,7 +205,7 @@ public class ServicePlusImpl<M extends BaseMapperPlus<T>, T, K> extends ServiceI
 	 * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
 	 */
 	@Override
-	public K getVoOne(Wrapper<T> queryWrapper, CopyOptions copyOptions) {
+	public V getVoOne(Wrapper<T> queryWrapper, CopyOptions copyOptions) {
 		T t = getOne(queryWrapper, true);
 		return BeanCopyUtils.oneCopy(t, copyOptions, voClass);
 	}
@@ -178,7 +216,7 @@ public class ServicePlusImpl<M extends BaseMapperPlus<T>, T, K> extends ServiceI
 	 * @param queryWrapper 实体对象封装操作类 {@link com.baomidou.mybatisplus.core.conditions.query.QueryWrapper}
 	 */
 	@Override
-	public List<K> listVo(Wrapper<T> queryWrapper, CopyOptions copyOptions) {
+	public List<V> listVo(Wrapper<T> queryWrapper, CopyOptions copyOptions) {
 		List<T> list = getBaseMapper().selectList(queryWrapper);
 		if (list == null) {
 			return null;
@@ -193,9 +231,9 @@ public class ServicePlusImpl<M extends BaseMapperPlus<T>, T, K> extends ServiceI
 	 * @param queryWrapper 实体对象封装操作类
 	 */
 	@Override
-	public PagePlus<T, K> pageVo(PagePlus<T, K> page, Wrapper<T> queryWrapper, CopyOptions copyOptions) {
-		PagePlus<T, K> result = getBaseMapper().selectPage(page, queryWrapper);
-		List<K> volist = BeanCopyUtils.listCopy(result.getRecords(), copyOptions, voClass);
+	public PagePlus<T, V> pageVo(PagePlus<T, V> page, Wrapper<T> queryWrapper, CopyOptions copyOptions) {
+		PagePlus<T, V> result = getBaseMapper().selectPage(page, queryWrapper);
+		List<V> volist = BeanCopyUtils.listCopy(result.getRecords(), copyOptions, voClass);
 		result.setRecordsVo(volist);
 		return result;
 	}

+ 31 - 4
ruoyi-common/src/main/java/com/ruoyi/common/core/mybatisplus/methods/InsertAll.java

@@ -2,6 +2,7 @@ package com.ruoyi.common.core.mybatisplus.methods;
 
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.core.injector.AbstractMethod;
+import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
 import com.baomidou.mybatisplus.core.metadata.TableInfo;
 import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
 import com.ruoyi.common.utils.StringUtils;
@@ -11,13 +12,17 @@ import org.apache.ibatis.executor.keygen.NoKeyGenerator;
 import org.apache.ibatis.mapping.MappedStatement;
 import org.apache.ibatis.mapping.SqlSource;
 
+import java.util.List;
+
 /**
- * 单sql批量插入( 全量填充 无视数据库默认值 )
+ * 单sql批量插入( 全量填充 )
  *
  * @author Lion Li
  */
 public class InsertAll extends AbstractMethod {
 
+	private final static String[] FILL_PROPERTY = {"createTime", "createBy", "updateTime", "updateBy"};
+
 	@Override
 	public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
 		final String sql = "<script>insert into %s %s values %s</script>";
@@ -63,10 +68,32 @@ public class InsertAll extends AbstractMethod {
 		final StringBuilder valueSql = new StringBuilder();
 		valueSql.append("<foreach collection=\"list\" item=\"item\" index=\"index\" open=\"(\" separator=\"),(\" close=\")\">");
 		if (StringUtils.isNotBlank(tableInfo.getKeyColumn())) {
-			valueSql.append("#{item.").append(tableInfo.getKeyProperty()).append("},");
+			valueSql.append("\n#{item.").append(tableInfo.getKeyProperty()).append("},\n");
+		}
+		List<TableFieldInfo> fieldList = tableInfo.getFieldList();
+		int last = fieldList.size() - 1;
+		for (int i = 0; i < fieldList.size(); i++) {
+			String property = fieldList.get(i).getProperty();
+			if (!StringUtils.equalsAny(property, FILL_PROPERTY)) {
+				valueSql.append("<if test=\"item.").append(property).append(" != null\">");
+				valueSql.append("#{item.").append(property).append("}");
+				if (i != last) {
+					valueSql.append(",");
+				}
+				valueSql.append("</if>");
+				valueSql.append("<if test=\"item.").append(property).append(" == null\">");
+				valueSql.append("DEFAULT");
+				if (i != last) {
+					valueSql.append(",");
+				}
+				valueSql.append("</if>");
+			} else {
+				valueSql.append("#{item.").append(property).append("}");
+				if (i != last) {
+					valueSql.append(",");
+				}
+			}
 		}
-		tableInfo.getFieldList().forEach(x -> valueSql.append("#{item.").append(x.getProperty()).append("},"));
-		valueSql.delete(valueSql.length() - 1, valueSql.length());
 		valueSql.append("</foreach>");
 		return valueSql.toString();
 	}

+ 38 - 1
ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java

@@ -5,22 +5,59 @@ import org.redisson.api.*;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
-import java.util.*;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
 
 /**
  * spring redis 工具类
  *
  * @author shenxinquan
+ * @see com.ruoyi.common.utils.RedisUtils
+ * @deprecated 3.2.0 删除此类
  **/
 @SuppressWarnings(value = {"unchecked", "rawtypes"})
 @Component
+@Deprecated
 public class RedisCache {
 
 	@Autowired
 	private RedissonClient redissonClient;
 
 	/**
+	 * 发布通道消息
+	 *
+	 * @param channelKey 通道key
+	 * @param msg 发送数据
+	 * @param consumer 自定义处理
+	 */
+	public <T> void publish(String channelKey, T msg, Consumer<T> consumer) {
+		RTopic topic = redissonClient.getTopic(channelKey);
+		topic.publish(msg);
+		consumer.accept(msg);
+	}
+
+	public <T> void publish(String channelKey, T msg) {
+		RTopic topic = redissonClient.getTopic(channelKey);
+		topic.publish(msg);
+	}
+
+	/**
+	 * 订阅通道接收消息
+	 *
+	 * @param channelKey 通道key
+	 * @param clazz 消息类型
+	 * @param consumer 自定义处理
+	 */
+	public <T> void subscribe(String channelKey, Class<T> clazz, Consumer<T> consumer) {
+		RTopic topic = redissonClient.getTopic(channelKey);
+		topic.addListener(clazz, (channel, msg) -> consumer.accept(msg));
+	}
+
+	/**
 	 * 缓存基本的对象,Integer、String、实体类等
 	 *
 	 * @param key   缓存的键值

+ 9 - 0
ruoyi-common/src/main/java/com/ruoyi/common/core/validate/QueryGroup.java

@@ -0,0 +1,9 @@
+package com.ruoyi.common.core.validate;
+
+/**
+ * 校验分组 query
+ *
+ * @author Lion Li
+ */
+public interface QueryGroup {
+}

+ 35 - 0
ruoyi-common/src/main/java/com/ruoyi/common/enums/CaptchaCategory.java

@@ -0,0 +1,35 @@
+package com.ruoyi.common.enums;
+
+import cn.hutool.captcha.AbstractCaptcha;
+import cn.hutool.captcha.CircleCaptcha;
+import cn.hutool.captcha.LineCaptcha;
+import cn.hutool.captcha.ShearCaptcha;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 验证码类别
+ *
+ * @author Lion Li
+ */
+@Getter
+@AllArgsConstructor
+public enum CaptchaCategory {
+
+    /**
+     * 线段干扰
+     */
+    LINE(LineCaptcha.class),
+
+    /**
+     * 圆圈干扰
+     */
+    CIRCLE(CircleCaptcha.class),
+
+    /**
+     * 扭曲干扰
+     */
+    SHEAR(ShearCaptcha.class);
+
+    private final Class<? extends AbstractCaptcha> clazz;
+}

+ 29 - 0
ruoyi-common/src/main/java/com/ruoyi/common/enums/CaptchaType.java

@@ -0,0 +1,29 @@
+package com.ruoyi.common.enums;
+
+import cn.hutool.captcha.generator.CodeGenerator;
+import cn.hutool.captcha.generator.RandomGenerator;
+import com.ruoyi.common.captcha.UnsignedMathGenerator;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * 验证码类型
+ *
+ * @author Lion Li
+ */
+@Getter
+@AllArgsConstructor
+public enum CaptchaType {
+
+    /**
+     * 数字
+     */
+    MATH(UnsignedMathGenerator.class),
+
+    /**
+     * 字符
+     */
+    CHAR(RandomGenerator.class);
+
+    private final Class<? extends CodeGenerator> clazz;
+}

+ 26 - 0
ruoyi-common/src/main/java/com/ruoyi/common/enums/ThreadPoolRejectedPolicy.java

@@ -0,0 +1,26 @@
+package com.ruoyi.common.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.concurrent.RejectedExecutionHandler;
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * 线程池 拒绝策略 泛型
+ *
+ * @author Lion Li
+ */
+@Getter
+@AllArgsConstructor
+public enum ThreadPoolRejectedPolicy {
+
+    CALLER_RUNS_POLICY("等待", ThreadPoolExecutor.CallerRunsPolicy.class),
+    DISCARD_OLDEST_POLICY("放弃最旧的", ThreadPoolExecutor.DiscardOldestPolicy.class),
+    DISCARD_POLICY("丢弃", ThreadPoolExecutor.DiscardPolicy.class),
+    ABORT_POLICY("中止", ThreadPoolExecutor.AbortPolicy.class);
+
+    private final String name;
+    private final Class<? extends RejectedExecutionHandler> clazz;
+
+}

+ 9 - 3
ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java

@@ -65,8 +65,8 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper
 
         // xss过滤
         json = HtmlUtil.cleanHtmlTag(json).trim();
-
-        final ByteArrayInputStream bis = IoUtil.toStream(json, StandardCharsets.UTF_8);
+        byte[] jsonBytes = json.getBytes(StandardCharsets.UTF_8);
+        final ByteArrayInputStream bis = IoUtil.toStream(jsonBytes);
         return new ServletInputStream()
         {
             @Override
@@ -82,6 +82,12 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper
             }
 
             @Override
+            public int available() throws IOException
+            {
+                return jsonBytes.length;
+            }
+
+            @Override
             public void setReadListener(ReadListener readListener)
             {
             }
@@ -104,4 +110,4 @@ public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper
         String header = super.getHeader(HttpHeaders.CONTENT_TYPE);
         return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE);
     }
-}
+}

+ 11 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/BeanCopyUtils.java

@@ -2,6 +2,8 @@ package com.ruoyi.common.utils;
 
 import cn.hutool.core.bean.copier.BeanCopier;
 import cn.hutool.core.bean.copier.CopyOptions;
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.ReflectUtil;
 
 import java.util.List;
@@ -36,6 +38,9 @@ public class BeanCopyUtils {
 	 * @return desc
 	 */
 	public static <T, V> V oneCopy(T source, CopyOptions copyOptions, V desc) {
+		if (ObjectUtil.isNull(source)) {
+			return null;
+		}
 		return BeanCopier.create(source, desc, copyOptions).copy();
 	}
 
@@ -48,6 +53,12 @@ public class BeanCopyUtils {
 	 * @return desc
 	 */
 	public static <T, V> List<V> listCopy(List<T> sourceList, CopyOptions copyOptions, Class<V> desc) {
+		if (ObjectUtil.isNull(sourceList)) {
+			return null;
+		}
+		if (CollUtil.isEmpty(sourceList)) {
+			return CollUtil.newArrayList();
+		}
 		return sourceList.stream()
 			.map(source -> oneCopy(source, copyOptions, desc))
 			.collect(Collectors.toList());

+ 5 - 7
ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java

@@ -3,8 +3,6 @@ package com.ruoyi.common.utils;
 import cn.hutool.core.collection.CollUtil;
 import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.core.domain.entity.SysDictData;
-import com.ruoyi.common.core.redis.RedisCache;
-import com.ruoyi.common.utils.spring.SpringUtils;
 
 import java.util.Collection;
 import java.util.List;
@@ -29,7 +27,7 @@ public class DictUtils
      */
     public static void setDictCache(String key, List<SysDictData> dictDatas)
     {
-        SpringUtils.getBean(RedisCache.class).setCacheObject(getCacheKey(key), dictDatas);
+        RedisUtils.setCacheObject(getCacheKey(key), dictDatas);
     }
 
     /**
@@ -40,7 +38,7 @@ public class DictUtils
      */
     public static List<SysDictData> getDictCache(String key)
     {
-        Object cacheObj = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key));
+        Object cacheObj = RedisUtils.getCacheObject(getCacheKey(key));
         if (StringUtils.isNotNull(cacheObj))
         {
             List<SysDictData> dictDatas = (List<SysDictData>)cacheObj;
@@ -160,7 +158,7 @@ public class DictUtils
      */
     public static void removeDictCache(String key)
     {
-        SpringUtils.getBean(RedisCache.class).deleteObject(getCacheKey(key));
+        RedisUtils.deleteObject(getCacheKey(key));
     }
 
     /**
@@ -168,8 +166,8 @@ public class DictUtils
      */
     public static void clearDictCache()
     {
-        Collection<String> keys = SpringUtils.getBean(RedisCache.class).keys(Constants.SYS_DICT_KEY + "*");
-        SpringUtils.getBean(RedisCache.class).deleteObject(keys);
+        Collection<String> keys = RedisUtils.keys(Constants.SYS_DICT_KEY + "*");
+        RedisUtils.deleteObject(keys);
     }
 
     /**

+ 5 - 12
ruoyi-common/src/main/java/com/ruoyi/common/utils/JsonUtils.java

@@ -4,6 +4,9 @@ import cn.hutool.core.util.ArrayUtil;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -15,20 +18,10 @@ import java.util.Map;
  *
  * @author 芋道源码
  */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
 public class JsonUtils {
 
-    private static ObjectMapper objectMapper = new ObjectMapper();
-
-    /**
-     * 初始化 objectMapper 属性
-     * <p>
-     * 通过这样的方式,使用 Spring 创建的 ObjectMapper Bean
-     *
-     * @param objectMapper ObjectMapper 对象
-     */
-    public static void init(ObjectMapper objectMapper) {
-        JsonUtils.objectMapper = objectMapper;
-    }
+    private static ObjectMapper objectMapper = SpringUtils.getBean(ObjectMapper.class);
 
     public static String toJsonString(Object object) {
 		if (StringUtils.isNull(object)) {

+ 30 - 17
ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java

@@ -57,15 +57,12 @@ public class PageUtils {
         Integer pageSize = ServletUtils.getParameterToInt(PAGE_SIZE, DEFAULT_PAGE_SIZE);
         String orderByColumn = ServletUtils.getParameter(ORDER_BY_COLUMN);
         String isAsc = ServletUtils.getParameter(IS_ASC);
-        PagePlus<T, K> page = new PagePlus<>(pageNum, pageSize);
-        if (StringUtils.isNotBlank(orderByColumn)) {
-            String orderBy = SqlUtil.escapeOrderBySql(orderByColumn);
-            if ("asc".equals(isAsc)) {
-                page.addOrder(OrderItem.asc(orderBy));
-            } else if ("desc".equals(isAsc)) {
-                page.addOrder(OrderItem.desc(orderBy));
-            }
+        if (pageNum <= 0) {
+            pageNum = DEFAULT_PAGE_NUM;
         }
+        PagePlus<T, K> page = new PagePlus<>(pageNum, pageSize);
+        OrderItem orderItem = buildOrderItem(orderByColumn, isAsc);
+        page.addOrder(orderItem);
         return page;
     }
 
@@ -83,23 +80,32 @@ public class PageUtils {
         Integer pageSize = ServletUtils.getParameterToInt(PAGE_SIZE, DEFAULT_PAGE_SIZE);
         String orderByColumn = ServletUtils.getParameter(ORDER_BY_COLUMN, defaultOrderByColumn);
         String isAsc = ServletUtils.getParameter(IS_ASC, defaultIsAsc);
-		// 兼容前端排序类型
-		if ("ascending".equals(isAsc)) {
-			isAsc = "asc";
-		} else if ("descending".equals(isAsc)) {
-			isAsc = "desc";
-		}
+        if (pageNum <= 0) {
+            pageNum = DEFAULT_PAGE_NUM;
+        }
         Page<T> page = new Page<>(pageNum, pageSize);
+        OrderItem orderItem = buildOrderItem(orderByColumn, isAsc);
+        page.addOrder(orderItem);
+        return page;
+    }
+
+    private static OrderItem buildOrderItem(String orderByColumn, String isAsc) {
+        // 兼容前端排序类型
+        if ("ascending".equals(isAsc)) {
+            isAsc = "asc";
+        } else if ("descending".equals(isAsc)) {
+            isAsc = "desc";
+        }
         if (StringUtils.isNotBlank(orderByColumn)) {
             String orderBy = SqlUtil.escapeOrderBySql(orderByColumn);
 			orderBy = StringUtils.toUnderScoreCase(orderBy);
 			if ("asc".equals(isAsc)) {
-                page.addOrder(OrderItem.asc(orderBy));
+                return OrderItem.asc(orderBy);
             } else if ("desc".equals(isAsc)) {
-                page.addOrder(OrderItem.desc(orderBy));
+                return OrderItem.desc(orderBy);
             }
         }
-        return page;
+        return null;
     }
 
     public static <T, K> TableDataInfo<K> buildDataInfo(PagePlus<T, K> page) {
@@ -129,4 +135,11 @@ public class PageUtils {
         return rspData;
     }
 
+    public static <T> TableDataInfo<T> buildDataInfo() {
+        TableDataInfo<T> rspData = new TableDataInfo<>();
+        rspData.setCode(HttpStatus.HTTP_OK);
+        rspData.setMsg("查询成功");
+        return rspData;
+    }
+
 }

+ 258 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/RedisUtils.java

@@ -0,0 +1,258 @@
+package com.ruoyi.common.utils;
+
+import com.google.common.collect.Lists;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.redisson.api.*;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+
+/**
+ * redis 工具类
+ *
+ * @author Lion Li
+ * @version 3.1.0 新增
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+@SuppressWarnings(value = {"unchecked", "rawtypes"})
+public class RedisUtils {
+
+    private static RedissonClient client = SpringUtils.getBean(RedissonClient.class);
+
+    /**
+     * 发布通道消息
+     *
+     * @param channelKey 通道key
+     * @param msg        发送数据
+     * @param consumer   自定义处理
+     */
+    public static <T> void publish(String channelKey, T msg, Consumer<T> consumer) {
+        RTopic topic = client.getTopic(channelKey);
+        topic.publish(msg);
+        consumer.accept(msg);
+    }
+
+    public static <T> void publish(String channelKey, T msg) {
+        RTopic topic = client.getTopic(channelKey);
+        topic.publish(msg);
+    }
+
+    /**
+     * 订阅通道接收消息
+     *
+     * @param channelKey 通道key
+     * @param clazz      消息类型
+     * @param consumer   自定义处理
+     */
+    public static <T> void subscribe(String channelKey, Class<T> clazz, Consumer<T> consumer) {
+        RTopic topic = client.getTopic(channelKey);
+        topic.addListener(clazz, (channel, msg) -> consumer.accept(msg));
+    }
+
+    /**
+     * 缓存基本的对象,Integer、String、实体类等
+     *
+     * @param key   缓存的键值
+     * @param value 缓存的值
+     */
+    public static <T> void setCacheObject(final String key, final T value) {
+        client.getBucket(key).set(value);
+    }
+
+    /**
+     * 缓存基本的对象,Integer、String、实体类等
+     *
+     * @param key      缓存的键值
+     * @param value    缓存的值
+     * @param timeout  时间
+     * @param timeUnit 时间颗粒度
+     */
+    public static <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit) {
+        RBucket<T> result = client.getBucket(key);
+        result.set(value);
+        result.expire(timeout, timeUnit);
+    }
+
+    /**
+     * 设置有效时间
+     *
+     * @param key     Redis键
+     * @param timeout 超时时间
+     * @return true=设置成功;false=设置失败
+     */
+    public static boolean expire(final String key, final long timeout) {
+        return expire(key, timeout, TimeUnit.SECONDS);
+    }
+
+    /**
+     * 设置有效时间
+     *
+     * @param key     Redis键
+     * @param timeout 超时时间
+     * @param unit    时间单位
+     * @return true=设置成功;false=设置失败
+     */
+    public static boolean expire(final String key, final long timeout, final TimeUnit unit) {
+        RBucket rBucket = client.getBucket(key);
+        return rBucket.expire(timeout, unit);
+    }
+
+    /**
+     * 获得缓存的基本对象。
+     *
+     * @param key 缓存键值
+     * @return 缓存键值对应的数据
+     */
+    public static <T> T getCacheObject(final String key) {
+        RBucket<T> rBucket = client.getBucket(key);
+        return rBucket.get();
+    }
+
+    /**
+     * 删除单个对象
+     *
+     * @param key
+     */
+    public static boolean deleteObject(final String key) {
+        return client.getBucket(key).delete();
+    }
+
+    /* */
+
+    /**
+     * 删除集合对象
+     *
+     * @param collection 多个对象
+     * @return
+     */
+    public static void deleteObject(final Collection collection) {
+        RBatch batch = client.createBatch();
+        collection.forEach(t -> {
+            batch.getBucket(t.toString()).deleteAsync();
+        });
+        batch.execute();
+    }
+
+    /**
+     * 缓存List数据
+     *
+     * @param key      缓存的键值
+     * @param dataList 待缓存的List数据
+     * @return 缓存的对象
+     */
+    public static <T> boolean setCacheList(final String key, final List<T> dataList) {
+        RList<T> rList = client.getList(key);
+        return rList.addAll(dataList);
+    }
+
+    /**
+     * 获得缓存的list对象
+     *
+     * @param key 缓存的键值
+     * @return 缓存键值对应的数据
+     */
+    public static <T> List<T> getCacheList(final String key) {
+        RList<T> rList = client.getList(key);
+        return rList.readAll();
+    }
+
+    /**
+     * 缓存Set
+     *
+     * @param key     缓存键值
+     * @param dataSet 缓存的数据
+     * @return 缓存数据的对象
+     */
+    public static <T> boolean setCacheSet(final String key, final Set<T> dataSet) {
+        RSet<T> rSet = client.getSet(key);
+        return rSet.addAll(dataSet);
+    }
+
+    /**
+     * 获得缓存的set
+     *
+     * @param key
+     * @return
+     */
+    public static <T> Set<T> getCacheSet(final String key) {
+        RSet<T> rSet = client.getSet(key);
+        return rSet.readAll();
+    }
+
+    /**
+     * 缓存Map
+     *
+     * @param key
+     * @param dataMap
+     */
+    public static <T> void setCacheMap(final String key, final Map<String, T> dataMap) {
+        if (dataMap != null) {
+            RMap<String, T> rMap = client.getMap(key);
+            rMap.putAll(dataMap);
+        }
+    }
+
+    /**
+     * 获得缓存的Map
+     *
+     * @param key
+     * @return
+     */
+    public static <T> Map<String, T> getCacheMap(final String key) {
+        RMap<String, T> rMap = client.getMap(key);
+        return rMap.getAll(rMap.keySet());
+    }
+
+    /**
+     * 往Hash中存入数据
+     *
+     * @param key   Redis键
+     * @param hKey  Hash键
+     * @param value 值
+     */
+    public static <T> void setCacheMapValue(final String key, final String hKey, final T value) {
+        RMap<String, T> rMap = client.getMap(key);
+        rMap.put(hKey, value);
+    }
+
+    /**
+     * 获取Hash中的数据
+     *
+     * @param key  Redis键
+     * @param hKey Hash键
+     * @return Hash中的对象
+     */
+    public static <T> T getCacheMapValue(final String key, final String hKey) {
+        RMap<String, T> rMap = client.getMap(key);
+        return rMap.get(hKey);
+    }
+
+    /**
+     * 获取多个Hash中的数据
+     *
+     * @param key   Redis键
+     * @param hKeys Hash键集合
+     * @return Hash对象集合
+     */
+    public static <K, V> Map<K, V> getMultiCacheMapValue(final String key, final Set<K> hKeys) {
+        RMap<K, V> rMap = client.getMap(key);
+        return rMap.getAll(hKeys);
+    }
+
+    /**
+     * 获得缓存的基本对象列表
+     *
+     * @param pattern 字符串前缀
+     * @return 对象列表
+     */
+    public static Collection<String> keys(final String pattern) {
+        Iterable<String> iterable = client.getKeys().getKeysByPattern(pattern);
+        return Lists.newArrayList(iterable);
+    }
+}

+ 20 - 6
ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java

@@ -48,12 +48,26 @@ public class ServletUtils extends ServletUtil {
 		return Convert.toInt(getRequest().getParameter(name), defaultValue);
 	}
 
-	/**
-	 * 获取request
-	 */
-	public static HttpServletRequest getRequest() {
-		return getRequestAttributes().getRequest();
-	}
+    /**
+     * 获取Boolean参数
+     */
+    public static Boolean getParameterToBool(String name) {
+        return Convert.toBool(getRequest().getParameter(name));
+    }
+
+    /**
+     * 获取Boolean参数
+     */
+    public static Boolean getParameterToBool(String name, Boolean defaultValue) {
+        return Convert.toBool(getRequest().getParameter(name), defaultValue);
+    }
+
+    /**
+     * 获取request
+     */
+    public static HttpServletRequest getRequest() {
+        return getRequestAttributes().getRequest();
+    }
 
 	/**
 	 * 获取response

+ 3 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java

@@ -3,6 +3,7 @@ package com.ruoyi.common.utils.poi;
 import cn.hutool.core.util.IdUtil;
 import com.alibaba.excel.EasyExcel;
 import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
+import com.ruoyi.common.convert.ExcelBigNumberConvert;
 import com.ruoyi.common.utils.DictUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.file.FileUtils;
@@ -52,6 +53,8 @@ public class ExcelUtil {
 				.autoCloseStream(false)
 				// 自动适配
 				.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
+				// 大数值自动转换 防止失真
+				.registerConverter(new ExcelBigNumberConvert())
 				.sheet(sheetName).doWrite(list);
 		} catch (IOException e) {
 			throw new RuntimeException("导出Excel异常");

+ 1 - 1
ruoyi-demo/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi-vue-plus</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>3.0.0</version>
+        <version>3.1.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 7 - 0
ruoyi-demo/src/main/java/com/ruoyi/demo/controller/FeignTestController.java

@@ -2,6 +2,8 @@ package com.ruoyi.demo.controller;
 
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.demo.feign.FeignTestService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
 import lombok.RequiredArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -14,6 +16,7 @@ import org.springframework.web.bind.annotation.RestController;
  *
  * @author Lion Li
  */
+@Api(value = "feign测试", tags = {"feign测试"})
 @RequiredArgsConstructor(onConstructor_ = @Autowired)
 @RestController
 @RequestMapping("/feign/test")
@@ -21,6 +24,10 @@ public class FeignTestController {
 
     private final FeignTestService feignTestService;
 
+    /**
+     * 搜索数据
+     */
+    @ApiOperation("测试使用feign请求数据")
     @GetMapping("/search/{wd}")
     public AjaxResult search(@PathVariable String wd) {
         String search = feignTestService.search(wd);

+ 6 - 0
ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisCacheController.java

@@ -1,6 +1,8 @@
 package com.ruoyi.demo.controller;
 
 import com.ruoyi.common.core.domain.AjaxResult;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
 import lombok.RequiredArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.cache.annotation.CacheEvict;
@@ -17,6 +19,7 @@ import org.springframework.web.bind.annotation.RestController;
  */
 // 类级别 缓存统一配置
 //@CacheConfig(cacheNames = "redissonCacheMap")
+@Api(value = "spring-cache 演示案例", tags = {"spring-cache 演示案例"})
 @RequiredArgsConstructor(onConstructor_ = @Autowired)
 @RestController
 @RequestMapping("/demo/cache")
@@ -33,6 +36,7 @@ public class RedisCacheController {
 	 *
 	 * cacheNames 为配置文件内 groupId
 	 */
+	@ApiOperation("测试 @Cacheable")
 	@Cacheable(cacheNames = "redissonCacheMap", key = "#key", condition = "#key != null")
 	@GetMapping("/test1")
 	public AjaxResult<String> test1(String key, String value){
@@ -47,6 +51,7 @@ public class RedisCacheController {
 	 *
 	 * cacheNames 为 配置文件内 groupId
 	 */
+	@ApiOperation("测试 @CachePut")
 	@CachePut(cacheNames = "redissonCacheMap", key = "#key", condition = "#key != null")
 	@GetMapping("/test2")
 	public AjaxResult<String> test2(String key, String value){
@@ -61,6 +66,7 @@ public class RedisCacheController {
 	 *
 	 * cacheNames 为 配置文件内 groupId
 	 */
+	@ApiOperation("测试 @CacheEvict")
 	@CacheEvict(cacheNames = "redissonCacheMap", key = "#key", condition = "#key != null")
 	@GetMapping("/test3")
 	public AjaxResult<String> test3(String key, String value){

+ 6 - 0
ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisLockController.java

@@ -5,6 +5,8 @@ import com.baomidou.lock.LockTemplate;
 import com.baomidou.lock.annotation.Lock4j;
 import com.baomidou.lock.executor.RedissonLockExecutor;
 import com.ruoyi.common.core.domain.AjaxResult;
+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.cache.annotation.Cacheable;
@@ -20,6 +22,7 @@ import java.time.LocalTime;
  *
  * @author shenxinquan
  */
+@Api(value = "测试分布式锁的样例", tags = {"测试分布式锁的样例"})
 @Slf4j
 @RestController
 @RequestMapping("/demo/redisLock")
@@ -31,6 +34,7 @@ public class RedisLockController {
 	/**
 	 * 测试lock4j 注解
 	 */
+	@ApiOperation("测试lock4j 注解")
 	@Lock4j(keys = {"#key"})
 	@GetMapping("/testLock4j")
 	public  AjaxResult<String> testLock4j(String key,String value){
@@ -47,6 +51,7 @@ public class RedisLockController {
 	/**
 	 * 测试lock4j 工具
 	 */
+	@ApiOperation("测试lock4j 工具")
 	@GetMapping("/testLock4jLockTemaplate")
 	public  AjaxResult<String> testLock4jLockTemaplate(String key,String value){
 		final LockInfo lockInfo = lockTemplate.lock(key, 30000L, 5000L, RedissonLockExecutor.class);
@@ -72,6 +77,7 @@ public class RedisLockController {
 	/**
 	 * 测试spring-cache注解
 	 */
+	@ApiOperation("测试spring-cache注解")
 	@Cacheable(value = "test", key = "#key")
 	@GetMapping("/testCache")
 	public AjaxResult<String> testCache(String key) {

+ 42 - 0
ruoyi-demo/src/main/java/com/ruoyi/demo/controller/RedisPubSubController.java

@@ -0,0 +1,42 @@
+package com.ruoyi.demo.controller;
+
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.utils.RedisUtils;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.RequiredArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * Redis 发布订阅 演示案例
+ *
+ * @author Lion Li
+ */
+@Api(value = "Redis发布订阅 演示案例", tags = {"Redis发布订阅"})
+@RequiredArgsConstructor(onConstructor_ = @Autowired)
+@RestController
+@RequestMapping("/demo/redis/pubsub")
+public class RedisPubSubController {
+
+	@ApiOperation("发布消息")
+	@GetMapping("/pub")
+	public AjaxResult<Void> pub(String key, String value){
+		RedisUtils.publish(key, value, consumer -> {
+			System.out.println("发布通道 => " + key + ", 发送值 => " + value);
+		});
+		return AjaxResult.success("操作成功");
+	}
+
+	@ApiOperation("订阅消息")
+	@GetMapping("/sub")
+	public AjaxResult<Void> sub(String key){
+		RedisUtils.subscribe(key, String.class, msg -> {
+			System.out.println("订阅通道 => " + key + ", 接收值 => " + msg);
+		});
+		return AjaxResult.success("操作成功");
+	}
+
+}

+ 24 - 2
ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestBatchController.java

@@ -32,10 +32,10 @@ public class TestBatchController extends BaseController {
     private final ITestDemoService iTestDemoService;
 
     /**
-     * 新增批量方法 ( 全量覆盖填充 )
+     * 新增批量方法 可完美替代 saveBatch 秒级插入上万数据 (对mysql负荷较大)
      */
 	@ApiOperation(value = "新增批量方法")
-    @PostMapping()
+    @PostMapping("/add")
 //	@DataSource(DataSourceType.SLAVE)
     public AjaxResult<Void> add() {
 		List<TestDemo> list = new ArrayList<>();
@@ -45,6 +45,28 @@ public class TestBatchController extends BaseController {
         return toAjax(iTestDemoService.saveAll(list) ? 1 : 0);
     }
 
+	/**
+	 * 新增或更新 可完美替代 saveOrUpdateBatch 高性能
+	 */
+	@ApiOperation(value = "新增或更新批量方法")
+	@PostMapping("/addOrUpdate")
+//	@DataSource(DataSourceType.SLAVE)
+	public AjaxResult<Void> addOrUpdate() {
+		List<TestDemo> list = new ArrayList<>();
+		for (int i = 0; i < 1000; i++) {
+			list.add(new TestDemo().setOrderNum(-1L).setTestKey("批量新增").setValue("测试新增"));
+		}
+		iTestDemoService.saveAll(list);
+		for (int i = 0; i < list.size(); i++) {
+			TestDemo testDemo = list.get(i);
+			testDemo.setTestKey("批量新增或修改").setValue("批量新增或修改");
+			if (i % 2 == 0) {
+				testDemo.setId(null);
+			}
+		}
+		return toAjax(iTestDemoService.saveOrUpdateAll(list) ? 1 : 0);
+	}
+
     /**
      * 删除批量方法
      */

+ 6 - 1
ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestDemoController.java

@@ -7,6 +7,7 @@ import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.core.validate.AddGroup;
 import com.ruoyi.common.core.validate.EditGroup;
+import com.ruoyi.common.core.validate.QueryGroup;
 import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.demo.domain.bo.TestDemoBo;
@@ -48,7 +49,7 @@ public class TestDemoController extends BaseController {
     @ApiOperation("查询测试单表列表")
     @PreAuthorize("@ss.hasPermi('demo:demo:list')")
     @GetMapping("/list")
-    public TableDataInfo<TestDemoVo> list(@Validated TestDemoBo bo) {
+    public TableDataInfo<TestDemoVo> list(@Validated(QueryGroup.class) TestDemoBo bo) {
         return iTestDemoService.queryPageList(bo);
     }
 
@@ -71,6 +72,10 @@ public class TestDemoController extends BaseController {
     @GetMapping("/export")
     public void export(@Validated TestDemoBo bo, HttpServletResponse response) {
         List<TestDemoVo> list = iTestDemoService.queryList(bo);
+		// 测试雪花id导出
+//        for (TestDemoVo vo : list) {
+//			vo.setId(1234567891234567893L);
+//		}
 		ExcelUtil.exportExcel(list, "测试单表", TestDemoVo.class, response);
     }
 

+ 4 - 0
ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestI18nController.java

@@ -2,6 +2,8 @@ package com.ruoyi.demo.controller;
 
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.utils.MessageUtils;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
@@ -12,6 +14,7 @@ import org.springframework.web.bind.annotation.RestController;
  *
  * @author Lion Li
  */
+@Api(value = "测试国际化控制器", tags = {"测试国际化管理"})
 @RestController
 @RequestMapping("/demo/i18n")
 public class TestI18nController {
@@ -22,6 +25,7 @@ public class TestI18nController {
 	 *
 	 * 测试使用 user.register.success
 	 */
+	@ApiOperation("通过code获取国际化内容")
 	@GetMapping()
 	public AjaxResult<Void> get(String code) {
 		return AjaxResult.success(MessageUtils.message(code));

+ 2 - 1
ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestTreeController.java

@@ -6,6 +6,7 @@ import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.core.validate.AddGroup;
 import com.ruoyi.common.core.validate.EditGroup;
+import com.ruoyi.common.core.validate.QueryGroup;
 import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.demo.domain.bo.TestTreeBo;
@@ -46,7 +47,7 @@ public class TestTreeController extends BaseController {
     @ApiOperation("查询测试树表列表")
     @PreAuthorize("@ss.hasPermi('demo:tree:list')")
     @GetMapping("/list")
-    public AjaxResult<List<TestTreeVo>> list(@Validated TestTreeBo bo) {
+    public AjaxResult<List<TestTreeVo>> list(@Validated(QueryGroup.class) TestTreeBo bo) {
         List<TestTreeVo> list = iTestTreeService.queryList(bo);
         return AjaxResult.success(list);
     }

+ 0 - 3
ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestDemo.java

@@ -1,8 +1,6 @@
 package com.ruoyi.demo.domain;
 
 import com.baomidou.mybatisplus.annotation.*;
-import com.fasterxml.jackson.databind.annotation.JsonSerialize;
-import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 import lombok.experimental.Accessors;
@@ -29,7 +27,6 @@ public class TestDemo implements Serializable {
 	 * 主键
 	 */
     @TableId(value = "id")
-	@JsonSerialize(using = ToStringSerializer.class)
     private Long id;
 
     /**

+ 1 - 0
ruoyi-demo/src/main/java/com/ruoyi/demo/domain/vo/TestDemoVo.java

@@ -26,6 +26,7 @@ public class TestDemoVo {
 	/**
      *  主键
      */
+	@ExcelProperty(value = "主键")
 	@ApiModelProperty("主键")
 	private Long id;
 

+ 3 - 1
ruoyi-demo/src/main/java/com/ruoyi/demo/feign/FeignTestService.java

@@ -10,7 +10,9 @@ import org.springframework.web.bind.annotation.RequestParam;
  * feign测试service
  * 规范接口 Service 无感调用
  * 常量管理请求路径 更加规范
- * 自定义容错处理 安全可靠
+ * 自定义容错处理 安全可靠 (需自行配置熔断器)
+ * 增加 feign 的目的为使 http 请求接口化
+ *
  * @author Lion Li
  */
 @FeignClient(

+ 2 - 0
ruoyi-demo/src/main/java/com/ruoyi/demo/feign/fallback/FeignTestFallback.java

@@ -10,6 +10,8 @@ import org.springframework.stereotype.Component;
  * 自定义封装结构体熔断
  * 需重写解码器 根据自定义实体 自行解析熔断
  *
+ * 熔断器需要自行添加配置
+ *
  * @see {com.ruoyi.framework.config.FeignConfig#errorDecoder()}
  * @author Lion Li
  */

+ 1 - 1
ruoyi-extend/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi-vue-plus</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>3.0.0</version>
+        <version>3.1.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>ruoyi-extend</artifactId>

+ 1 - 1
ruoyi-extend/ruoyi-monitor-admin/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi-extend</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>3.0.0</version>
+        <version>3.1.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <packaging>jar</packaging>

+ 1 - 1
ruoyi-framework/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi-vue-plus</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>3.0.0</version>
+        <version>3.1.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 2 - 4
ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java

@@ -5,11 +5,9 @@ import com.ruoyi.common.core.domain.BaseEntity;
 import com.ruoyi.common.core.domain.entity.SysRole;
 import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.core.domain.model.LoginUser;
-import com.ruoyi.common.utils.ServletUtils;
+import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.reflect.ReflectUtils;
-import com.ruoyi.common.utils.spring.SpringUtils;
-import com.ruoyi.framework.web.service.TokenService;
 import org.aspectj.lang.JoinPoint;
 import org.aspectj.lang.Signature;
 import org.aspectj.lang.annotation.Aspect;
@@ -78,7 +76,7 @@ public class DataScopeAspect {
 			return;
 		}
 		// 获取当前的用户
-		LoginUser loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest());
+		LoginUser loginUser = SecurityUtils.getLoginUser();
 		if (StringUtils.isNotNull(loginUser)) {
 			SysUser currentUser = loginUser.getUser();
 			// 如果是超级管理员,则不过滤数据

+ 2 - 2
ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java

@@ -5,11 +5,11 @@ import com.ruoyi.common.core.domain.model.LoginUser;
 import com.ruoyi.common.enums.BusinessStatus;
 import com.ruoyi.common.enums.HttpMethod;
 import com.ruoyi.common.utils.JsonUtils;
+import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.ServletUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.spring.SpringUtils;
 import com.ruoyi.framework.web.service.AsyncService;
-import com.ruoyi.framework.web.service.TokenService;
 import com.ruoyi.system.domain.SysOperLog;
 import org.aspectj.lang.JoinPoint;
 import org.aspectj.lang.Signature;
@@ -83,7 +83,7 @@ public class LogAspect
             }
 
             // 获取当前的用户
-            LoginUser loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest());
+            LoginUser loginUser = SecurityUtils.getLoginUser();
 
             // *========数据库日志=========*//
             SysOperLog operLog = new SysOperLog();

+ 16 - 9
ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java

@@ -1,10 +1,14 @@
 package com.ruoyi.framework.config;
 
-import java.awt.*;
-
-import cn.hutool.captcha.*;
+import cn.hutool.captcha.CaptchaUtil;
+import cn.hutool.captcha.CircleCaptcha;
+import cn.hutool.captcha.LineCaptcha;
+import cn.hutool.captcha.ShearCaptcha;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Lazy;
+
+import java.awt.*;
 
 /**
  * 验证码配置
@@ -22,8 +26,9 @@ public class CaptchaConfig {
     /**
      * 圆圈干扰验证码
      */
-    @Bean(name = "CircleCaptcha")
-    public CircleCaptcha getCircleCaptcha() {
+    @Lazy
+    @Bean
+    public CircleCaptcha circleCaptcha() {
         CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(width, height);
         captcha.setBackground(background);
         captcha.setFont(font);
@@ -33,8 +38,9 @@ public class CaptchaConfig {
     /**
      * 线段干扰的验证码
      */
-    @Bean(name = "LineCaptcha")
-    public LineCaptcha getLineCaptcha() {
+    @Lazy
+    @Bean
+    public LineCaptcha lineCaptcha() {
         LineCaptcha captcha = CaptchaUtil.createLineCaptcha(width, height);
         captcha.setBackground(background);
         captcha.setFont(font);
@@ -44,8 +50,9 @@ public class CaptchaConfig {
     /**
      * 扭曲干扰验证码
      */
-    @Bean(name = "ShearCaptcha")
-    public ShearCaptcha getShearCaptcha() {
+    @Lazy
+    @Bean
+    public ShearCaptcha shearCaptcha() {
         ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(width, height);
         captcha.setBackground(background);
         captcha.setFont(font);

+ 20 - 26
ruoyi-framework/src/main/java/com/ruoyi/framework/config/JacksonConfig.java

@@ -5,17 +5,18 @@ import com.fasterxml.jackson.databind.module.SimpleModule;
 import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
 import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
-import com.ruoyi.common.utils.JsonUtils;
 import com.ruoyi.framework.jackson.BigNumberSerializer;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.springframework.boot.autoconfigure.jackson.JacksonProperties;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
 
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
 import java.util.TimeZone;
 
 /**
@@ -27,30 +28,23 @@ import java.util.TimeZone;
 @Configuration
 public class JacksonConfig {
 
+	@Primary
 	@Bean
-	public BeanPostProcessor objectMapperBeanPostProcessor() {
-		return new BeanPostProcessor() {
-			@Override
-			public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
-				if (!(bean instanceof ObjectMapper)) {
-					return bean;
-				}
-				ObjectMapper objectMapper = (ObjectMapper) bean;
-				// 全局配置序列化返回 JSON 处理
-				SimpleModule simpleModule = new SimpleModule();
-				simpleModule.addSerializer(Long.class, BigNumberSerializer.INSTANCE);
-				simpleModule.addSerializer(Long.TYPE, BigNumberSerializer.INSTANCE);
-				simpleModule.addSerializer(BigInteger.class, BigNumberSerializer.INSTANCE);
-				simpleModule.addSerializer(BigDecimal.class, ToStringSerializer.instance);
-				simpleModule.addSerializer(LocalDateTime.class, LocalDateTimeSerializer.INSTANCE);
-				simpleModule.addDeserializer(LocalDateTime.class, LocalDateTimeDeserializer.INSTANCE);
-				objectMapper.registerModule(simpleModule);
-				objectMapper.setTimeZone(TimeZone.getDefault());
-				JsonUtils.init(objectMapper);
-				log.info("初始化 jackson 配置");
-				return bean;
-			}
-		};
+	public ObjectMapper getObjectMapper(Jackson2ObjectMapperBuilder builder, JacksonProperties jacksonProperties) {
+		ObjectMapper objectMapper = builder.createXmlMapper(false).build();
+		// 全局配置序列化返回 JSON 处理
+		SimpleModule simpleModule = new SimpleModule();
+		simpleModule.addSerializer(Long.class, BigNumberSerializer.INSTANCE);
+		simpleModule.addSerializer(Long.TYPE, BigNumberSerializer.INSTANCE);
+		simpleModule.addSerializer(BigInteger.class, BigNumberSerializer.INSTANCE);
+		simpleModule.addSerializer(BigDecimal.class, ToStringSerializer.instance);
+		DateTimeFormatter formatter = DateTimeFormatter.ofPattern(jacksonProperties.getDateFormat());
+		simpleModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter));
+		simpleModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatter));
+		objectMapper.registerModule(simpleModule);
+		objectMapper.setTimeZone(TimeZone.getDefault());
+		log.info("初始化 jackson 配置");
+		return objectMapper;
 	}
 
 }

+ 5 - 5
ruoyi-framework/src/main/java/com/ruoyi/framework/config/MybatisPlusConfig.java

@@ -1,10 +1,10 @@
 package com.ruoyi.framework.config;
 
-import com.baomidou.mybatisplus.annotation.DbType;
 import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
 import com.baomidou.mybatisplus.core.injector.AbstractMethod;
 import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
 import com.baomidou.mybatisplus.core.injector.ISqlInjector;
+import com.baomidou.mybatisplus.core.metadata.TableInfo;
 import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
 import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
 import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
@@ -46,10 +46,10 @@ public class MybatisPlusConfig {
 	 */
 	public PaginationInnerInterceptor paginationInnerInterceptor() {
 		PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
-		// 设置数据库类型为mysql
-		paginationInnerInterceptor.setDbType(DbType.MYSQL);
 		// 设置最大单页限制数量,默认 500 条,-1 不受限制
 		paginationInnerInterceptor.setMaxLimit(-1L);
+		// 分页合理化
+		paginationInnerInterceptor.setOverflow(true);
 		return paginationInnerInterceptor;
 	}
 
@@ -104,8 +104,8 @@ public class MybatisPlusConfig {
 	public ISqlInjector sqlInjector() {
 		return new DefaultSqlInjector() {
 			@Override
-			public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
-				List<AbstractMethod> methodList = super.getMethodList(mapperClass);
+			public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
+				List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
 				methodList.add(new InsertAll());
 				return methodList;
 			}

+ 5 - 1
ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java

@@ -3,6 +3,7 @@ package com.ruoyi.framework.config;
 import cn.hutool.core.util.StrUtil;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.framework.config.properties.RedissonProperties;
+import lombok.extern.slf4j.Slf4j;
 import org.redisson.Redisson;
 import org.redisson.api.RedissonClient;
 import org.redisson.codec.JsonJacksonCodec;
@@ -29,6 +30,7 @@ import java.util.Map;
  *
  * @author Lion Li
  */
+@Slf4j
 @Configuration
 @EnableCaching
 public class RedisConfig extends CachingConfigurerSupport {
@@ -73,7 +75,9 @@ public class RedisConfig extends CachingConfigurerSupport {
 			.setConnectionMinimumIdleSize(singleServerConfig.getConnectionMinimumIdleSize())
 			.setConnectionPoolSize(singleServerConfig.getConnectionPoolSize())
 			.setDnsMonitoringInterval(singleServerConfig.getDnsMonitoringInterval());
-		return Redisson.create(config);
+		RedissonClient redissonClient = Redisson.create(config);
+		log.info("初始化 redis 配置");
+		return redissonClient;
 	}
 
 	/**

+ 2 - 16
ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java

@@ -1,6 +1,7 @@
 package com.ruoyi.framework.config;
 
 import com.ruoyi.common.utils.Threads;
+import com.ruoyi.common.utils.reflect.ReflectUtils;
 import com.ruoyi.framework.config.properties.ThreadPoolProperties;
 import org.apache.commons.lang3.concurrent.BasicThreadFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -12,7 +13,6 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 import java.util.concurrent.RejectedExecutionHandler;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ScheduledThreadPoolExecutor;
-import java.util.concurrent.ThreadPoolExecutor;
 
 /**
  * 线程池配置
@@ -33,21 +33,7 @@ public class ThreadPoolConfig {
         executor.setCorePoolSize(threadPoolProperties.getCorePoolSize());
         executor.setQueueCapacity(threadPoolProperties.getQueueCapacity());
         executor.setKeepAliveSeconds(threadPoolProperties.getKeepAliveSeconds());
-        RejectedExecutionHandler handler;
-        switch (threadPoolProperties.getRejectedExecutionHandler()) {
-            case "CallerRunsPolicy":
-                handler = new ThreadPoolExecutor.CallerRunsPolicy();
-                break;
-            case "DiscardOldestPolicy":
-                handler = new ThreadPoolExecutor.DiscardOldestPolicy();
-                break;
-            case "DiscardPolicy":
-                handler = new ThreadPoolExecutor.DiscardPolicy();
-                break;
-            default:
-                handler = new ThreadPoolExecutor.AbortPolicy();
-                break;
-        }
+        RejectedExecutionHandler handler = ReflectUtils.newInstance(threadPoolProperties.getRejectedExecutionHandler().getClazz());
         executor.setRejectedExecutionHandler(handler);
         return executor;
     }

+ 4 - 2
ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/CaptchaProperties.java

@@ -1,5 +1,7 @@
 package com.ruoyi.framework.config.properties;
 
+import com.ruoyi.common.enums.CaptchaCategory;
+import com.ruoyi.common.enums.CaptchaType;
 import lombok.Data;
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.stereotype.Component;
@@ -17,12 +19,12 @@ public class CaptchaProperties {
 	/**
 	 * 验证码类型
  	 */
-    private String type;
+    private CaptchaType type;
 
 	/**
 	 * 验证码类别
 	 */
-    private String category;
+    private CaptchaCategory category;
 
 	/**
 	 * 数字验证码位数

+ 2 - 1
ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/ThreadPoolProperties.java

@@ -1,5 +1,6 @@
 package com.ruoyi.framework.config.properties;
 
+import com.ruoyi.common.enums.ThreadPoolRejectedPolicy;
 import lombok.Data;
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.stereotype.Component;
@@ -42,6 +43,6 @@ public class ThreadPoolProperties {
     /**
      * 线程池对拒绝任务(无线程可用)的处理策略
      */
-    private String rejectedExecutionHandler;
+    private ThreadPoolRejectedPolicy rejectedExecutionHandler;
 
 }

+ 3 - 4
ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java

@@ -4,9 +4,9 @@ import cn.hutool.core.convert.Convert;
 import cn.hutool.core.io.IoUtil;
 import com.ruoyi.common.annotation.RepeatSubmit;
 import com.ruoyi.common.constant.Constants;
-import com.ruoyi.common.core.redis.RedisCache;
 import com.ruoyi.common.filter.RepeatedlyRequestWrapper;
 import com.ruoyi.common.utils.JsonUtils;
+import com.ruoyi.common.utils.RedisUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.framework.config.properties.RepeatSubmitProperties;
 import com.ruoyi.framework.config.properties.TokenProperties;
@@ -38,7 +38,6 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor {
 
 	private final TokenProperties tokenProperties;
 	private final RepeatSubmitProperties repeatSubmitProperties;
-	private final RedisCache redisCache;
 
 
 	@SuppressWarnings("unchecked")
@@ -79,7 +78,7 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor {
 		// 唯一标识(指定key + 消息头)
 		String cacheRepeatKey = Constants.REPEAT_SUBMIT_KEY + submitKey;
 
-		Object sessionObj = redisCache.getCacheObject(cacheRepeatKey);
+		Object sessionObj = RedisUtils.getCacheObject(cacheRepeatKey);
 		if (sessionObj != null) {
 			Map<String, Object> sessionMap = (Map<String, Object>) sessionObj;
 			if (sessionMap.containsKey(url)) {
@@ -91,7 +90,7 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor {
 		}
 		Map<String, Object> cacheMap = new HashMap<String, Object>();
 		cacheMap.put(url, nowDataMap);
-		redisCache.setCacheObject(cacheRepeatKey, cacheMap, Convert.toInt(intervalTime), TimeUnit.MILLISECONDS);
+		RedisUtils.setCacheObject(cacheRepeatKey, cacheMap, Convert.toInt(intervalTime), TimeUnit.MILLISECONDS);
 		return false;
 	}
 

+ 6 - 10
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java

@@ -1,10 +1,9 @@
 package com.ruoyi.framework.web.service;
 
-import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.core.domain.entity.SysRole;
 import com.ruoyi.common.core.domain.model.LoginUser;
-import com.ruoyi.common.utils.ServletUtils;
-import org.springframework.beans.factory.annotation.Autowired;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
 
@@ -28,9 +27,6 @@ public class PermissionService
 
     private static final String PERMISSION_DELIMETER = ",";
 
-    @Autowired
-    private TokenService tokenService;
-
     /**
      * 验证用户是否具备某权限
      *
@@ -43,7 +39,7 @@ public class PermissionService
         {
             return false;
         }
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        LoginUser loginUser = SecurityUtils.getLoginUser();
         if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions()))
         {
             return false;
@@ -74,7 +70,7 @@ public class PermissionService
         {
             return false;
         }
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        LoginUser loginUser = SecurityUtils.getLoginUser();
         if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions()))
         {
             return false;
@@ -102,7 +98,7 @@ public class PermissionService
         {
             return false;
         }
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        LoginUser loginUser = SecurityUtils.getLoginUser();
         if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles()))
         {
             return false;
@@ -141,7 +137,7 @@ public class PermissionService
         {
             return false;
         }
-        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
+        LoginUser loginUser = SecurityUtils.getLoginUser();
         if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles()))
         {
             return false;

+ 3 - 6
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java

@@ -3,13 +3,13 @@ package com.ruoyi.framework.web.service;
 import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.core.domain.model.LoginUser;
-import com.ruoyi.common.core.redis.RedisCache;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.exception.user.CaptchaException;
 import com.ruoyi.common.exception.user.CaptchaExpireException;
 import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
 import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.RedisUtils;
 import com.ruoyi.common.utils.ServletUtils;
 import com.ruoyi.system.service.ISysConfigService;
 import com.ruoyi.system.service.ISysUserService;
@@ -37,9 +37,6 @@ public class SysLoginService
     @Resource
     private AuthenticationManager authenticationManager;
 
-    @Autowired
-    private RedisCache redisCache;
-
 	@Autowired
     private ISysUserService userService;
 
@@ -105,8 +102,8 @@ public class SysLoginService
      */
     public void validateCaptcha(String username, String code, String uuid, HttpServletRequest request) {
 		String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
-		String captcha = redisCache.getCacheObject(verifyKey);
-		redisCache.deleteObject(verifyKey);
+		String captcha = RedisUtils.getCacheObject(verifyKey);
+        RedisUtils.deleteObject(verifyKey);
 		if (captcha == null) {
 			asyncService.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"), request);
 			throw new CaptchaExpireException();

+ 3 - 10
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java

@@ -4,13 +4,9 @@ import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.constant.UserConstants;
 import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.core.domain.model.RegisterBody;
-import com.ruoyi.common.core.redis.RedisCache;
 import com.ruoyi.common.exception.user.CaptchaException;
 import com.ruoyi.common.exception.user.CaptchaExpireException;
-import com.ruoyi.common.utils.MessageUtils;
-import com.ruoyi.common.utils.SecurityUtils;
-import com.ruoyi.common.utils.ServletUtils;
-import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.*;
 import com.ruoyi.system.service.ISysConfigService;
 import com.ruoyi.system.service.ISysUserService;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -30,9 +26,6 @@ public class SysRegisterService
     @Autowired
     private ISysConfigService configService;
 
-    @Autowired
-    private RedisCache redisCache;
-
 	@Autowired
 	private AsyncService asyncService;
 
@@ -103,8 +96,8 @@ public class SysRegisterService
     public void validateCaptcha(String username, String code, String uuid)
     {
         String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
-        String captcha = redisCache.getCacheObject(verifyKey);
-        redisCache.deleteObject(verifyKey);
+        String captcha = RedisUtils.getCacheObject(verifyKey);
+        RedisUtils.deleteObject(verifyKey);
         if (captcha == null)
         {
             throw new CaptchaExpireException();

+ 4 - 7
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java

@@ -5,7 +5,7 @@ import cn.hutool.http.useragent.UserAgent;
 import cn.hutool.http.useragent.UserAgentUtil;
 import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.core.domain.model.LoginUser;
-import com.ruoyi.common.core.redis.RedisCache;
+import com.ruoyi.common.utils.RedisUtils;
 import com.ruoyi.common.utils.ServletUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.ip.AddressUtils;
@@ -36,9 +36,6 @@ public class TokenService {
     private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L;
 
     @Autowired
-    private RedisCache redisCache;
-
-    @Autowired
     private TokenProperties tokenProperties;
 
     /**
@@ -55,7 +52,7 @@ public class TokenService {
 				// 解析对应的权限以及用户信息
 				String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
 				String userKey = getTokenKey(uuid);
-				LoginUser user = redisCache.getCacheObject(userKey);
+				LoginUser user = RedisUtils.getCacheObject(userKey);
 				return user;
 			} catch (Exception e) {
 
@@ -79,7 +76,7 @@ public class TokenService {
     public void delLoginUser(String token) {
         if (StringUtils.isNotEmpty(token)) {
             String userKey = getTokenKey(token);
-            redisCache.deleteObject(userKey);
+            RedisUtils.deleteObject(userKey);
         }
     }
 
@@ -124,7 +121,7 @@ public class TokenService {
         loginUser.setExpireTime(loginUser.getLoginTime() + tokenProperties.getExpireTime() * MILLIS_MINUTE);
         // 根据uuid将loginUser缓存
         String userKey = getTokenKey(loginUser.getToken());
-        redisCache.setCacheObject(userKey, loginUser, tokenProperties.getExpireTime(), TimeUnit.MINUTES);
+        RedisUtils.setCacheObject(userKey, loginUser, tokenProperties.getExpireTime(), TimeUnit.MINUTES);
     }
 
     /**

+ 1 - 1
ruoyi-generator/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi-vue-plus</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>3.0.0</version>
+        <version>3.1.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 8 - 0
ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java

@@ -44,6 +44,7 @@ public class GenTableColumn implements Serializable {
     /**
      * 列描述
      */
+    @TableField(updateStrategy = FieldStrategy.IGNORED)
     private String columnComment;
 
     /**
@@ -65,36 +66,43 @@ public class GenTableColumn implements Serializable {
     /**
      * 是否主键(1是)
      */
+    @TableField(updateStrategy = FieldStrategy.IGNORED)
     private String isPk;
 
     /**
      * 是否自增(1是)
      */
+    @TableField(updateStrategy = FieldStrategy.IGNORED)
     private String isIncrement;
 
     /**
      * 是否必填(1是)
      */
+    @TableField(updateStrategy = FieldStrategy.IGNORED)
     private String isRequired;
 
     /**
      * 是否为插入字段(1是)
      */
+    @TableField(updateStrategy = FieldStrategy.IGNORED)
     private String isInsert;
 
     /**
      * 是否编辑字段(1是)
      */
+    @TableField(updateStrategy = FieldStrategy.IGNORED)
     private String isEdit;
 
     /**
      * 是否列表字段(1是)
      */
+    @TableField(updateStrategy = FieldStrategy.IGNORED)
     private String isList;
 
     /**
      * 是否查询字段(1是)
      */
+    @TableField(updateStrategy = FieldStrategy.IGNORED)
     private String isQuery;
 
     /**

+ 22 - 29
ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java

@@ -2,9 +2,7 @@ package com.ruoyi.generator.service;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.convert.Convert;
-import com.ruoyi.common.utils.StringUtils;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.constant.GenConstants;
 import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
@@ -13,6 +11,7 @@ import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.JsonUtils;
 import com.ruoyi.common.utils.PageUtils;
 import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.file.FileUtils;
 import com.ruoyi.generator.domain.GenTable;
 import com.ruoyi.generator.domain.GenTableColumn;
@@ -34,10 +33,7 @@ import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.IOException;
 import java.io.StringWriter;
-import java.util.Arrays;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.stream.Collectors;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipOutputStream;
@@ -134,18 +130,7 @@ public class GenTableServiceImpl extends ServicePlusImpl<GenTableMapper, GenTabl
         int row = baseMapper.updateById(genTable);
         if (row > 0) {
             for (GenTableColumn cenTableColumn : genTable.getColumns()) {
-                genTableColumnMapper.update(cenTableColumn,
-                        new LambdaUpdateWrapper<GenTableColumn>()
-							.set(StringUtils.isBlank(cenTableColumn.getColumnComment()), GenTableColumn::getColumnComment, null)
-							.set(StringUtils.isBlank(cenTableColumn.getIsPk()), GenTableColumn::getIsPk, null)
-							.set(StringUtils.isBlank(cenTableColumn.getIsIncrement()), GenTableColumn::getIsIncrement, null)
-							.set(StringUtils.isBlank(cenTableColumn.getIsInsert()), GenTableColumn::getIsInsert, null)
-							.set(StringUtils.isBlank(cenTableColumn.getIsEdit()), GenTableColumn::getIsEdit, null)
-							.set(StringUtils.isBlank(cenTableColumn.getIsList()), GenTableColumn::getIsList, null)
-							.set(StringUtils.isBlank(cenTableColumn.getIsQuery()), GenTableColumn::getIsQuery, null)
-							.set(StringUtils.isBlank(cenTableColumn.getIsRequired()), GenTableColumn::getIsRequired, null)
-							.set(StringUtils.isBlank(cenTableColumn.getDictType()), GenTableColumn::getDictType, "")
-							.eq(GenTableColumn::getColumnId,cenTableColumn.getColumnId()));
+                genTableColumnMapper.updateById(cenTableColumn);
             }
         }
     }
@@ -178,13 +163,17 @@ public class GenTableServiceImpl extends ServicePlusImpl<GenTableMapper, GenTabl
                 String tableName = table.getTableName();
                 GenUtils.initTable(table, operName);
                 int row = baseMapper.insert(table);
-                if (row > 0) {
-                    // 保存列信息
-                    List<GenTableColumn> genTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
-                    for (GenTableColumn column : genTableColumns) {
-                        GenUtils.initColumnField(column, table);
-						genTableColumnMapper.insert(column);
-                    }
+				if (row > 0) {
+					// 保存列信息
+					List<GenTableColumn> genTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
+					List<GenTableColumn> saveColumns = new ArrayList<>();
+					for (GenTableColumn column : genTableColumns) {
+						GenUtils.initColumnField(column, table);
+						saveColumns.add(column);
+					}
+					if (CollUtil.isNotEmpty(saveColumns)) {
+						genTableColumnMapper.insertAll(saveColumns);
+					}
 				}
             }
         } catch (Exception e) {
@@ -292,12 +281,16 @@ public class GenTableServiceImpl extends ServicePlusImpl<GenTableMapper, GenTabl
         }
         List<String> dbTableColumnNames = dbTableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList());
 
-        dbTableColumns.forEach(column -> {
-            if (!tableColumnNames.contains(column.getColumnName())) {
-                GenUtils.initColumnField(column, table);
-				genTableColumnMapper.insert(column);
+		List<GenTableColumn> saveColumns = new ArrayList<>();
+		dbTableColumns.forEach(column -> {
+			if (!tableColumnNames.contains(column.getColumnName())) {
+				GenUtils.initColumnField(column, table);
+				saveColumns.add(column);
 			}
 		});
+		if (CollUtil.isNotEmpty(saveColumns)) {
+			genTableColumnMapper.insertAll(saveColumns);
+		}
 
         List<GenTableColumn> delColumns = tableColumns.stream().filter(column -> !dbTableColumnNames.contains(column.getColumnName())).collect(Collectors.toList());
         if (CollUtil.isNotEmpty(delColumns)) {

+ 3 - 2
ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java

@@ -164,9 +164,10 @@ public class GenUtils
      */
     public static String getBusinessName(String tableName)
     {
-        int lastIndex = tableName.lastIndexOf("_");
+        int firstIndex = tableName.indexOf("_");
         int nameLength = tableName.length();
-        String businessName = StringUtils.substring(tableName, lastIndex + 1, nameLength);
+        String businessName = StringUtils.substring(tableName, firstIndex + 1, nameLength);
+		businessName = StringUtils.toCamelCase(businessName);
         return businessName;
     }
 

+ 3 - 1
ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml

@@ -92,6 +92,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 		<if test="genTable.params.endTime != null and genTable.params.endTime != ''"><!-- 结束时间检索 -->
 			AND date_format(create_time,'%y%m%d') &lt;= date_format(#{genTable.params.endTime},'%y%m%d')
 		</if>
+		order by create_time desc
 	</select>
 
 
@@ -130,6 +131,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 		<if test="params.endTime != null and params.endTime != ''"><!-- 结束时间检索 -->
 			AND date_format(create_time,'%y%m%d') &lt;= date_format(#{params.endTime},'%y%m%d')
 		</if>
+        order by create_time desc
 	</select>
 	
 	<select id="selectDbTableListByNames" resultMap="GenTableResult">
@@ -162,7 +164,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 			 LEFT JOIN gen_table_column c ON t.table_id = c.table_id
 		where t.table_name = #{tableName} order by c.sort
 	</select>
-
+	
 	<select id="selectGenTableAll" parameterType="String" resultMap="GenTableResult">
 	    SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.options, t.remark,
 			   c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort

+ 3 - 2
ruoyi-generator/src/main/resources/vm/java/controller.java.vm

@@ -17,6 +17,7 @@ import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.core.validate.AddGroup;
 import com.ruoyi.common.core.validate.EditGroup;
+import com.ruoyi.common.core.validate.QueryGroup;
 import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import ${packageName}.domain.vo.${ClassName}Vo;
@@ -51,11 +52,11 @@ public class ${ClassName}Controller extends BaseController {
     @PreAuthorize("@ss.hasPermi('${permissionPrefix}:list')")
     @GetMapping("/list")
 #if($table.crud || $table.sub)
-    public TableDataInfo<${ClassName}Vo> list(@Validated ${ClassName}Bo bo) {
+    public TableDataInfo<${ClassName}Vo> list(@Validated(QueryGroup.class) ${ClassName}Bo bo) {
         return i${ClassName}Service.queryPageList(bo);
     }
 #elseif($table.tree)
-    public AjaxResult<List<${ClassName}Vo>> list(@Validated ${ClassName}Bo bo) {
+    public AjaxResult<List<${ClassName}Vo>> list(@Validated(QueryGroup.class) ${ClassName}Bo bo) {
         List<${ClassName}Vo> list = i${ClassName}Service.queryList(bo);
         return AjaxResult.success(list);
     }

+ 5 - 15
ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm

@@ -106,7 +106,11 @@
         </template>
       </el-table-column>
 #elseif($column.list && $column.dictType && "" != $column.dictType)
-      <el-table-column label="${comment}" align="center" prop="${javaField}" :formatter="${javaField}Format" />
+      <el-table-column label="${comment}" align="center" prop="${javaField}">
+        <template slot-scope="scope">
+          <dict-tag :options="${javaField}Options" :value="scope.row.${javaField}"/>
+        </template>
+      </el-table-column>
 #elseif($column.list && "" != $javaField)
 #if(${foreach.index} == 1)
       <el-table-column label="${comment}" prop="${javaField}" />
@@ -378,20 +382,6 @@ export default {
         this.${businessName}Options.push(data);
       });
     },
-#foreach ($column in $columns)
-#if(${column.dictType} && ${column.dictType} != '')
-#set($parentheseIndex=$column.columnComment.indexOf("("))
-#if($parentheseIndex != -1)
-#set($comment=$column.columnComment.substring(0, $parentheseIndex))
-#else
-#set($comment=$column.columnComment)
-#end
-    // $comment字典翻译
-    ${column.javaField}Format(row, column) {
-      return this.selectDictLabel#if($column.htmlType == "checkbox")s#end(this.${column.javaField}Options, row.${column.javaField});
-    },
-#end
-#end
     // 取消按钮
     cancel() {
       this.open = false;

+ 6 - 17
ruoyi-generator/src/main/resources/vm/vue/index.vue.vm

@@ -135,7 +135,11 @@
         </template>
       </el-table-column>
 #elseif($column.list && $column.dictType && "" != $column.dictType)
-      <el-table-column label="${comment}" align="center" prop="${javaField}" :formatter="${javaField}Format" />
+      <el-table-column label="${comment}" align="center" prop="${javaField}">
+        <template slot-scope="scope">
+          <dict-tag :options="${javaField}Options" :value="scope.row.${javaField}"/>
+        </template>
+      </el-table-column>
 #elseif($column.list && "" != $javaField)
       <el-table-column label="${comment}" align="center" prop="${javaField}" />
 #end
@@ -308,7 +312,6 @@
 
 <script>
 import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}";
-import { downLoadExcel } from "@/utils/download";
 
 export default {
   name: "${BusinessName}",
@@ -427,20 +430,6 @@ export default {
         this.loading = false;
       });
     },
-#foreach ($column in $columns)
-#if(${column.dictType} && ${column.dictType} != '')
-#set($parentheseIndex=$column.columnComment.indexOf("("))
-#if($parentheseIndex != -1)
-#set($comment=$column.columnComment.substring(0, $parentheseIndex))
-#else
-#set($comment=$column.columnComment)
-#end
-    // $comment字典翻译
-    ${column.javaField}Format(row, column) {
-      return this.selectDictLabel#if($column.htmlType == "checkbox")s#end(this.${column.javaField}Options, row.${column.javaField});
-    },
-#end
-#end
     // 取消按钮
     cancel() {
       this.open = false;
@@ -601,7 +590,7 @@ export default {
 #end
     /** 导出按钮操作 */
     handleExport() {
-      downLoadExcel('/${moduleName}/${businessName}/export', this.queryParams);
+      this.downLoadExcel('/${moduleName}/${businessName}/export', this.queryParams);
     }
   }
 };

+ 1 - 1
ruoyi-oss/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi-vue-plus</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>3.0.0</version>
+        <version>3.1.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 18 - 22
ruoyi-oss/src/main/java/com/ruoyi/oss/factory/OssFactory.java

@@ -1,19 +1,18 @@
 package com.ruoyi.oss.factory;
 
 import cn.hutool.core.convert.Convert;
-import com.ruoyi.common.core.redis.RedisCache;
 import com.ruoyi.common.utils.JsonUtils;
+import com.ruoyi.common.utils.RedisUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.reflect.ReflectUtils;
-import com.ruoyi.common.utils.spring.SpringUtils;
 import com.ruoyi.oss.constant.CloudConstant;
 import com.ruoyi.oss.enumd.CloudServiceEnumd;
 import com.ruoyi.oss.exception.OssException;
 import com.ruoyi.oss.properties.CloudStorageProperties;
 import com.ruoyi.oss.service.ICloudStorageStrategy;
 import com.ruoyi.oss.service.abstractd.AbstractCloudStorageStrategy;
+import lombok.extern.slf4j.Slf4j;
 
-import java.util.Date;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -22,12 +21,14 @@ import java.util.concurrent.ConcurrentHashMap;
  *
  * @author Lion Li
  */
+@Slf4j
 public class OssFactory {
 
-	private static RedisCache redisCache;
-
 	static {
-		OssFactory.redisCache = SpringUtils.getBean(RedisCache.class);
+		RedisUtils.subscribe(CloudConstant.CACHE_CONFIG_KEY, String.class, msg -> {
+			refreshService(msg);
+			log.info("订阅刷新OSS配置 => " + msg);
+		});
 	}
 
 	/**
@@ -36,16 +37,11 @@ public class OssFactory {
 	private static final Map<String, ICloudStorageStrategy> SERVICES = new ConcurrentHashMap<>();
 
 	/**
-	 * 服务配置更新时间缓存
-	 */
-	private static final Map<String, Date> SERVICES_UPDATE_TIME = new ConcurrentHashMap<>();
-
-	/**
 	 * 获取默认实例
 	 */
 	public static ICloudStorageStrategy instance() {
 		// 获取redis 默认类型
-		String type = Convert.toStr(redisCache.getCacheObject(CloudConstant.CACHE_CONFIG_KEY));
+		String type = Convert.toStr(RedisUtils.getCacheObject(CloudConstant.CACHE_CONFIG_KEY));
 		if (StringUtils.isEmpty(type)) {
 			throw new OssException("文件存储服务类型无法找到!");
 		}
@@ -57,23 +53,23 @@ public class OssFactory {
 	 */
 	public static ICloudStorageStrategy instance(String type) {
 		ICloudStorageStrategy service = SERVICES.get(type);
-		Date oldDate = SERVICES_UPDATE_TIME.get(type);
-		Object json = redisCache.getCacheObject(CloudConstant.SYS_OSS_KEY + type);
+		if (service == null) {
+			refreshService(type);
+			service = SERVICES.get(type);
+		}
+		return service;
+	}
+
+	private static void refreshService(String type) {
+		Object json = RedisUtils.getCacheObject(CloudConstant.SYS_OSS_KEY + type);
 		CloudStorageProperties properties = JsonUtils.parseObject(json.toString(), CloudStorageProperties.class);
 		if (properties == null) {
 			throw new OssException("系统异常, '" + type + "'配置信息不存在!");
 		}
-		Date nowDate = properties.getUpdateTime();
-		// 服务存在并更新时间相同则返回(使用更新时间确保配置最终一致性)
-		if (service != null && oldDate.equals(nowDate)) {
-			return service;
-		}
 		// 获取redis配置信息 创建对象 并缓存
-		service = (ICloudStorageStrategy) ReflectUtils.newInstance(CloudServiceEnumd.getServiceClass(type));
+		ICloudStorageStrategy service = (ICloudStorageStrategy) ReflectUtils.newInstance(CloudServiceEnumd.getServiceClass(type));
 		((AbstractCloudStorageStrategy)service).init(properties);
 		SERVICES.put(type, service);
-		SERVICES_UPDATE_TIME.put(type, nowDate);
-		return service;
 	}
 
 }

+ 2 - 3
ruoyi-oss/src/main/java/com/ruoyi/oss/service/abstractd/AbstractCloudStorageStrategy.java

@@ -1,15 +1,14 @@
 package com.ruoyi.oss.service.abstractd;
 
-import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.io.IoUtil;
 import cn.hutool.core.util.IdUtil;
+import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.oss.entity.UploadResult;
 import com.ruoyi.oss.properties.CloudStorageProperties;
 import com.ruoyi.oss.service.ICloudStorageStrategy;
 
 import java.io.InputStream;
-import java.util.Date;
 
 /**
  * 云存储策略(支持七牛、阿里云、腾讯云、minio)
@@ -33,7 +32,7 @@ public abstract class AbstractCloudStorageStrategy implements ICloudStorageStrat
 		// 生成uuid
 		String uuid = IdUtil.fastSimpleUUID();
 		// 文件路径
-		String path = DateUtil.format(new Date(), "yyyyMMdd") + "/" + uuid;
+		String path = DateUtils.datePath() + "/" + uuid;
 		if (StringUtils.isNotBlank(prefix)) {
 			path = prefix + "/" + path;
 		}

+ 4 - 4
ruoyi-oss/src/main/java/com/ruoyi/oss/service/impl/AliyunCloudStorageStrategy.java

@@ -36,7 +36,7 @@ public class AliyunCloudStorageStrategy extends AbstractCloudStorageStrategy {
 			client = new OSSClient(properties.getEndpoint(), credentialProvider, configuration);
 			createBucket();
 		} catch (Exception e) {
-			throw new OssException("阿里云存储配置错误! 请检查系统配置!");
+			throw new OssException("阿里云存储配置错误! 请检查系统配置:[" + e.getMessage() + "]");
 		}
 	}
 
@@ -51,7 +51,7 @@ public class AliyunCloudStorageStrategy extends AbstractCloudStorageStrategy {
 			createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
 			client.createBucket(createBucketRequest);
 		} catch (Exception e) {
-			throw new OssException("创建Bucket失败, 请核对阿里云配置信息");
+			throw new OssException("创建Bucket失败, 请核对阿里云配置信息:[" + e.getMessage() + "]");
 		}
 	}
 
@@ -72,7 +72,7 @@ public class AliyunCloudStorageStrategy extends AbstractCloudStorageStrategy {
 			metadata.setContentType(contentType);
 			client.putObject(new PutObjectRequest(properties.getBucketName(), path, inputStream, metadata));
 		} catch (Exception e) {
-			throw new OssException("上传文件失败,请检查阿里云配置信息");
+			throw new OssException("上传文件失败,请检查阿里云配置信息:[" + e.getMessage() + "]");
 		}
 		return new UploadResult().setUrl(getEndpointLink() + "/" + path).setFilename(path);
 	}
@@ -83,7 +83,7 @@ public class AliyunCloudStorageStrategy extends AbstractCloudStorageStrategy {
 		try {
 			client.deleteObject(properties.getBucketName(), path);
 		} catch (Exception e) {
-			throw new OssException("上传文件失败,请检查阿里云配置信息");
+			throw new OssException("上传文件失败,请检查阿里云配置信息:[" + e.getMessage() + "]");
 		}
 	}
 

+ 4 - 4
ruoyi-oss/src/main/java/com/ruoyi/oss/service/impl/MinioCloudStorageStrategy.java

@@ -32,7 +32,7 @@ public class MinioCloudStorageStrategy extends AbstractCloudStorageStrategy {
 				.build();
 			createBucket();
 		} catch (Exception e) {
-			throw new OssException("Minio存储配置错误! 请检查系统配置!");
+			throw new OssException("Minio存储配置错误! 请检查系统配置:[" + e.getMessage() + "]");
 		}
 	}
 
@@ -51,7 +51,7 @@ public class MinioCloudStorageStrategy extends AbstractCloudStorageStrategy {
 				.config(getPolicy(bucketName, PolicyType.READ))
 				.build());
 		} catch (Exception e) {
-			throw new OssException("创建Bucket失败, 请核对Minio配置信息");
+			throw new OssException("创建Bucket失败, 请核对Minio配置信息:[" + e.getMessage() + "]");
 		}
 	}
 
@@ -75,7 +75,7 @@ public class MinioCloudStorageStrategy extends AbstractCloudStorageStrategy {
 				.stream(inputStream, inputStream.available(), -1)
 				.build());
 		} catch (Exception e) {
-			throw new OssException("上传文件失败,请核对Minio配置信息");
+			throw new OssException("上传文件失败,请核对Minio配置信息:[" + e.getMessage() + "]");
 		}
 		return new UploadResult().setUrl(getEndpointLink() + "/" + path).setFilename(path);
 	}
@@ -95,7 +95,7 @@ public class MinioCloudStorageStrategy extends AbstractCloudStorageStrategy {
 
 	@Override
 	public UploadResult uploadSuffix(byte[] data, String suffix, String contentType) {
-		return upload(data, getPath("", suffix), contentType);
+		return upload(data, getPath(properties.getPrefix(), suffix), contentType);
 	}
 
 	@Override

+ 4 - 4
ruoyi-oss/src/main/java/com/ruoyi/oss/service/impl/QcloudCloudStorageStrategy.java

@@ -44,7 +44,7 @@ public class QcloudCloudStorageStrategy extends AbstractCloudStorageStrategy {
 			client = new COSClient(credentials, clientConfig);
 			createBucket();
 		} catch (Exception e) {
-			throw new OssException("腾讯云存储配置错误! 请检查系统配置!");
+			throw new OssException("腾讯云存储配置错误! 请检查系统配置:[" + e.getMessage() + "]");
 		}
 	}
 
@@ -59,7 +59,7 @@ public class QcloudCloudStorageStrategy extends AbstractCloudStorageStrategy {
 			createBucketRequest.setCannedAcl(CannedAccessControlList.PublicRead);
 			client.createBucket(createBucketRequest);
 		} catch (Exception e) {
-			throw new OssException("创建Bucket失败, 请核对腾讯云配置信息");
+			throw new OssException("创建Bucket失败, 请核对腾讯云配置信息:[" + e.getMessage() + "]");
 		}
 	}
 
@@ -80,7 +80,7 @@ public class QcloudCloudStorageStrategy extends AbstractCloudStorageStrategy {
 			metadata.setContentType(contentType);
 			client.putObject(new PutObjectRequest(properties.getBucketName(), path, inputStream, metadata));
 		} catch (Exception e) {
-			throw new OssException("上传文件失败,请检查腾讯云配置信息");
+			throw new OssException("上传文件失败,请检查腾讯云配置信息:[" + e.getMessage() + "]");
 		}
 		return new UploadResult().setUrl(getEndpointLink() + "/" + path).setFilename(path);
 	}
@@ -91,7 +91,7 @@ public class QcloudCloudStorageStrategy extends AbstractCloudStorageStrategy {
 		try {
 			client.deleteObject(new DeleteObjectRequest(properties.getBucketName(), path));
 		} catch (Exception e) {
-			throw new OssException("上传文件失败,请检腾讯云查配置信息");
+			throw new OssException("上传文件失败,请检腾讯云查配置信息:[" + e.getMessage() + "]");
 		}
 	}
 

+ 3 - 3
ruoyi-oss/src/main/java/com/ruoyi/oss/service/impl/QiniuCloudStorageStrategy.java

@@ -44,7 +44,7 @@ public class QiniuCloudStorageStrategy extends AbstractCloudStorageStrategy {
 				bucketManager.createBucket(bucketName, properties.getRegion());
 			}
 		} catch (Exception e) {
-			throw new OssException("七牛云存储配置错误! 请检查系统配置!");
+			throw new OssException("七牛云存储配置错误! 请检查系统配置:[" + e.getMessage() + "]");
 		}
 	}
 
@@ -57,7 +57,7 @@ public class QiniuCloudStorageStrategy extends AbstractCloudStorageStrategy {
 			}
 			bucketManager.createBucket(bucketName, properties.getRegion());
 		} catch (Exception e) {
-			throw new OssException("创建Bucket失败, 请核对七牛云配置信息");
+			throw new OssException("创建Bucket失败, 请核对七牛云配置信息:[" + e.getMessage() + "]");
 		}
 	}
 
@@ -74,7 +74,7 @@ public class QiniuCloudStorageStrategy extends AbstractCloudStorageStrategy {
 				throw new RuntimeException("上传七牛出错:" + res.toString());
 			}
 		} catch (Exception e) {
-			throw new OssException("上传文件失败,请核对七牛配置信息");
+			throw new OssException("上传文件失败,请核对七牛配置信息:[" + e.getMessage() + "]");
 		}
 		return new UploadResult().setUrl(getEndpointLink() + "/" + path).setFilename(path);
 	}

+ 1 - 1
ruoyi-quartz/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi-vue-plus</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>3.0.0</version>
+        <version>3.1.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 8 - 0
ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java

@@ -80,6 +80,10 @@ public class SysJobController extends BaseController
         {
             return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'rmi://'调用");
         }
+        else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_LDAP))
+        {
+            return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'ldap://'调用");
+        }
         else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS }))
         {
             return error("新增任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)//'调用");
@@ -104,6 +108,10 @@ public class SysJobController extends BaseController
         {
             return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'rmi://'调用");
         }
+        else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_LDAP))
+        {
+            return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'ldap://'调用");
+        }
         else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS }))
         {
             return error("修改任务'" + job.getJobName() + "'失败,目标字符串不允许'http(s)//'调用");

+ 8 - 8
ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobServiceImpl.java

@@ -87,7 +87,7 @@ public class SysJobServiceImpl extends ServicePlusImpl<SysJobMapper, SysJob, Sys
      * @param job 调度信息
      */
     @Override
-    @Transactional
+    @Transactional(rollbackFor = Exception.class)
     public int pauseJob(SysJob job) throws SchedulerException {
         Long jobId = job.getJobId();
         String jobGroup = job.getJobGroup();
@@ -105,7 +105,7 @@ public class SysJobServiceImpl extends ServicePlusImpl<SysJobMapper, SysJob, Sys
      * @param job 调度信息
      */
     @Override
-    @Transactional
+    @Transactional(rollbackFor = Exception.class)
     public int resumeJob(SysJob job) throws SchedulerException {
         Long jobId = job.getJobId();
         String jobGroup = job.getJobGroup();
@@ -123,7 +123,7 @@ public class SysJobServiceImpl extends ServicePlusImpl<SysJobMapper, SysJob, Sys
      * @param job 调度信息
      */
     @Override
-    @Transactional
+    @Transactional(rollbackFor = Exception.class)
     public int deleteJob(SysJob job) throws SchedulerException {
         Long jobId = job.getJobId();
         String jobGroup = job.getJobGroup();
@@ -141,7 +141,7 @@ public class SysJobServiceImpl extends ServicePlusImpl<SysJobMapper, SysJob, Sys
      * @return 结果
      */
     @Override
-    @Transactional
+    @Transactional(rollbackFor = Exception.class)
     public void deleteJobByIds(Long[] jobIds) throws SchedulerException {
         for (Long jobId : jobIds) {
             SysJob job = getById(jobId);
@@ -155,7 +155,7 @@ public class SysJobServiceImpl extends ServicePlusImpl<SysJobMapper, SysJob, Sys
      * @param job 调度信息
      */
     @Override
-    @Transactional
+    @Transactional(rollbackFor = Exception.class)
     public int changeStatus(SysJob job) throws SchedulerException {
         int rows = 0;
         String status = job.getStatus();
@@ -173,7 +173,7 @@ public class SysJobServiceImpl extends ServicePlusImpl<SysJobMapper, SysJob, Sys
      * @param job 调度信息
      */
     @Override
-    @Transactional
+    @Transactional(rollbackFor = Exception.class)
     public void run(SysJob job) throws SchedulerException {
         Long jobId = job.getJobId();
         String jobGroup = job.getJobGroup();
@@ -190,7 +190,7 @@ public class SysJobServiceImpl extends ServicePlusImpl<SysJobMapper, SysJob, Sys
      * @param job 调度信息 调度信息
      */
     @Override
-    @Transactional
+    @Transactional(rollbackFor = Exception.class)
     public int insertJob(SysJob job) throws SchedulerException, TaskException {
         job.setStatus(ScheduleConstants.Status.PAUSE.getValue());
         int rows = baseMapper.insert(job);
@@ -206,7 +206,7 @@ public class SysJobServiceImpl extends ServicePlusImpl<SysJobMapper, SysJob, Sys
      * @param job 调度信息
      */
     @Override
-    @Transactional
+    @Transactional(rollbackFor = Exception.class)
     public int updateJob(SysJob job) throws SchedulerException, TaskException {
         SysJob properties = selectJobById(job.getJobId());
         int rows = baseMapper.updateById(job);

+ 1 - 1
ruoyi-system/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <artifactId>ruoyi-vue-plus</artifactId>
         <groupId>com.ruoyi</groupId>
-        <version>3.0.0</version>
+        <version>3.1.0</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
 

+ 8 - 1
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java

@@ -58,7 +58,7 @@ public interface ISysDeptService extends IService<SysDept> {
      * @param deptId 部门ID
      * @return 子部门数
      */
-    public int selectNormalChildrenDeptById(Long deptId);
+    public long selectNormalChildrenDeptById(Long deptId);
 
     /**
      * 是否存在部门子节点
@@ -85,6 +85,13 @@ public interface ISysDeptService extends IService<SysDept> {
     public String checkDeptNameUnique(SysDept dept);
 
     /**
+     * 校验部门是否有数据权限
+     *
+     * @param deptId 部门id
+     */
+    public void checkDeptDataScope(Long deptId);
+
+    /**
      * 新增保存部门信息
      *
      * @param dept 部门信息

+ 1 - 1
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java

@@ -69,7 +69,7 @@ public interface ISysPostService extends IService<SysPost> {
      * @param postId 岗位ID
      * @return 结果
      */
-    public int countUserPostById(Long postId);
+    public long countUserPostById(Long postId);
 
     /**
      * 删除岗位信息

+ 8 - 1
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java

@@ -89,12 +89,19 @@ public interface ISysRoleService extends IService<SysRole> {
     public void checkRoleAllowed(SysRole role);
 
     /**
+     * 校验角色是否有数据权限
+     *
+     * @param roleId 角色id
+     */
+    public void checkRoleDataScope(Long roleId);
+
+    /**
      * 通过角色ID查询角色使用数量
      *
      * @param roleId 角色ID
      * @return 结果
      */
-    public int countUserRoleByRoleId(Long roleId);
+    public long countUserRoleByRoleId(Long roleId);
 
     /**
      * 新增保存角色信息

+ 7 - 0
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java

@@ -104,6 +104,13 @@ public interface ISysUserService extends IService<SysUser> {
     public void checkUserAllowed(SysUser user);
 
     /**
+     * 校验用户是否有数据权限
+     *
+     * @param userId 用户id
+     */
+    public void checkUserDataScope(Long userId);
+
+    /**
      * 新增用户信息
      *
      * @param user 用户信息

+ 10 - 14
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java

@@ -1,21 +1,20 @@
 package com.ruoyi.system.service.impl;
 
 import cn.hutool.core.convert.Convert;
-import com.ruoyi.common.utils.StringUtils;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.ruoyi.common.annotation.DataSource;
 import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.constant.UserConstants;
 import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
 import com.ruoyi.common.core.page.TableDataInfo;
-import com.ruoyi.common.core.redis.RedisCache;
 import com.ruoyi.common.enums.DataSourceType;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.PageUtils;
+import com.ruoyi.common.utils.RedisUtils;
+import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.system.domain.SysConfig;
 import com.ruoyi.system.mapper.SysConfigMapper;
 import com.ruoyi.system.service.ISysConfigService;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.PostConstruct;
@@ -32,9 +31,6 @@ import java.util.Map;
 @Service
 public class SysConfigServiceImpl extends ServicePlusImpl<SysConfigMapper, SysConfig, SysConfig> implements ISysConfigService {
 
-	@Autowired
-	private RedisCache redisCache;
-
 	/**
 	 * 项目启动时,初始化参数到缓存
 	 */
@@ -79,14 +75,14 @@ public class SysConfigServiceImpl extends ServicePlusImpl<SysConfigMapper, SysCo
 	 */
 	@Override
 	public String selectConfigByKey(String configKey) {
-		String configValue = Convert.toStr(redisCache.getCacheObject(getCacheKey(configKey)));
+		String configValue = Convert.toStr(RedisUtils.getCacheObject(getCacheKey(configKey)));
 		if (StringUtils.isNotEmpty(configValue)) {
 			return configValue;
 		}
 		SysConfig retConfig = baseMapper.selectOne(new LambdaQueryWrapper<SysConfig>()
 			.eq(SysConfig::getConfigKey, configKey));
 		if (StringUtils.isNotNull(retConfig)) {
-			redisCache.setCacheObject(getCacheKey(configKey), retConfig.getConfigValue());
+			RedisUtils.setCacheObject(getCacheKey(configKey), retConfig.getConfigValue());
 			return retConfig.getConfigValue();
 		}
 		return StringUtils.EMPTY;
@@ -138,7 +134,7 @@ public class SysConfigServiceImpl extends ServicePlusImpl<SysConfigMapper, SysCo
 	public int insertConfig(SysConfig config) {
 		int row = baseMapper.insert(config);
 		if (row > 0) {
-			redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
+			RedisUtils.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
 		}
 		return row;
 	}
@@ -153,7 +149,7 @@ public class SysConfigServiceImpl extends ServicePlusImpl<SysConfigMapper, SysCo
 	public int updateConfig(SysConfig config) {
 		int row = baseMapper.updateById(config);
 		if (row > 0) {
-			redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
+			RedisUtils.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
 		}
 		return row;
 	}
@@ -171,7 +167,7 @@ public class SysConfigServiceImpl extends ServicePlusImpl<SysConfigMapper, SysCo
 			if (StringUtils.equals(UserConstants.YES, config.getConfigType())) {
 				throw new ServiceException(String.format("内置参数【%1$s】不能删除 ", config.getConfigKey()));
 			}
-			redisCache.deleteObject(getCacheKey(config.getConfigKey()));
+			RedisUtils.deleteObject(getCacheKey(config.getConfigKey()));
 		}
 		baseMapper.deleteBatchIds(Arrays.asList(configIds));
 	}
@@ -183,7 +179,7 @@ public class SysConfigServiceImpl extends ServicePlusImpl<SysConfigMapper, SysCo
 	public void loadingConfigCache() {
 		List<SysConfig> configsList = selectConfigList(new SysConfig());
 		for (SysConfig config : configsList) {
-			redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
+			RedisUtils.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
 		}
 	}
 
@@ -192,8 +188,8 @@ public class SysConfigServiceImpl extends ServicePlusImpl<SysConfigMapper, SysCo
 	 */
 	@Override
 	public void clearConfigCache() {
-		Collection<String> keys = redisCache.keys(Constants.SYS_CONFIG_KEY + "*");
-		redisCache.deleteObject(keys);
+		Collection<String> keys = RedisUtils.keys(Constants.SYS_CONFIG_KEY + "*");
+		RedisUtils.deleteObject(keys);
 	}
 
 	/**

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio