mirror of
https://gitee.com/dromara/RuoYi-Vue-Plus.git
synced 2026-09-20 02:08:15 +08:00
Pre Merge pull request !108 from wenchaogong/develop
This commit is contained in:
commit
a08f703e45
75
pom.xml
75
pom.xml
@ -29,15 +29,19 @@
|
|||||||
<mybatis-plus.version>3.4.3.4</mybatis-plus.version>
|
<mybatis-plus.version>3.4.3.4</mybatis-plus.version>
|
||||||
<p6spy.version>3.9.1</p6spy.version>
|
<p6spy.version>3.9.1</p6spy.version>
|
||||||
<hutool.version>5.7.15</hutool.version>
|
<hutool.version>5.7.15</hutool.version>
|
||||||
|
<guava.version>29.0-jre</guava.version>
|
||||||
<feign.version>3.0.3</feign.version>
|
<feign.version>3.0.3</feign.version>
|
||||||
|
<gateway.version>3.0.3</gateway.version>
|
||||||
<feign-okhttp.version>11.6</feign-okhttp.version>
|
<feign-okhttp.version>11.6</feign-okhttp.version>
|
||||||
<okhttp.version>4.9.1</okhttp.version>
|
<okhttp.version>4.9.1</okhttp.version>
|
||||||
<spring-boot-admin.version>2.5.2</spring-boot-admin.version>
|
<spring-boot-admin.version>2.5.2</spring-boot-admin.version>
|
||||||
<redisson.version>3.16.3</redisson.version>
|
<redisson.version>3.16.3</redisson.version>
|
||||||
|
<okio.version>2.8.0</okio.version>
|
||||||
<lock4j.version>2.2.1</lock4j.version>
|
<lock4j.version>2.2.1</lock4j.version>
|
||||||
<dynamic-ds.version>3.4.1</dynamic-ds.version>
|
<dynamic-ds.version>3.4.1</dynamic-ds.version>
|
||||||
<tlog.version>1.3.3</tlog.version>
|
<tlog.version>1.3.3</tlog.version>
|
||||||
<xxl-job.version>2.3.0</xxl-job.version>
|
<xxl-job.version>2.3.0</xxl-job.version>
|
||||||
|
<wildfly-common.version>1.5.2.Final</wildfly-common.version>
|
||||||
|
|
||||||
<!-- jdk11 缺失依赖 jaxb-->
|
<!-- jdk11 缺失依赖 jaxb-->
|
||||||
<jaxb.version>3.0.1</jaxb.version>
|
<jaxb.version>3.0.1</jaxb.version>
|
||||||
@ -53,7 +57,6 @@
|
|||||||
<docker.registry.host>http://${docker.registry.url}:2375</docker.registry.host>
|
<docker.registry.host>http://${docker.registry.url}:2375</docker.registry.host>
|
||||||
<docker.namespace>ruoyi</docker.namespace>
|
<docker.namespace>ruoyi</docker.namespace>
|
||||||
<docker.plugin.version>1.2.2</docker.plugin.version>
|
<docker.plugin.version>1.2.2</docker.plugin.version>
|
||||||
|
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<!-- 依赖声明 -->
|
<!-- 依赖声明 -->
|
||||||
@ -88,6 +91,7 @@
|
|||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 指定 swagger-annotations 版本冲突-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.swagger</groupId>
|
<groupId>io.swagger</groupId>
|
||||||
<artifactId>swagger-annotations</artifactId>
|
<artifactId>swagger-annotations</artifactId>
|
||||||
@ -168,6 +172,18 @@
|
|||||||
<version>${hutool.version}</version>
|
<version>${hutool.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
<version>${guava.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-gateway</artifactId>
|
||||||
|
<version>${gateway.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- @deprecated 由于使用人数较少 决定与 3.4.0 版本移除 -->
|
<!-- @deprecated 由于使用人数较少 决定与 3.4.0 版本移除 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.cloud</groupId>
|
<groupId>org.springframework.cloud</groupId>
|
||||||
@ -178,6 +194,10 @@
|
|||||||
<artifactId>feign-core</artifactId>
|
<artifactId>feign-core</artifactId>
|
||||||
<groupId>io.github.openfeign</groupId>
|
<groupId>io.github.openfeign</groupId>
|
||||||
</exclusion>
|
</exclusion>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.bouncycastle</groupId>
|
||||||
|
<artifactId>bcprov-jdk15on</artifactId>
|
||||||
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- @deprecated 由于使用人数较少 决定与 3.4.0 版本移除 -->
|
<!-- @deprecated 由于使用人数较少 决定与 3.4.0 版本移除 -->
|
||||||
@ -186,6 +206,11 @@
|
|||||||
<artifactId>feign-okhttp</artifactId>
|
<artifactId>feign-okhttp</artifactId>
|
||||||
<version>${feign-okhttp.version}</version>
|
<version>${feign-okhttp.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.squareup.okio</groupId>
|
||||||
|
<artifactId>okio</artifactId>
|
||||||
|
<version>${okio.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.squareup.okhttp3</groupId>
|
<groupId>com.squareup.okhttp3</groupId>
|
||||||
@ -204,7 +229,24 @@
|
|||||||
<version>${spring-boot-admin.version}</version>
|
<version>${spring-boot-admin.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- redis 缓存操作 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>io.lettuce</groupId>
|
||||||
|
<artifactId>lettuce-core</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
<version>${spring-boot.version}</version>
|
||||||
|
</dependency>
|
||||||
<!--redisson-->
|
<!--redisson-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.redisson</groupId>
|
||||||
|
<artifactId>redisson</artifactId>
|
||||||
|
<version>${redisson.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.redisson</groupId>
|
<groupId>org.redisson</groupId>
|
||||||
<artifactId>redisson-spring-boot-starter</artifactId>
|
<artifactId>redisson-spring-boot-starter</artifactId>
|
||||||
@ -216,11 +258,24 @@
|
|||||||
<version>${lock4j.version}</version>
|
<version>${lock4j.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- undertow 中的wildfly-common包冲突处理 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wildfly.common</groupId>
|
||||||
|
<artifactId>wildfly-common</artifactId>
|
||||||
|
<version>${wildfly-common.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- xxl-job-core -->
|
<!-- xxl-job-core -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.xuxueli</groupId>
|
<groupId>com.xuxueli</groupId>
|
||||||
<artifactId>xxl-job-core</artifactId>
|
<artifactId>xxl-job-core</artifactId>
|
||||||
<version>${xxl-job.version}</version>
|
<version>${xxl-job.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.javassist</groupId>
|
||||||
|
<artifactId>javassist</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -306,6 +361,23 @@
|
|||||||
<version>${ruoyi-vue-plus.version}</version>
|
<version>${ruoyi-vue-plus.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- isc模块 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<artifactId>ruoyi-isc-parent</artifactId>
|
||||||
|
<version>${ruoyi-vue-plus.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<artifactId>ruoyi-isc-common</artifactId>
|
||||||
|
<version>${ruoyi-vue-plus.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<artifactId>ruoyi-isc</artifactId>
|
||||||
|
<version>${ruoyi-vue-plus.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- demo模块 -->
|
<!-- demo模块 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
@ -327,6 +399,7 @@
|
|||||||
<module>ruoyi-demo</module>
|
<module>ruoyi-demo</module>
|
||||||
<module>ruoyi-extend</module>
|
<module>ruoyi-extend</module>
|
||||||
<module>ruoyi-oss</module>
|
<module>ruoyi-oss</module>
|
||||||
|
<module>ruoyi-isc-parent</module>
|
||||||
</modules>
|
</modules>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
|
|||||||
@ -52,10 +52,11 @@
|
|||||||
<artifactId>ruoyi-job</artifactId>
|
<artifactId>ruoyi-job</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!--
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-oss</artifactId>
|
<artifactId>ruoyi-oss</artifactId>
|
||||||
</dependency>
|
</dependency>-->
|
||||||
|
|
||||||
<!-- 代码生成-->
|
<!-- 代码生成-->
|
||||||
<dependency>
|
<dependency>
|
||||||
@ -63,6 +64,12 @@
|
|||||||
<artifactId>ruoyi-generator</artifactId>
|
<artifactId>ruoyi-generator</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- isc模块 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<artifactId>ruoyi-isc</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- demo模块 -->
|
<!-- demo模块 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
package com.ruoyi.web.controller.system;
|
package com.ruoyi.web.controller.system;
|
||||||
|
|
||||||
|
import cn.hutool.core.lang.tree.Tree;
|
||||||
import cn.hutool.core.util.ArrayUtil;
|
import cn.hutool.core.util.ArrayUtil;
|
||||||
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
import com.ruoyi.common.constant.UserConstants;
|
import com.ruoyi.common.constant.UserConstants;
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.core.domain.TreeSelect;
|
|
||||||
import com.ruoyi.common.core.domain.entity.SysDept;
|
import com.ruoyi.common.core.domain.entity.SysDept;
|
||||||
import com.ruoyi.common.enums.BusinessType;
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
@ -76,7 +76,7 @@ public class SysDeptController extends BaseController {
|
|||||||
*/
|
*/
|
||||||
@ApiOperation("获取部门下拉树列表")
|
@ApiOperation("获取部门下拉树列表")
|
||||||
@GetMapping("/treeselect")
|
@GetMapping("/treeselect")
|
||||||
public AjaxResult<List<TreeSelect>> treeselect(SysDept dept) {
|
public AjaxResult<List<Tree<Long>>> treeselect(SysDept dept) {
|
||||||
List<SysDept> depts = deptService.selectDeptList(dept);
|
List<SysDept> depts = deptService.selectDeptList(dept);
|
||||||
return AjaxResult.success(deptService.buildDeptTreeSelect(depts));
|
return AjaxResult.success(deptService.buildDeptTreeSelect(depts));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
package com.ruoyi.web.controller.system;
|
package com.ruoyi.web.controller.system;
|
||||||
|
|
||||||
|
import cn.hutool.core.lang.tree.Tree;
|
||||||
import com.ruoyi.common.annotation.Log;
|
import com.ruoyi.common.annotation.Log;
|
||||||
import com.ruoyi.common.constant.UserConstants;
|
import com.ruoyi.common.constant.UserConstants;
|
||||||
import com.ruoyi.common.core.controller.BaseController;
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
import com.ruoyi.common.core.domain.AjaxResult;
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
import com.ruoyi.common.core.domain.TreeSelect;
|
|
||||||
import com.ruoyi.common.core.domain.entity.SysMenu;
|
import com.ruoyi.common.core.domain.entity.SysMenu;
|
||||||
import com.ruoyi.common.enums.BusinessType;
|
import com.ruoyi.common.enums.BusinessType;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
@ -61,7 +61,7 @@ public class SysMenuController extends BaseController {
|
|||||||
*/
|
*/
|
||||||
@ApiOperation("获取菜单下拉树列表")
|
@ApiOperation("获取菜单下拉树列表")
|
||||||
@GetMapping("/treeselect")
|
@GetMapping("/treeselect")
|
||||||
public AjaxResult<List<TreeSelect>> treeselect(SysMenu menu) {
|
public AjaxResult<List<Tree<Long>>> treeselect(SysMenu menu) {
|
||||||
List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
|
List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
|
||||||
return AjaxResult.success(menuService.buildMenuTreeSelect(menus));
|
return AjaxResult.success(menuService.buildMenuTreeSelect(menus));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,8 +10,8 @@ spring:
|
|||||||
url: http://localhost:9090/admin
|
url: http://localhost:9090/admin
|
||||||
instance:
|
instance:
|
||||||
prefer-ip: true # 注册实例时,优先使用 IP
|
prefer-ip: true # 注册实例时,优先使用 IP
|
||||||
username: ruoyi
|
username: admin
|
||||||
password: 123456
|
password: admin123
|
||||||
|
|
||||||
--- # xxl-job 配置
|
--- # xxl-job 配置
|
||||||
xxl:
|
xxl:
|
||||||
@ -51,7 +51,7 @@ spring:
|
|||||||
# 主库数据源
|
# 主库数据源
|
||||||
master:
|
master:
|
||||||
driverClassName: com.mysql.cj.jdbc.Driver
|
driverClassName: com.mysql.cj.jdbc.Driver
|
||||||
url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true
|
url: jdbc:mysql://192.168.64.128:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true
|
||||||
username: root
|
username: root
|
||||||
password: root
|
password: root
|
||||||
# 从库数据源
|
# 从库数据源
|
||||||
@ -113,7 +113,7 @@ spring:
|
|||||||
spring:
|
spring:
|
||||||
redis:
|
redis:
|
||||||
# 地址
|
# 地址
|
||||||
host: localhost
|
host: 192.168.64.128
|
||||||
# 端口,默认为6379
|
# 端口,默认为6379
|
||||||
port: 6379
|
port: 6379
|
||||||
# 数据库索引
|
# 数据库索引
|
||||||
|
|||||||
158
ruoyi-admin/src/main/resources/application-local.yml
Normal file
158
ruoyi-admin/src/main/resources/application-local.yml
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
--- # 监控配置
|
||||||
|
spring:
|
||||||
|
boot:
|
||||||
|
admin:
|
||||||
|
# Spring Boot Admin Client 客户端的相关配置
|
||||||
|
client:
|
||||||
|
# 增加客户端开关
|
||||||
|
enabled: true
|
||||||
|
# 设置 Spring Boot Admin Server 地址
|
||||||
|
url: http://localhost:9090/admin
|
||||||
|
instance:
|
||||||
|
prefer-ip: true # 注册实例时,优先使用 IP
|
||||||
|
username: admin
|
||||||
|
password: admin123
|
||||||
|
|
||||||
|
--- # xxl-job 配置
|
||||||
|
xxl:
|
||||||
|
job:
|
||||||
|
# 执行器开关
|
||||||
|
enabled: true
|
||||||
|
# 调度中心地址:如调度中心集群部署存在多个地址则用逗号分隔。
|
||||||
|
admin-addresses: http://localhost:9100/xxl-job-admin
|
||||||
|
# 执行器通讯TOKEN:非空时启用
|
||||||
|
access-token: xxl-job
|
||||||
|
# 执行器配置
|
||||||
|
executor:
|
||||||
|
# 执行器AppName:执行器心跳注册分组依据;为空则关闭自动注册
|
||||||
|
appname: xxl-job-executor
|
||||||
|
# 执行器端口号 执行器从9101开始往后写
|
||||||
|
port: 9101
|
||||||
|
# 执行器注册:默认IP:PORT
|
||||||
|
address:
|
||||||
|
# 执行器IP:默认自动获取IP
|
||||||
|
ip:
|
||||||
|
# 执行器运行日志文件存储磁盘路径
|
||||||
|
logpath: ./logs/xxl-job
|
||||||
|
# 执行器日志文件保存天数:大于3生效
|
||||||
|
logretentiondays: 30
|
||||||
|
|
||||||
|
# 数据源配置
|
||||||
|
spring:
|
||||||
|
datasource:
|
||||||
|
type: com.alibaba.druid.pool.DruidDataSource
|
||||||
|
# 动态数据源文档 https://www.kancloud.cn/tracy5546/dynamic-datasource/content
|
||||||
|
dynamic:
|
||||||
|
# 性能分析插件(有性能损耗 不建议生产环境使用)
|
||||||
|
p6spy: true
|
||||||
|
# 设置默认的数据源或者数据源组,默认值即为 master
|
||||||
|
primary: master
|
||||||
|
datasource:
|
||||||
|
# 主库数据源
|
||||||
|
master:
|
||||||
|
driverClassName: com.mysql.cj.jdbc.Driver
|
||||||
|
url: jdbc:mysql://127.0.0.1:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true
|
||||||
|
username: root
|
||||||
|
password: root
|
||||||
|
# 从库数据源
|
||||||
|
slave:
|
||||||
|
lazy: true
|
||||||
|
driverClassName: com.mysql.cj.jdbc.Driver
|
||||||
|
url:
|
||||||
|
username:
|
||||||
|
password:
|
||||||
|
druid:
|
||||||
|
# 初始连接数
|
||||||
|
initialSize: 5
|
||||||
|
# 最小连接池数量
|
||||||
|
minIdle: 10
|
||||||
|
# 最大连接池数量
|
||||||
|
maxActive: 20
|
||||||
|
# 配置获取连接等待超时的时间
|
||||||
|
maxWait: 60000
|
||||||
|
# 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
|
||||||
|
timeBetweenEvictionRunsMillis: 60000
|
||||||
|
# 配置一个连接在池中最小生存的时间,单位是毫秒
|
||||||
|
minEvictableIdleTimeMillis: 300000
|
||||||
|
# 配置一个连接在池中最大生存的时间,单位是毫秒
|
||||||
|
maxEvictableIdleTimeMillis: 900000
|
||||||
|
# 配置检测连接是否有效
|
||||||
|
validationQuery: SELECT 1 FROM DUAL
|
||||||
|
testWhileIdle: true
|
||||||
|
testOnBorrow: false
|
||||||
|
testOnReturn: false
|
||||||
|
# 注意这个值和druid原生不一致,默认启动了stat
|
||||||
|
filters: stat
|
||||||
|
|
||||||
|
--- # druid 配置
|
||||||
|
spring:
|
||||||
|
datasource:
|
||||||
|
druid:
|
||||||
|
webStatFilter:
|
||||||
|
enabled: true
|
||||||
|
statViewServlet:
|
||||||
|
enabled: true
|
||||||
|
# 设置白名单,不填则允许所有访问
|
||||||
|
allow:
|
||||||
|
url-pattern: /druid/*
|
||||||
|
# 控制台管理用户名和密码
|
||||||
|
login-username: ruoyi
|
||||||
|
login-password: 123456
|
||||||
|
filter:
|
||||||
|
stat:
|
||||||
|
enabled: true
|
||||||
|
# 慢SQL记录
|
||||||
|
log-slow-sql: true
|
||||||
|
slow-sql-millis: 1000
|
||||||
|
merge-sql: true
|
||||||
|
wall:
|
||||||
|
config:
|
||||||
|
multi-statement-allow: true
|
||||||
|
|
||||||
|
--- # redis 配置
|
||||||
|
spring:
|
||||||
|
redis:
|
||||||
|
# 地址
|
||||||
|
host: 127.0.0.1
|
||||||
|
# 端口,默认为6379
|
||||||
|
port: 6379
|
||||||
|
# 数据库索引
|
||||||
|
database: 11
|
||||||
|
# 密码
|
||||||
|
password:
|
||||||
|
# 连接超时时间
|
||||||
|
timeout: 10s
|
||||||
|
# 是否开启ssl
|
||||||
|
ssl: false
|
||||||
|
|
||||||
|
redisson:
|
||||||
|
# 线程池数量
|
||||||
|
threads: 16
|
||||||
|
# Netty线程池数量
|
||||||
|
nettyThreads: 32
|
||||||
|
# 传输模式
|
||||||
|
transportMode: "NIO"
|
||||||
|
# 单节点配置
|
||||||
|
singleServerConfig:
|
||||||
|
# 客户端名称
|
||||||
|
clientName: ${ruoyi.name}
|
||||||
|
# 最小空闲连接数
|
||||||
|
connectionMinimumIdleSize: 32
|
||||||
|
# 连接池大小
|
||||||
|
connectionPoolSize: 64
|
||||||
|
# 连接空闲超时,单位:毫秒
|
||||||
|
idleConnectionTimeout: 10000
|
||||||
|
# 命令等待超时,单位:毫秒
|
||||||
|
timeout: 3000
|
||||||
|
# 如果尝试在此限制之内发送成功,则开始启用 timeout 计时。
|
||||||
|
retryAttempts: 3
|
||||||
|
# 命令重试发送时间间隔,单位:毫秒
|
||||||
|
retryInterval: 1500
|
||||||
|
# 发布和订阅连接的最小空闲连接数
|
||||||
|
subscriptionConnectionMinimumIdleSize: 1
|
||||||
|
# 发布和订阅连接池大小
|
||||||
|
subscriptionConnectionPoolSize: 50
|
||||||
|
# 单个连接最大订阅数量
|
||||||
|
subscriptionsPerConnection: 5
|
||||||
|
# DNS监测时间间隔,单位:毫秒
|
||||||
|
dnsMonitoringInterval: 5000
|
||||||
@ -51,7 +51,7 @@ spring:
|
|||||||
# 主库数据源
|
# 主库数据源
|
||||||
master:
|
master:
|
||||||
driverClassName: com.mysql.cj.jdbc.Driver
|
driverClassName: com.mysql.cj.jdbc.Driver
|
||||||
url: jdbc:mysql://172.30.0.36:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true
|
url: jdbc:mysql://172.17.0.1:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&autoReconnect=true
|
||||||
username: root
|
username: root
|
||||||
password: root
|
password: root
|
||||||
# 从库数据源
|
# 从库数据源
|
||||||
@ -113,7 +113,7 @@ spring:
|
|||||||
spring:
|
spring:
|
||||||
redis:
|
redis:
|
||||||
# 地址
|
# 地址
|
||||||
host: 172.30.0.48
|
host: 172.17.0.1
|
||||||
# 端口,默认为6379
|
# 端口,默认为6379
|
||||||
port: 6379
|
port: 6379
|
||||||
# 数据库索引
|
# 数据库索引
|
||||||
|
|||||||
@ -2,8 +2,8 @@
|
|||||||
<configuration>
|
<configuration>
|
||||||
<property name="log.path" value="./logs"/>
|
<property name="log.path" value="./logs"/>
|
||||||
<property name="console.log.pattern"
|
<property name="console.log.pattern"
|
||||||
value="%red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}%n) - %msg%n"/>
|
value="%red(%d{yyyy-MM-dd HH:mm:ss}) %highlight(%-5level) %green([%thread]) %boldMagenta(%logger{36}) - %msg%n"/>
|
||||||
<property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n"/>
|
<property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger{36} - %msg%n"/>
|
||||||
|
|
||||||
<!-- 控制台输出 -->
|
<!-- 控制台输出 -->
|
||||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
@ -31,7 +31,7 @@
|
|||||||
<level>INFO</level>
|
<level>INFO</level>
|
||||||
</filter>
|
</filter>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<!-- 系统日志输出 -->
|
<!-- 系统日志输出 -->
|
||||||
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
<file>${log.path}/sys-info.log</file>
|
<file>${log.path}/sys-info.log</file>
|
||||||
@ -54,7 +54,7 @@
|
|||||||
<onMismatch>DENY</onMismatch>
|
<onMismatch>DENY</onMismatch>
|
||||||
</filter>
|
</filter>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
<file>${log.path}/sys-error.log</file>
|
<file>${log.path}/sys-error.log</file>
|
||||||
<!-- 循环政策:基于时间创建日志文件 -->
|
<!-- 循环政策:基于时间创建日志文件 -->
|
||||||
@ -76,7 +76,7 @@
|
|||||||
<onMismatch>DENY</onMismatch>
|
<onMismatch>DENY</onMismatch>
|
||||||
</filter>
|
</filter>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<!-- 用户访问日志输出 -->
|
<!-- 用户访问日志输出 -->
|
||||||
<appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
<appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
<file>${log.path}/sys-user.log</file>
|
<file>${log.path}/sys-user.log</file>
|
||||||
@ -90,7 +90,7 @@
|
|||||||
<pattern>${log.pattern}</pattern>
|
<pattern>${log.pattern}</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
<!-- 系统模块日志级别控制 -->
|
<!-- 系统模块日志级别控制 -->
|
||||||
<logger name="com.ruoyi" level="info" />
|
<logger name="com.ruoyi" level="info" />
|
||||||
<!-- Spring日志级别控制 -->
|
<!-- Spring日志级别控制 -->
|
||||||
@ -99,16 +99,16 @@
|
|||||||
<root level="info">
|
<root level="info">
|
||||||
<appender-ref ref="console" />
|
<appender-ref ref="console" />
|
||||||
</root>
|
</root>
|
||||||
|
|
||||||
<!--系统操作日志-->
|
<!--系统操作日志-->
|
||||||
<root level="info">
|
<root level="info">
|
||||||
<appender-ref ref="file_info" />
|
<appender-ref ref="file_info" />
|
||||||
<appender-ref ref="file_error" />
|
<appender-ref ref="file_error" />
|
||||||
<appender-ref ref="file_console" />
|
<appender-ref ref="file_console" />
|
||||||
</root>
|
</root>
|
||||||
|
|
||||||
<!--系统用户操作日志-->
|
<!--系统用户操作日志-->
|
||||||
<logger name="sys-user" level="info">
|
<logger name="sys-user" level="info">
|
||||||
<appender-ref ref="sys-user"/>
|
<appender-ref ref="sys-user"/>
|
||||||
</logger>
|
</logger>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|||||||
@ -1,26 +1,26 @@
|
|||||||
# p6spy 性能分析插件配置文件
|
# p6spy \u6027\u80FD\u5206\u6790\u63D2\u4EF6\u914D\u7F6E\u6587\u4EF6
|
||||||
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
|
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
|
||||||
# 自定义日志打印
|
# \u81EA\u5B9A\u4E49\u65E5\u5FD7\u6253\u5370
|
||||||
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
|
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
|
||||||
#日志输出到控制台
|
#\u65E5\u5FD7\u8F93\u51FA\u5230\u63A7\u5236\u53F0
|
||||||
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
|
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
|
||||||
# 使用日志系统记录 sql
|
# \u4F7F\u7528\u65E5\u5FD7\u7CFB\u7EDF\u8BB0\u5F55 sql
|
||||||
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
|
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
|
||||||
# 设置 p6spy driver 代理
|
# \u8BBE\u7F6E p6spy driver \u4EE3\u7406
|
||||||
#deregisterdrivers=true
|
#deregisterdrivers=true
|
||||||
# 取消JDBC URL前缀
|
# \u53D6\u6D88JDBC URL\u524D\u7F00
|
||||||
useprefix=true
|
useprefix=true
|
||||||
# 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
|
# \u914D\u7F6E\u8BB0\u5F55 Log \u4F8B\u5916,\u53EF\u53BB\u6389\u7684\u7ED3\u679C\u96C6\u6709error,info,batch,debug,statement,commit,rollback,result,resultset.
|
||||||
excludecategories=info,debug,result,commit,resultset
|
excludecategories=info,debug,result,commit,resultset
|
||||||
# 日期格式
|
# \u65E5\u671F\u683C\u5F0F
|
||||||
dateformat=yyyy-MM-dd HH:mm:ss
|
dateformat=yyyy-MM-dd HH:mm:ss
|
||||||
# 实际驱动可多个
|
# \u5B9E\u9645\u9A71\u52A8\u53EF\u591A\u4E2A
|
||||||
#driverlist=org.h2.Driver
|
#driverlist=org.h2.Driver
|
||||||
# 是否开启慢SQL记录
|
# \u662F\u5426\u5F00\u542F\u6162SQL\u8BB0\u5F55
|
||||||
outagedetection=true
|
outagedetection=true
|
||||||
# 慢SQL记录标准 2 秒
|
# \u6162SQL\u8BB0\u5F55\u6807\u51C6 2 \u79D2
|
||||||
outagedetectioninterval=2
|
outagedetectioninterval=2
|
||||||
# 是否过滤 Log
|
# \u662F\u5426\u8FC7\u6EE4 Log
|
||||||
filter=true
|
filter=true
|
||||||
# 过滤 Log 时所排除的表名列表,以逗号分隔
|
# \u8FC7\u6EE4 Log \u65F6\u6240\u6392\u9664\u7684\u8868\u540D\u5217\u8868\uFF0C\u4EE5\u9017\u53F7\u5206\u9694
|
||||||
exclude=QRTZ_
|
exclude=QRTZ_
|
||||||
|
|||||||
@ -46,6 +46,10 @@
|
|||||||
<groupId>org.apache.commons</groupId>
|
<groupId>org.apache.commons</groupId>
|
||||||
<artifactId>commons-lang3</artifactId>
|
<artifactId>commons-lang3</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- JSON工具类 -->
|
<!-- JSON工具类 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
@ -142,4 +142,14 @@ public class Constants {
|
|||||||
* LDAP 远程方法调用
|
* LDAP 远程方法调用
|
||||||
*/
|
*/
|
||||||
public static final String LOOKUP_LDAP = "ldap://";
|
public static final String LOOKUP_LDAP = "ldap://";
|
||||||
|
|
||||||
|
/** 待审核 */
|
||||||
|
public static final String AUDIT_WAIT = "0";
|
||||||
|
|
||||||
|
/** 审核通过 */
|
||||||
|
public static final String AUDIT_PASS = "1";
|
||||||
|
|
||||||
|
/** 审核驳回 */
|
||||||
|
public static final String AUDIT_REJECT = "2";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,16 @@
|
|||||||
|
package com.ruoyi.common.constant;
|
||||||
|
|
||||||
|
public class IscConstants {
|
||||||
|
|
||||||
|
/** 在线状态 在线 */
|
||||||
|
public static final String ONLINE_STATUS_ON = "1";
|
||||||
|
|
||||||
|
/** 申请类型 申请服务 */
|
||||||
|
public static final String APPLY_TYPE_APPLY = "0";
|
||||||
|
|
||||||
|
/** 申请类型 服务续期 */
|
||||||
|
public static final String APPLY_TYPE_RENEWAL = "1";
|
||||||
|
|
||||||
|
/** 申请类型 申请修改 */
|
||||||
|
public static final String APPLY_TYPE_MODIFY = "2";
|
||||||
|
}
|
||||||
@ -1,67 +0,0 @@
|
|||||||
package com.ruoyi.common.core.domain;
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
|
||||||
import com.ruoyi.common.core.domain.entity.SysDept;
|
|
||||||
import com.ruoyi.common.core.domain.entity.SysMenu;
|
|
||||||
import io.swagger.annotations.ApiModel;
|
|
||||||
import io.swagger.annotations.ApiModelProperty;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import lombok.experimental.Accessors;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Treeselect树结构实体类
|
|
||||||
*
|
|
||||||
* @author Lion Li
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Data
|
|
||||||
@NoArgsConstructor
|
|
||||||
@Accessors(chain = true)
|
|
||||||
@ApiModel("树结构实体类")
|
|
||||||
public class TreeSelect implements Serializable {
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 节点ID
|
|
||||||
*/
|
|
||||||
@ApiModelProperty(value = "节点ID")
|
|
||||||
private Long id;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 节点名称
|
|
||||||
*/
|
|
||||||
@ApiModelProperty(value = "节点名称")
|
|
||||||
private String label;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 子节点
|
|
||||||
*/
|
|
||||||
@ApiModelProperty(value = "子节点")
|
|
||||||
@JsonInclude(JsonInclude.Include.NON_EMPTY)
|
|
||||||
private List<TreeSelect> children;
|
|
||||||
|
|
||||||
public TreeSelect(SysDept dept) {
|
|
||||||
this.id = dept.getDeptId();
|
|
||||||
this.label = dept.getDeptName();
|
|
||||||
this.children = dept.getChildren()
|
|
||||||
.stream()
|
|
||||||
.map(d -> new TreeSelect((SysDept) d))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
public TreeSelect(SysMenu menu) {
|
|
||||||
this.id = menu.getMenuId();
|
|
||||||
this.label = menu.getMenuName();
|
|
||||||
this.children = menu.getChildren()
|
|
||||||
.stream()
|
|
||||||
.map(d -> new TreeSelect((SysMenu) d))
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -55,4 +55,9 @@ public enum BusinessType {
|
|||||||
* 清空数据
|
* 清空数据
|
||||||
*/
|
*/
|
||||||
CLEAN,
|
CLEAN,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审核
|
||||||
|
*/
|
||||||
|
AUDIT
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,12 @@
|
|||||||
package com.ruoyi.common.utils;
|
package com.ruoyi.common.utils;
|
||||||
|
|
||||||
|
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||||
import org.apache.commons.lang3.time.DateFormatUtils;
|
import org.apache.commons.lang3.time.DateFormatUtils;
|
||||||
|
|
||||||
import java.lang.management.ManagementFactory;
|
import java.lang.management.ManagementFactory;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.time.ZoneId;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -133,4 +135,30 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
|
|||||||
// long sec = diff % nd % nh % nm / ns;
|
// long sec = diff % nd % nh % nm / ns;
|
||||||
return day + "天" + hour + "小时" + min + "分钟";
|
return day + "天" + hour + "小时" + min + "分钟";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取一天的开始时间 即00:00:00
|
||||||
|
*
|
||||||
|
* @param date 日期
|
||||||
|
* @return 一天的开始时间
|
||||||
|
*/
|
||||||
|
public static Date beginOfDay(Date date)
|
||||||
|
{
|
||||||
|
return Date.from(LocalDateTimeUtil.beginOfDay(LocalDateTimeUtil.of(date))
|
||||||
|
.atZone(ZoneId.systemDefault()).toInstant());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取一天的结束时间 即23:59:59
|
||||||
|
*
|
||||||
|
* @param date 日期
|
||||||
|
* @return 一天的最后一秒
|
||||||
|
*/
|
||||||
|
public static Date endOfDay(Date date)
|
||||||
|
{
|
||||||
|
return Date.from(LocalDateTimeUtil.endOfDay(LocalDateTimeUtil.of(date))
|
||||||
|
.atZone(ZoneId.systemDefault()).toInstant());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,87 @@
|
|||||||
|
package com.ruoyi.common.utils;
|
||||||
|
|
||||||
|
public final class FullPathUtils {
|
||||||
|
|
||||||
|
public static final int FULL_PATH_LENGTH = 30;
|
||||||
|
public static final int FULL_PATH_LEVEL_LENGTH = 3;
|
||||||
|
public static final char REPEAT_CHAR = '0';
|
||||||
|
public static final char REPEAT_CHAR_MAX = '9';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成 FULL_PATH
|
||||||
|
*
|
||||||
|
* @param parentFullPath 父级full_path (可空)
|
||||||
|
* @param maxFullPath 同级最大 full_path(可空)
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String genFullPath(String parentFullPath, String maxFullPath)
|
||||||
|
{
|
||||||
|
int maxNum = 0;
|
||||||
|
String parentPath = StringUtils.EMPTY;
|
||||||
|
if (StringUtils.isNotBlank(maxFullPath))
|
||||||
|
{
|
||||||
|
int start = maxFullPath.length() - FULL_PATH_LEVEL_LENGTH;
|
||||||
|
int end = maxFullPath.length() - 1;
|
||||||
|
int temp = 0;
|
||||||
|
while (start > -1)
|
||||||
|
{
|
||||||
|
temp = Integer.parseInt(maxFullPath.substring(start, end));
|
||||||
|
if (temp > 0)
|
||||||
|
{
|
||||||
|
parentPath = maxFullPath.substring(0, start);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
end = start;
|
||||||
|
start -= FULL_PATH_LEVEL_LENGTH;
|
||||||
|
}
|
||||||
|
maxNum = temp;
|
||||||
|
} else if (StringUtils.isNotBlank(parentFullPath))
|
||||||
|
{
|
||||||
|
parentPath = getParentPath(parentFullPath);
|
||||||
|
}
|
||||||
|
int repeat = FULL_PATH_LENGTH - parentPath.length() - FULL_PATH_LEVEL_LENGTH;
|
||||||
|
String suffix = StringUtils.repeat(REPEAT_CHAR, repeat);
|
||||||
|
return String.format("%s%03d%s", parentPath, ++maxNum, suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据FULL_PATH 获取最大 子FULL_PATH
|
||||||
|
*
|
||||||
|
* @param fullPath
|
||||||
|
*/
|
||||||
|
public static String genMaxFullPath(String fullPath)
|
||||||
|
{
|
||||||
|
String parentPath = StringUtils.EMPTY;
|
||||||
|
if (StringUtils.isNotBlank(fullPath))
|
||||||
|
{
|
||||||
|
parentPath = getParentPath(fullPath);
|
||||||
|
}
|
||||||
|
int repeat = FULL_PATH_LENGTH - parentPath.length();
|
||||||
|
String suffix = StringUtils.repeat(REPEAT_CHAR_MAX, repeat);
|
||||||
|
return parentPath + suffix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取父 Path
|
||||||
|
*
|
||||||
|
* @param fullPath
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static String getParentPath(String fullPath)
|
||||||
|
{
|
||||||
|
int temp;
|
||||||
|
int start = fullPath.length() - FULL_PATH_LEVEL_LENGTH;
|
||||||
|
int end = fullPath.length() - 1;
|
||||||
|
while (start > -1)
|
||||||
|
{
|
||||||
|
temp = Integer.parseInt(fullPath.substring(start, end));
|
||||||
|
if (temp > 0)
|
||||||
|
{
|
||||||
|
return fullPath.substring(0, end);
|
||||||
|
}
|
||||||
|
end = start;
|
||||||
|
start -= FULL_PATH_LEVEL_LENGTH;
|
||||||
|
}
|
||||||
|
return StringUtils.EMPTY;
|
||||||
|
}
|
||||||
|
}
|
||||||
132
ruoyi-common/src/main/java/com/ruoyi/common/utils/TreeUtils.java
Normal file
132
ruoyi-common/src/main/java/com/ruoyi/common/utils/TreeUtils.java
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
package com.ruoyi.common.utils;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
|
import cn.hutool.core.lang.tree.Tree;
|
||||||
|
import cn.hutool.core.lang.tree.TreeNodeConfig;
|
||||||
|
import cn.hutool.core.lang.tree.TreeUtil;
|
||||||
|
import cn.hutool.core.lang.tree.parser.NodeParser;
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 树结构工具类
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-09-08
|
||||||
|
*/
|
||||||
|
public class TreeUtils
|
||||||
|
{
|
||||||
|
|
||||||
|
public static final TreeNodeConfig DEFAULT_TREE_NODE_CONFIG = new TreeNodeConfig();
|
||||||
|
public static final long DEFAULT_PARENT_ID = 0L;
|
||||||
|
public static final String FIELD_NODE_EXIST = "exist";
|
||||||
|
|
||||||
|
static {
|
||||||
|
DEFAULT_TREE_NODE_CONFIG.setNameKey("label");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置默认 parentId
|
||||||
|
*
|
||||||
|
* @param list
|
||||||
|
* @param nodeParser
|
||||||
|
* @param <T>
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static <T> List<Tree<Long>> build(List<T> list, NodeParser<T, Long> nodeParser)
|
||||||
|
{
|
||||||
|
return TreeUtil.build(list, DEFAULT_PARENT_ID, DEFAULT_TREE_NODE_CONFIG, nodeParser);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 树构建
|
||||||
|
*
|
||||||
|
* @param <T> 转换的实体 为数据源里的对象类型
|
||||||
|
* @param <E> ID类型
|
||||||
|
* @param list 源数据集合
|
||||||
|
* @param parentId 最顶层父id值 一般为 0 之类
|
||||||
|
* @param nodeParser 转换器
|
||||||
|
* @param needExistField 是否需要 已存在字段
|
||||||
|
* @return List
|
||||||
|
*/
|
||||||
|
public static <T, E> List<Tree<E>> build(List<T> list, E parentId, NodeParser<T, E> nodeParser,
|
||||||
|
boolean needExistField)
|
||||||
|
{
|
||||||
|
final List<Tree<E>> treeList = CollUtil.newArrayList();
|
||||||
|
final TreeNodeConfig treeNodeConfig = DEFAULT_TREE_NODE_CONFIG;
|
||||||
|
Tree<E> tree;
|
||||||
|
for (T obj : list) {
|
||||||
|
tree = new Tree<>(treeNodeConfig);
|
||||||
|
nodeParser.parse(obj, tree);
|
||||||
|
treeList.add(tree);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Tree<E>> finalTreeList = CollUtil.newArrayList();
|
||||||
|
for (Tree<E> node : treeList) {
|
||||||
|
if (ObjectUtil.equals(parentId, node.getParentId())) {
|
||||||
|
finalTreeList.add(node);
|
||||||
|
innerBuild(treeList, node, 0, treeNodeConfig.getDeep(), needExistField);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 内存每层已经排过了 这是最外层排序
|
||||||
|
finalTreeList = finalTreeList.stream().sorted().collect(Collectors.toList());
|
||||||
|
return finalTreeList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 递归处理
|
||||||
|
*
|
||||||
|
* @param treeNodes 数据集合
|
||||||
|
* @param parentNode 当前节点
|
||||||
|
* @param deep 已递归深度
|
||||||
|
* @param maxDeep 最大递归深度 可能为null即不限制
|
||||||
|
* @param needExistField 是否需要 已存在字段
|
||||||
|
*/
|
||||||
|
private static <T> void innerBuild(List<Tree<T>> treeNodes, Tree<T> parentNode, int deep, Integer maxDeep,
|
||||||
|
boolean needExistField)
|
||||||
|
{
|
||||||
|
if (CollUtil.isEmpty(treeNodes)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//maxDeep 可能为空
|
||||||
|
if (maxDeep != null && deep >= maxDeep) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 每层排序 TreeNodeMap 实现了Comparable接口
|
||||||
|
treeNodes = treeNodes.stream().sorted().collect(Collectors.toList());
|
||||||
|
for (Tree<T> childNode : treeNodes) {
|
||||||
|
if (parentNode.getId().equals(childNode.getParentId())) {
|
||||||
|
List<Tree<T>> children = parentNode.getChildren();
|
||||||
|
if (children == null) {
|
||||||
|
children = CollUtil.newArrayList();
|
||||||
|
parentNode.setChildren(children);
|
||||||
|
}
|
||||||
|
children.add(childNode);
|
||||||
|
childNode.setParent(parentNode);
|
||||||
|
if (needExistField) {
|
||||||
|
Object pobj = parentNode.get(FIELD_NODE_EXIST);
|
||||||
|
boolean exist = pobj == null ? true : (boolean) pobj;
|
||||||
|
if (exist && !CollectionUtils.isEmpty(children)) {
|
||||||
|
long count = children.stream().filter(t -> {
|
||||||
|
Object obj = t.get(FIELD_NODE_EXIST);
|
||||||
|
if (obj != null) {
|
||||||
|
return !(boolean) obj;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}).count();
|
||||||
|
if (count > 0) {
|
||||||
|
exist = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parentNode.put(FIELD_NODE_EXIST, exist);
|
||||||
|
}
|
||||||
|
innerBuild(treeNodes, childNode, deep + 1, maxDeep, needExistField);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -14,6 +14,7 @@
|
|||||||
<modules>
|
<modules>
|
||||||
<module>ruoyi-monitor-admin</module>
|
<module>ruoyi-monitor-admin</module>
|
||||||
<module>ruoyi-xxl-job-admin</module>
|
<module>ruoyi-xxl-job-admin</module>
|
||||||
|
<module>ruoyi-isc-gateway</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
46
ruoyi-extend/ruoyi-isc-gateway/pom.xml
Normal file
46
ruoyi-extend/ruoyi-isc-gateway/pom.xml
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>ruoyi-vue-plus</artifactId>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<version>3.3.0</version>
|
||||||
|
<relativePath>../../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>ruoyi-isc-gateway</artifactId>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<artifactId>ruoyi-isc-common</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-gateway</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.redisson</groupId>
|
||||||
|
<artifactId>redisson-spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>de.codecentric</groupId>
|
||||||
|
<artifactId>spring-boot-admin-starter-client</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-all</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
package com.ruoyi.gateway;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启动程序
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-09-11
|
||||||
|
*/
|
||||||
|
@SpringBootApplication
|
||||||
|
public class GatewayApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(GatewayApplication.class, args);
|
||||||
|
System.out.println("Gateway 启动成功" );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,112 @@
|
|||||||
|
package com.ruoyi.gateway.config;
|
||||||
|
|
||||||
|
import cn.hutool.extra.spring.SpringUtil;
|
||||||
|
import com.ruoyi.gateway.config.handler.GlobalErrorWebExceptionHandler;
|
||||||
|
import com.ruoyi.gateway.config.provider.RedisRouteDefinitionRepository;
|
||||||
|
import com.ruoyi.gateway.filter.CustomerGlobalFilter;
|
||||||
|
import com.ruoyi.gateway.ratelimit.CustomerRedisRateLimiter;
|
||||||
|
import com.ruoyi.gateway.utils.caching.CachingRule;
|
||||||
|
import com.ruoyi.isc.common.utils.beans.TopicMsg;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.redisson.api.RTopic;
|
||||||
|
import org.redisson.api.RedissonClient;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
|
||||||
|
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
|
||||||
|
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||||
|
import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter;
|
||||||
|
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
|
||||||
|
import org.springframework.cloud.gateway.support.ConfigurationService;
|
||||||
|
import org.springframework.context.ApplicationEventPublisher;
|
||||||
|
import org.springframework.context.ApplicationEventPublisherAware;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
|
||||||
|
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
||||||
|
import org.springframework.data.redis.core.script.RedisScript;
|
||||||
|
import org.springframework.lang.NonNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import static com.ruoyi.isc.common.constant.IscGatewayContants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gateway 配置文件
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-09-11
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Configuration
|
||||||
|
public class GatewayConfig implements ApplicationEventPublisherAware {
|
||||||
|
public ApplicationEventPublisher publisher;
|
||||||
|
private final RedissonClient client = SpringUtil.getBean(RedissonClient.class);
|
||||||
|
|
||||||
|
{
|
||||||
|
subscribe(TOPIC_GATEWAY_REFRESH_ROUTE, TopicMsg.class, msg -> {
|
||||||
|
publisher.publishEvent(new RefreshRoutesEvent(this));
|
||||||
|
log.info("网关接收通知[{}]刷新本地路由!", msg);
|
||||||
|
});
|
||||||
|
subscribe(TOPIC_GATEWAY_RULE, TopicMsg.class, msg -> {
|
||||||
|
switch (msg.getType()) {
|
||||||
|
case ADD:
|
||||||
|
case UPDATE:
|
||||||
|
case DELETE:
|
||||||
|
CachingRule.evict(msg.getId());
|
||||||
|
log.info("网关接收通知id:[{}], type:[{}], msg:[{}]清除本地规则!", msg.getId(), msg.getType(), msg.getMsg());
|
||||||
|
break;
|
||||||
|
case REFRESH:
|
||||||
|
CachingRule.refresh();
|
||||||
|
log.info("网关接收通知id:[{}], type:[{}], msg:[{}]本地所有规则!", msg.getId(), msg.getType(), msg.getMsg());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redis 路由仓库
|
||||||
|
*
|
||||||
|
* @return redis路由仓库
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public RouteDefinitionRepository redisRouteDefinitionRepository() {
|
||||||
|
return new RedisRouteDefinitionRepository(client);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public CustomerRedisRateLimiter customerRedisRateLimiter(ReactiveStringRedisTemplate redisTemplate,
|
||||||
|
@Qualifier(RedisRateLimiter.REDIS_SCRIPT_NAME) RedisScript<List<Long>> redisScript,
|
||||||
|
ConfigurationService configurationService, DefaultRedisScript<Long> timeRedisScript) {
|
||||||
|
return new CustomerRedisRateLimiter(redisTemplate, redisScript, configurationService, timeRedisScript);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public GlobalFilter customerGlobalFilter(CustomerRedisRateLimiter customerRedisRateLimiter) {
|
||||||
|
return new CustomerGlobalFilter(customerRedisRateLimiter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ErrorWebExceptionHandler errorWebExceptionHandler() {
|
||||||
|
return new GlobalErrorWebExceptionHandler();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅通道接收消息
|
||||||
|
*
|
||||||
|
* @param channelKey 通道key
|
||||||
|
* @param clazz 消息类型
|
||||||
|
* @param consumer 自定义处理
|
||||||
|
*/
|
||||||
|
public <T> void subscribe(String channelKey, Class<T> clazz, Consumer<T> consumer) {
|
||||||
|
RTopic topic = client.getTopic(channelKey);
|
||||||
|
topic.addListener(clazz, (channel, msg) -> consumer.accept(msg));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setApplicationEventPublisher(@NonNull ApplicationEventPublisher publisher) {
|
||||||
|
this.publisher = publisher;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,109 @@
|
|||||||
|
package com.ruoyi.gateway.config;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.ruoyi.gateway.config.provider.RedissonProperties;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.redisson.Redisson;
|
||||||
|
import org.redisson.api.RedissonClient;
|
||||||
|
import org.redisson.codec.JsonJacksonCodec;
|
||||||
|
import org.redisson.config.Config;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
|
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
|
||||||
|
import org.springframework.cache.annotation.CachingConfigurerSupport;
|
||||||
|
import org.springframework.cache.annotation.EnableCaching;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* redis配置
|
||||||
|
*
|
||||||
|
* @author Lion Li
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Configuration
|
||||||
|
@EnableCaching
|
||||||
|
public class RedisConfig extends CachingConfigurerSupport {
|
||||||
|
|
||||||
|
private static final String REDIS_PROTOCOL_PREFIX = "redis://";
|
||||||
|
private static final String REDISS_PROTOCOL_PREFIX = "rediss://";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RedisProperties redisProperties;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RedissonProperties redissonProperties;
|
||||||
|
|
||||||
|
@Bean(destroyMethod = "shutdown")
|
||||||
|
@ConditionalOnMissingBean(RedissonClient.class)
|
||||||
|
public RedissonClient redisson() throws IOException {
|
||||||
|
String prefix = REDIS_PROTOCOL_PREFIX;
|
||||||
|
if (redisProperties.isSsl()) {
|
||||||
|
prefix = REDISS_PROTOCOL_PREFIX;
|
||||||
|
}
|
||||||
|
Config config = new Config();
|
||||||
|
config.setThreads(redissonProperties.getThreads())
|
||||||
|
.setNettyThreads(redissonProperties.getNettyThreads())
|
||||||
|
.setCodec(JsonJacksonCodec.INSTANCE)
|
||||||
|
.setTransportMode(redissonProperties.getTransportMode());
|
||||||
|
|
||||||
|
RedissonProperties.SingleServerConfig singleServerConfig = redissonProperties.getSingleServerConfig();
|
||||||
|
// 使用单机模式
|
||||||
|
config.useSingleServer()
|
||||||
|
.setAddress(prefix + redisProperties.getHost() + ":" + redisProperties.getPort())
|
||||||
|
.setConnectTimeout(((Long) redisProperties.getTimeout().toMillis()).intValue())
|
||||||
|
.setDatabase(redisProperties.getDatabase())
|
||||||
|
.setPassword(StrUtil.isNotBlank(redisProperties.getPassword()) ? redisProperties.getPassword() : null)
|
||||||
|
.setTimeout(singleServerConfig.getTimeout())
|
||||||
|
.setRetryAttempts(singleServerConfig.getRetryAttempts())
|
||||||
|
.setRetryInterval(singleServerConfig.getRetryInterval())
|
||||||
|
.setSubscriptionsPerConnection(singleServerConfig.getSubscriptionsPerConnection())
|
||||||
|
.setClientName(singleServerConfig.getClientName())
|
||||||
|
.setIdleConnectionTimeout(singleServerConfig.getIdleConnectionTimeout())
|
||||||
|
.setSubscriptionConnectionMinimumIdleSize(singleServerConfig.getSubscriptionConnectionMinimumIdleSize())
|
||||||
|
.setSubscriptionConnectionPoolSize(singleServerConfig.getSubscriptionConnectionPoolSize())
|
||||||
|
.setConnectionMinimumIdleSize(singleServerConfig.getConnectionMinimumIdleSize())
|
||||||
|
.setConnectionPoolSize(singleServerConfig.getConnectionPoolSize())
|
||||||
|
.setDnsMonitoringInterval(singleServerConfig.getDnsMonitoringInterval());
|
||||||
|
RedissonClient redissonClient = Redisson.create(config);
|
||||||
|
log.info("初始化 redis 配置");
|
||||||
|
return redissonClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public DefaultRedisScript<Long> limitScript() {
|
||||||
|
DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
|
||||||
|
redisScript.setScriptText(limitScriptText());
|
||||||
|
redisScript.setResultType(Long.class);
|
||||||
|
return redisScript;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 限流脚本
|
||||||
|
*/
|
||||||
|
private String limitScriptText() {
|
||||||
|
return StrUtil.builder()
|
||||||
|
.append("local key = KEYS[1]\n")
|
||||||
|
.append("local count = tonumber(ARGV[1])\n")
|
||||||
|
.append("local time = tonumber(ARGV[2])\n")
|
||||||
|
.append("local current = tonumber(redis.call('get', key));\n")
|
||||||
|
.append("if current == nil then\n")
|
||||||
|
.append(" current = 1 \n")
|
||||||
|
.append("end\n")
|
||||||
|
//.append("redis.log(redis.LOG_WARNING, \"current \" .. current)\n")
|
||||||
|
.append("if current > count then\n")
|
||||||
|
.append(" return current;\n")
|
||||||
|
.append("end\n")
|
||||||
|
.append("current = tonumber(redis.call('incr', key))\n")
|
||||||
|
//.append("redis.log(redis.LOG_WARNING, \"current \" .. current)\n")
|
||||||
|
.append("if current == 1 then\n")
|
||||||
|
.append(" redis.call('expire', key, time)\n")
|
||||||
|
.append("end\n")
|
||||||
|
.append("return current;")
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,100 @@
|
|||||||
|
package com.ruoyi.gateway.config.handler;
|
||||||
|
|
||||||
|
import cn.hutool.core.map.MapUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.core.io.buffer.DataBufferFactory;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.server.RequestPath;
|
||||||
|
import org.springframework.http.server.reactive.ServerHttpResponse;
|
||||||
|
import org.springframework.web.server.ResponseStatusException;
|
||||||
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
import org.springframework.web.server.handler.ResponseStatusExceptionHandler;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网关异常通用处理器,只作用在webflux 环境下 , 优先级低于 {@link ResponseStatusExceptionHandler} 执行
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-10-18
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Order(-1)
|
||||||
|
public class GlobalErrorWebExceptionHandler implements ErrorWebExceptionHandler {
|
||||||
|
|
||||||
|
public static final String NOT_FOUND_MESSAGE = "服务不存在";
|
||||||
|
public static final String SERVICE_UNAVAILABLE_MESSAGE = "服务暂时不可用";
|
||||||
|
public static final String GATEWAY_TIMEOUT_MESSAGE = "服务响应超时";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mono<Void> handle(ServerWebExchange exchange, Throwable ex)
|
||||||
|
{
|
||||||
|
ServerHttpResponse response = exchange.getResponse();
|
||||||
|
|
||||||
|
if (response.isCommitted()) {
|
||||||
|
return Mono.error(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// header set
|
||||||
|
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
|
||||||
|
if (ex instanceof ResponseStatusException) {
|
||||||
|
final ResponseStatusException statusException = (ResponseStatusException) ex;
|
||||||
|
response.setStatusCode(statusException.getStatus());
|
||||||
|
}
|
||||||
|
Optional<Integer> code = Optional.ofNullable(response.getRawStatusCode());
|
||||||
|
final String message = getMessage(ex);
|
||||||
|
|
||||||
|
return response.writeWith(Mono.fromSupplier(() -> {
|
||||||
|
DataBufferFactory bufferFactory = response.bufferFactory();
|
||||||
|
return bufferFactory.wrap(JSONUtil.toJsonStr(result(code, message, exchange.getRequest().getPath()))
|
||||||
|
.getBytes(StandardCharsets.UTF_8));
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getMessage(Throwable ex)
|
||||||
|
{
|
||||||
|
String reason;
|
||||||
|
if(ex instanceof ResponseStatusException) {
|
||||||
|
ResponseStatusException statusException = (ResponseStatusException) ex;
|
||||||
|
switch (statusException.getStatus()) {
|
||||||
|
case NOT_FOUND:
|
||||||
|
reason = NOT_FOUND_MESSAGE;
|
||||||
|
break;
|
||||||
|
case SERVICE_UNAVAILABLE:
|
||||||
|
reason = SERVICE_UNAVAILABLE_MESSAGE;
|
||||||
|
break;
|
||||||
|
case GATEWAY_TIMEOUT:
|
||||||
|
reason = GATEWAY_TIMEOUT_MESSAGE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
reason = statusException.getReason();
|
||||||
|
}
|
||||||
|
if(log.isDebugEnabled()){
|
||||||
|
log.debug(reason, ex);
|
||||||
|
}
|
||||||
|
if(StrUtil.isNotBlank(reason)) {
|
||||||
|
return reason;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String message = ex.getMessage();
|
||||||
|
log.error(message, ex);
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> result(Optional<Integer> code, String message, RequestPath path) {
|
||||||
|
final HashMap<String, Object> result = MapUtil.newHashMap(3);
|
||||||
|
result.put("code", code.orElse(HttpStatus.INTERNAL_SERVER_ERROR.value()));
|
||||||
|
result.put("message", message);
|
||||||
|
result.put("path", path.value());
|
||||||
|
result.put("data", null);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,61 @@
|
|||||||
|
package com.ruoyi.gateway.config.provider;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.redisson.api.RMap;
|
||||||
|
import org.redisson.api.RedissonClient;
|
||||||
|
import org.redisson.client.codec.Codec;
|
||||||
|
import org.redisson.codec.TypedJsonJacksonCodec;
|
||||||
|
import org.springframework.cloud.gateway.route.RouteDefinition;
|
||||||
|
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
|
||||||
|
import reactor.core.publisher.Flux;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
import static com.ruoyi.isc.common.constant.IscRedisKeys.KEY_ROUTES;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redis 路由仓库
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-09-11
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class RedisRouteDefinitionRepository implements RouteDefinitionRepository
|
||||||
|
{
|
||||||
|
public static final Codec ROUTE_CODES_INSTANCE = new TypedJsonJacksonCodec(String.class, RouteDefinition.class);
|
||||||
|
private final RedissonClient redissonClient;
|
||||||
|
|
||||||
|
public RedisRouteDefinitionRepository(RedissonClient redissonClient)
|
||||||
|
{
|
||||||
|
this.redissonClient = redissonClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Flux<RouteDefinition> getRouteDefinitions()
|
||||||
|
{
|
||||||
|
RMap<String, RouteDefinition> map = redissonClient.getMap(KEY_ROUTES, ROUTE_CODES_INSTANCE);
|
||||||
|
log.debug("Routes from redis size:[{}]!", map.size());
|
||||||
|
return Flux.fromIterable(map.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mono<Void> save(Mono<RouteDefinition> route)
|
||||||
|
{
|
||||||
|
return route.flatMap(definition -> {
|
||||||
|
RMap<String, RouteDefinition> map = redissonClient.getMap(KEY_ROUTES, ROUTE_CODES_INSTANCE);
|
||||||
|
map.put(definition.getId(), definition);
|
||||||
|
log.debug("Saving route to redis id:[{}]!", definition.getId());
|
||||||
|
return Mono.empty();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mono<Void> delete(Mono<String> routeId)
|
||||||
|
{
|
||||||
|
return routeId.flatMap(id -> {
|
||||||
|
RMap<String, RouteDefinition> map = redissonClient.getMap(KEY_ROUTES, ROUTE_CODES_INSTANCE);
|
||||||
|
map.remove(id);
|
||||||
|
log.debug("Remove route from redis id:[{}]!", id);
|
||||||
|
return Mono.empty();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,134 @@
|
|||||||
|
package com.ruoyi.gateway.config.provider;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.redisson.config.TransportMode;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redisson 配置属性
|
||||||
|
*
|
||||||
|
* @author Lion Li
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Component
|
||||||
|
@ConfigurationProperties(prefix = "redisson")
|
||||||
|
public class RedissonProperties
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 线程池数量,默认值 = 当前处理核数量 * 2
|
||||||
|
*/
|
||||||
|
private int threads;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Netty线程池数量,默认值 = 当前处理核数量 * 2
|
||||||
|
*/
|
||||||
|
private int nettyThreads;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 传输模式
|
||||||
|
*/
|
||||||
|
private TransportMode transportMode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单机服务配置
|
||||||
|
*/
|
||||||
|
private SingleServerConfig singleServerConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存组
|
||||||
|
*/
|
||||||
|
private List<CacheGroup> cacheGroup;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
public static class SingleServerConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端名称
|
||||||
|
*/
|
||||||
|
private String clientName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最小空闲连接数
|
||||||
|
*/
|
||||||
|
private int connectionMinimumIdleSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 连接池大小
|
||||||
|
*/
|
||||||
|
private int connectionPoolSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 连接空闲超时,单位:毫秒
|
||||||
|
*/
|
||||||
|
private int idleConnectionTimeout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 命令等待超时,单位:毫秒
|
||||||
|
*/
|
||||||
|
private int timeout;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 如果尝试在此限制之内发送成功,则开始启用 timeout 计时。
|
||||||
|
*/
|
||||||
|
private int retryAttempts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 命令重试发送时间间隔,单位:毫秒
|
||||||
|
*/
|
||||||
|
private int retryInterval;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发布和订阅连接的最小空闲连接数
|
||||||
|
*/
|
||||||
|
private int subscriptionConnectionMinimumIdleSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发布和订阅连接池大小
|
||||||
|
*/
|
||||||
|
private int subscriptionConnectionPoolSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单个连接最大订阅数量
|
||||||
|
*/
|
||||||
|
private int subscriptionsPerConnection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DNS监测时间间隔,单位:毫秒
|
||||||
|
*/
|
||||||
|
private int dnsMonitoringInterval;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
public static class CacheGroup {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组id
|
||||||
|
*/
|
||||||
|
private String groupId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组过期时间
|
||||||
|
*/
|
||||||
|
private long ttl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组最大空闲时间
|
||||||
|
*/
|
||||||
|
private long maxIdleTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组最大长度
|
||||||
|
*/
|
||||||
|
private int maxSize;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
package com.ruoyi.gateway.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 错误消息常量
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-10-18
|
||||||
|
*/
|
||||||
|
public interface ErrorMessageConstant {
|
||||||
|
String AK_REQUIRE = "没有找到授权码[%s]";
|
||||||
|
String CONTENT_TYPE_NOT_SUPPORTED = "请求ContentType[%s]不支持";
|
||||||
|
String METHOD_NOT_SUPPORTED = "请求Method[%s]不支持";
|
||||||
|
String RATE_LIMIT = "调用次数[>%d/%s]过多";
|
||||||
|
String RULE_EXPIRED = "规则已过期[%s]";
|
||||||
|
String RULE_NOT_EXIST = "授权码[%s]对应服务[%s]规则不存在";
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
package com.ruoyi.gateway.exception;
|
||||||
|
|
||||||
|
import com.ruoyi.gateway.constant.ErrorMessageConstant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网关异常-AK必要
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-10-04
|
||||||
|
*/
|
||||||
|
public class AkRequireException extends GatewayException {
|
||||||
|
|
||||||
|
public AkRequireException(String ak)
|
||||||
|
{
|
||||||
|
super(String.format(ErrorMessageConstant.AK_REQUIRE, ak));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
package com.ruoyi.gateway.exception;
|
||||||
|
|
||||||
|
import com.ruoyi.gateway.constant.ErrorMessageConstant;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网关异常-请求方法不支持
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-10-04
|
||||||
|
*/
|
||||||
|
public class ContentTypeNotSupportedException extends GatewayException {
|
||||||
|
|
||||||
|
public ContentTypeNotSupportedException(MediaType contentType)
|
||||||
|
{
|
||||||
|
super(String.format(ErrorMessageConstant.CONTENT_TYPE_NOT_SUPPORTED, contentType));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
package com.ruoyi.gateway.exception;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.web.server.ResponseStatusException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网关异常
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-10-04
|
||||||
|
*/
|
||||||
|
public class GatewayException extends ResponseStatusException {
|
||||||
|
|
||||||
|
public GatewayException(String reason)
|
||||||
|
{
|
||||||
|
super(HttpStatus.INTERNAL_SERVER_ERROR, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GatewayException(HttpStatus status)
|
||||||
|
{
|
||||||
|
super(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GatewayException(HttpStatus status, String reason)
|
||||||
|
{
|
||||||
|
super(status, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GatewayException(HttpStatus status, String reason, Throwable cause)
|
||||||
|
{
|
||||||
|
super(status, reason, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GatewayException(int rawStatusCode, String reason, Throwable cause)
|
||||||
|
{
|
||||||
|
super(rawStatusCode, reason, cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
package com.ruoyi.gateway.exception;
|
||||||
|
|
||||||
|
import com.ruoyi.gateway.constant.ErrorMessageConstant;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网关异常-请求方法不支持
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-10-04
|
||||||
|
*/
|
||||||
|
public class MethodNotSupportedException extends GatewayException {
|
||||||
|
|
||||||
|
public MethodNotSupportedException(HttpMethod httpMethod)
|
||||||
|
{
|
||||||
|
super(String.format(ErrorMessageConstant.METHOD_NOT_SUPPORTED, httpMethod));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
package com.ruoyi.gateway.exception;
|
||||||
|
|
||||||
|
import com.ruoyi.gateway.constant.ErrorMessageConstant;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网关异常-限流异常
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-10-04
|
||||||
|
*/
|
||||||
|
public class RateLimitException extends GatewayException {
|
||||||
|
|
||||||
|
public RateLimitException(long limit, TimeUnit timeUnit)
|
||||||
|
{
|
||||||
|
super(HttpStatus.TOO_MANY_REQUESTS, String.format(ErrorMessageConstant.RATE_LIMIT, limit, timeUnit.name()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
package com.ruoyi.gateway.exception;
|
||||||
|
|
||||||
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import com.ruoyi.gateway.constant.ErrorMessageConstant;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网关异常-规则已过期
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-10-04
|
||||||
|
*/
|
||||||
|
public class RuleExpiredException extends GatewayException {
|
||||||
|
|
||||||
|
public RuleExpiredException(Date endTime)
|
||||||
|
{
|
||||||
|
super(String.format(ErrorMessageConstant.RULE_EXPIRED, DateUtil.formatDateTime(endTime)));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
package com.ruoyi.gateway.exception;
|
||||||
|
|
||||||
|
import com.ruoyi.gateway.constant.ErrorMessageConstant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网关异常-规则不存在
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-10-04
|
||||||
|
*/
|
||||||
|
public class RuleNotExistException extends GatewayException {
|
||||||
|
|
||||||
|
public RuleNotExistException(String ak, String path)
|
||||||
|
{
|
||||||
|
super(String.format(ErrorMessageConstant.RULE_NOT_EXIST, ak, path));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,378 @@
|
|||||||
|
package com.ruoyi.gateway.filter;
|
||||||
|
|
||||||
|
import cn.hutool.core.lang.Assert;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.hutool.json.JSONArray;
|
||||||
|
import cn.hutool.json.JSONException;
|
||||||
|
import cn.hutool.json.JSONObject;
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import com.ruoyi.gateway.exception.*;
|
||||||
|
import com.ruoyi.gateway.ratelimit.CustomerRedisRateLimiter;
|
||||||
|
import com.ruoyi.gateway.utils.GatewayUtils;
|
||||||
|
import com.ruoyi.isc.common.utils.beans.IscRule;
|
||||||
|
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||||
|
import org.springframework.cloud.gateway.filter.GlobalFilter;
|
||||||
|
import org.springframework.cloud.gateway.route.Route;
|
||||||
|
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||||
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
|
import org.springframework.util.MultiValueMap;
|
||||||
|
import org.springframework.web.reactive.function.server.HandlerStrategies;
|
||||||
|
import org.springframework.web.reactive.function.server.ServerRequest;
|
||||||
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
import org.springframework.web.util.UriComponentsBuilder;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static com.ruoyi.gateway.filter.CustomerGlobalFilter.AccessKey.AccessKeyType;
|
||||||
|
import static com.ruoyi.gateway.filter.CustomerGlobalFilter.AccessKey.AccessKeyType.*;
|
||||||
|
import static com.ruoyi.isc.common.constant.IscGatewayContants.*;
|
||||||
|
import static org.springframework.util.CollectionUtils.unmodifiableMultiValueMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自定义全局过滤器,操作如下:
|
||||||
|
* 1.ak 是否存在
|
||||||
|
* 2.是否到期
|
||||||
|
* 3.是否限流
|
||||||
|
* 4.删除参数ak
|
||||||
|
* 5.添加隐藏参数
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-10-15
|
||||||
|
*/
|
||||||
|
public class CustomerGlobalFilter implements GlobalFilter, Ordered {
|
||||||
|
private final CustomerRedisRateLimiter rateLimiter;
|
||||||
|
|
||||||
|
public CustomerGlobalFilter(CustomerRedisRateLimiter rateLimiter) {
|
||||||
|
this.rateLimiter = rateLimiter;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final TimeUnit[] TIME_UNITS = {TimeUnit.SECONDS, TimeUnit.MINUTES, TimeUnit.HOURS, TimeUnit.DAYS};
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
|
||||||
|
final Route route = exchange.getRequiredAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
|
||||||
|
final Map<String, Object> metadata = route.getMetadata();
|
||||||
|
final ServerHttpRequest request = exchange.getRequest();
|
||||||
|
//ak 是否存在
|
||||||
|
final HttpMethod httpMethod = request.getMethod();
|
||||||
|
AccessKey accessKey = new AccessKey(String.valueOf(metadata.getOrDefault(CONFIG_ACCESS_KEY_NAME_KEY,
|
||||||
|
ACCESS_KEY_NAME_DEFAULT)));
|
||||||
|
accessKey.set(GatewayUtils.getValue(null, () -> request.getHeaders().get(accessKey.name)), HEADER);
|
||||||
|
MultiValueMap<String, String> queryParams = request.getQueryParams().containsKey(accessKey.name) ?
|
||||||
|
new LinkedMultiValueMap<>(request.getQueryParams()) : request.getQueryParams();
|
||||||
|
if (HttpMethod.GET.equals(httpMethod)) {
|
||||||
|
return handleGetRequest(exchange, chain, route, request, accessKey, queryParams);
|
||||||
|
} else if (HttpMethod.POST.equals(httpMethod)) {
|
||||||
|
return handlePostRequest(exchange, chain, route, request, accessKey, queryParams);
|
||||||
|
}
|
||||||
|
throw new MethodNotSupportedException(httpMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理POST 请求
|
||||||
|
*
|
||||||
|
* @param exchange 当前服务交换器
|
||||||
|
* @param chain 当前过滤链
|
||||||
|
* @param route 路由信息
|
||||||
|
* @param request 请求信息
|
||||||
|
* @param accessKey AK信息
|
||||||
|
* @param queryParams URL查询参数
|
||||||
|
* @return 指示请求处理何时完成
|
||||||
|
*/
|
||||||
|
private Mono<Void> handlePostRequest(ServerWebExchange exchange, GatewayFilterChain chain, Route route,
|
||||||
|
ServerHttpRequest request, AccessKey accessKey,
|
||||||
|
MultiValueMap<String, String> queryParams) {
|
||||||
|
//处理 URL AccessKey
|
||||||
|
handleAccessKey(accessKey, () -> queryParams.get(accessKey.name), URI, false);
|
||||||
|
ServerRequest serverRequest = ServerRequest.create(exchange, HandlerStrategies.withDefaults().messageReaders());
|
||||||
|
final Mono<String> modifiedBody = serverRequest.bodyToMono(String.class).defaultIfEmpty(StrUtil.EMPTY)
|
||||||
|
.flatMap(body -> {
|
||||||
|
MediaType mediaType = request.getHeaders().getContentType();
|
||||||
|
if (Objects.isNull(mediaType) || MediaType.APPLICATION_JSON.equals(mediaType)) {
|
||||||
|
try {
|
||||||
|
JSONObject jsonObj = StrUtil.isBlank(body) ? new JSONObject() : JSONUtil.parseObj(body);
|
||||||
|
return handlePostRequestJson(exchange, route, request, accessKey, jsonObj, queryParams);
|
||||||
|
}catch (JSONException e) {
|
||||||
|
if(Objects.nonNull(mediaType)) {
|
||||||
|
return Mono.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (MediaType.APPLICATION_FORM_URLENCODED.equals(mediaType)) {
|
||||||
|
return handlePostRequestFormUrlencoded(exchange, route, request, accessKey, body, queryParams);
|
||||||
|
}
|
||||||
|
return Mono.error(() -> new ContentTypeNotSupportedException(mediaType));
|
||||||
|
});
|
||||||
|
//如果 AccessKey 在URI部分 URI需要重新生成
|
||||||
|
URI uri = URI.equals(accessKey.type) ? getNewUri().apply(request, queryParams) : null;
|
||||||
|
return GatewayUtils.modifyBody(exchange, chain, modifiedBody, uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理POST APPLICATION_FORM_URLENCODED 请求
|
||||||
|
*
|
||||||
|
* @param exchange 当前服务交换器
|
||||||
|
* @param route 路由信息
|
||||||
|
* @param request 请求信息
|
||||||
|
* @param accessKey AK信息
|
||||||
|
* @param body 请求Body信息
|
||||||
|
* @return 处理后的Body信息
|
||||||
|
*/
|
||||||
|
private Mono<? extends String> handlePostRequestFormUrlencoded(ServerWebExchange exchange, Route route,
|
||||||
|
ServerHttpRequest request, AccessKey accessKey,
|
||||||
|
String body, MultiValueMap<String, String> queryParams) {
|
||||||
|
|
||||||
|
if (StrUtil.isBlank(body)) {
|
||||||
|
Assert.notBlank(accessKey.value, () -> new AkRequireException(accessKey.name));
|
||||||
|
}
|
||||||
|
final List<String[]> srcParams = Arrays.stream(body.split("&")).map(param -> param.split("="))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
final IscRule rule = handleRule(accessKey, () -> srcParams.stream()
|
||||||
|
.filter(param -> param.length > 0 && accessKey.name.equals(param[0]))
|
||||||
|
.map(param -> param[1]).collect(Collectors.toList()), route, BODY);
|
||||||
|
Supplier<Mono<String>> rateLimiterAfterSupplier = () -> {
|
||||||
|
removeParam(accessKey, request, null, queryParams);
|
||||||
|
final List<String[]> params = srcParams.stream().filter(param -> !accessKey.name.equals(param[0]))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
handleHiddenParams(route, params, (next, list) -> {
|
||||||
|
Object value;
|
||||||
|
if (Objects.isNull(value = next.getValue())) {
|
||||||
|
list.add(new String[]{next.getKey(), StrUtil.EMPTY});
|
||||||
|
} else if (value instanceof JSONArray) {
|
||||||
|
((JSONArray) value).stream().map(String::valueOf)
|
||||||
|
.forEach(v -> list.add(new String[]{next.getKey(), v}));
|
||||||
|
} else {
|
||||||
|
list.add(new String[]{next.getKey(), next.getValue().toString()});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return Mono.just(params.stream().map(param -> param[0] + '=' + param[1]).collect(Collectors.joining("&")));
|
||||||
|
};
|
||||||
|
|
||||||
|
return rateLimiter(exchange, rule, route, 0, rateLimiterAfterSupplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理POST APPLICATION_JSON 请求
|
||||||
|
*
|
||||||
|
* @param exchange 当前服务交换器
|
||||||
|
* @param route 路由信息
|
||||||
|
* @param request 请求信息
|
||||||
|
* @param accessKey AK信息
|
||||||
|
* @param jsonObj 请求Body JSON信息
|
||||||
|
* @return 处理后的Body信息
|
||||||
|
*/
|
||||||
|
private Mono<? extends String> handlePostRequestJson(ServerWebExchange exchange, Route route,
|
||||||
|
ServerHttpRequest request, AccessKey accessKey,
|
||||||
|
JSONObject jsonObj, MultiValueMap<String, String> queryParams) {
|
||||||
|
final IscRule rule = handleRule(accessKey, () -> Collections.singletonList(jsonObj.get(accessKey.name,
|
||||||
|
String.class, true)), route, BODY);
|
||||||
|
Supplier<Mono<String>> rateLimiterAfterSupplier = () -> {
|
||||||
|
removeParam(accessKey, request, () -> jsonObj.remove(accessKey.name), queryParams);
|
||||||
|
handleHiddenParams(route, jsonObj, (next, map) -> map.set(next.getKey(), next.getValue()));
|
||||||
|
return Mono.just(jsonObj.toString());
|
||||||
|
};
|
||||||
|
|
||||||
|
return rateLimiter(exchange, rule, route, 0, rateLimiterAfterSupplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理GET 请求
|
||||||
|
*
|
||||||
|
* @param exchange 当前服务交换器
|
||||||
|
* @param chain 当前过滤链
|
||||||
|
* @param route 路由信息
|
||||||
|
* @param request 请求信息
|
||||||
|
* @param accessKey AK信息
|
||||||
|
* @param queryParams URL查询参数
|
||||||
|
* @return 指示请求处理何时完成
|
||||||
|
*/
|
||||||
|
private Mono<Void> handleGetRequest(ServerWebExchange exchange, GatewayFilterChain chain, Route route,
|
||||||
|
ServerHttpRequest request, AccessKey accessKey,
|
||||||
|
MultiValueMap<String, String> queryParams) {
|
||||||
|
final IscRule rule = handleRule(accessKey, () -> queryParams.get(accessKey.name), route, URI);
|
||||||
|
Supplier<Mono<Void>> rateLimiterAfterSupplier = () -> {
|
||||||
|
removeParam(accessKey, request, null, queryParams);
|
||||||
|
handleHiddenParams(route, queryParams, (next, map) -> {
|
||||||
|
Object value;
|
||||||
|
if (Objects.isNull(value = next.getValue())) {
|
||||||
|
map.add(next.getKey(), StrUtil.EMPTY);
|
||||||
|
} else if (value instanceof JSONArray) {
|
||||||
|
map.put(next.getKey(), ((JSONArray) value).toList(String.class));
|
||||||
|
} else {
|
||||||
|
map.add(next.getKey(), value.toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
ServerHttpRequest req = exchange.getRequest().mutate().uri(getNewUri().apply(request, queryParams)).build();
|
||||||
|
return chain.filter(exchange.mutate().request(req).build());
|
||||||
|
};
|
||||||
|
return rateLimiter(exchange, rule, route, 0, rateLimiterAfterSupplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
private BiFunction<ServerHttpRequest, MultiValueMap<String, String>, URI> getNewUri() {
|
||||||
|
return (request, queryParams) -> UriComponentsBuilder.fromUri(request.getURI())
|
||||||
|
.replaceQueryParams(unmodifiableMultiValueMap(queryParams)).build().toUri();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getOrder() {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理规则
|
||||||
|
*
|
||||||
|
* @param accessKey AK信息
|
||||||
|
* @param valueSupplier valueList 生产者
|
||||||
|
* @param route 路由信息
|
||||||
|
* @param type AK类型
|
||||||
|
* @return AK对应服务规则信息
|
||||||
|
*/
|
||||||
|
private IscRule handleRule(AccessKey accessKey, Supplier<List<String>> valueSupplier, Route route, AccessKeyType type) {
|
||||||
|
if(Objects.nonNull(valueSupplier) && Objects.nonNull(type)) {
|
||||||
|
handleAccessKey(accessKey, valueSupplier, type, true);
|
||||||
|
}
|
||||||
|
//获取规则
|
||||||
|
final IscRule rule = GatewayUtils.getRequiredValue(() -> GatewayUtils.getRule(accessKey.value, route.getId()),
|
||||||
|
() -> new RuleNotExistException(accessKey.value, route.getId()));
|
||||||
|
//是否到期
|
||||||
|
GatewayUtils.isBefore(rule, () -> new RuleExpiredException(rule.getExpire()));
|
||||||
|
//设置AK 到ID 为了传参方便
|
||||||
|
rule.setId(accessKey.value);
|
||||||
|
return rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理 accessKey
|
||||||
|
*
|
||||||
|
* @param accessKey AccessKey
|
||||||
|
* @param valueSupplier valueList 生产者
|
||||||
|
* @param type AccessKeyType
|
||||||
|
* @param throwException 是否抛出异常
|
||||||
|
*/
|
||||||
|
private void handleAccessKey(AccessKey accessKey, Supplier<List<String>> valueSupplier, AccessKeyType type, boolean throwException) {
|
||||||
|
//获取AK
|
||||||
|
String value;
|
||||||
|
if(throwException) {
|
||||||
|
value = GatewayUtils.getValue(accessKey.value, valueSupplier, () -> new AkRequireException(accessKey.name));
|
||||||
|
}else {
|
||||||
|
value = GatewayUtils.getValue(accessKey.value, valueSupplier, null);
|
||||||
|
}
|
||||||
|
accessKey.set(value, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除参数
|
||||||
|
*
|
||||||
|
* @param accessKey AK信息
|
||||||
|
* @param request 请求
|
||||||
|
* @param removeSupplier 删除参数提供者
|
||||||
|
* @param queryParams URI请求参数
|
||||||
|
* @param <T> 类型
|
||||||
|
*/
|
||||||
|
private <T> void removeParam(AccessKey accessKey, ServerHttpRequest request, Supplier<T> removeSupplier,
|
||||||
|
MultiValueMap<String, String> queryParams) {
|
||||||
|
//如果header中有AK,则删除
|
||||||
|
if (HEADER.equals(accessKey.type)) {
|
||||||
|
final HttpHeaders headers = request.getHeaders();
|
||||||
|
if(headers.containsKey(accessKey.name)) {
|
||||||
|
request.mutate().headers(headMap -> headMap.remove(accessKey.name)).build();
|
||||||
|
}
|
||||||
|
}else if(URI.equals(accessKey.type)) {
|
||||||
|
queryParams.remove(accessKey.name);
|
||||||
|
}
|
||||||
|
if (Objects.nonNull(removeSupplier)) {
|
||||||
|
removeSupplier.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理隐藏参数
|
||||||
|
*
|
||||||
|
* @param route 路由信息
|
||||||
|
* @param result 参数
|
||||||
|
* @param mapper 处理参数方法
|
||||||
|
* @param <U> 参数类型
|
||||||
|
*/
|
||||||
|
private <U> void handleHiddenParams(Route route, U result, BiConsumer<Map.Entry<String, Object>, U> mapper) {
|
||||||
|
final Object obj = route.getMetadata().get(CONFIG_ADD_PARAM_KEY);
|
||||||
|
if (Objects.isNull(obj)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final JSONObject json = JSONUtil.parseObj(obj.toString());
|
||||||
|
if (json.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (Map.Entry<String, Object> next : json.entrySet()) {
|
||||||
|
mapper.accept(next, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 限流
|
||||||
|
*
|
||||||
|
* @param exchange 当前服务交换器
|
||||||
|
* @param rule 限流规则
|
||||||
|
* @param route 路由
|
||||||
|
* @param rateLimiterAfterSupplier 限流后操作(删除参数、添加隐藏参数,跳转)
|
||||||
|
* @param <T> 最终返回类型
|
||||||
|
* @return rateLimiterAfterSupplier 返回类型
|
||||||
|
*/
|
||||||
|
private <T> Mono<T> rateLimiter(ServerWebExchange exchange, IscRule rule, Route route, final int index,
|
||||||
|
Supplier<Mono<T>> rateLimiterAfterSupplier) {
|
||||||
|
final TimeUnit timeUnit = TIME_UNITS[index];
|
||||||
|
final Long limit = TimeUnit.SECONDS.equals(timeUnit) ? rule.getSecondsLimit() : TimeUnit.MINUTES.equals(timeUnit)
|
||||||
|
? rule.getMinutesLimit() : TimeUnit.HOURS.equals(timeUnit) ? rule.getHoursLimit() : rule.getDaysLimit();
|
||||||
|
if (Objects.isNull(limit) || limit <= 0L) {
|
||||||
|
if (TimeUnit.DAYS.equals(timeUnit)) {
|
||||||
|
return rateLimiterAfterSupplier.get();
|
||||||
|
}
|
||||||
|
return rateLimiter(exchange, rule, route, index + 1, rateLimiterAfterSupplier);
|
||||||
|
}
|
||||||
|
return rateLimiter.isAllowed(route.getId(), rule.getId(), limit, timeUnit).flatMap(response -> {
|
||||||
|
for (Map.Entry<String, String> header : response.getHeaders().entrySet()) {
|
||||||
|
exchange.getResponse().getHeaders().add(header.getKey(), header.getValue());
|
||||||
|
}
|
||||||
|
if (response.isAllowed()) {
|
||||||
|
if (TimeUnit.DAYS.equals(timeUnit)) {
|
||||||
|
return rateLimiterAfterSupplier.get();
|
||||||
|
}
|
||||||
|
return rateLimiter(exchange, rule, route, index + 1, rateLimiterAfterSupplier);
|
||||||
|
}
|
||||||
|
return Mono.error(() -> new RateLimitException(limit, timeUnit));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AK 信息
|
||||||
|
*/
|
||||||
|
public static class AccessKey {
|
||||||
|
public AccessKey(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
public void set(String value, AccessKeyType type) {
|
||||||
|
if(StrUtil.isNotBlank(value)) {
|
||||||
|
this.value = value;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public enum AccessKeyType {
|
||||||
|
HEADER,
|
||||||
|
URI,
|
||||||
|
BODY
|
||||||
|
}
|
||||||
|
private final String name;
|
||||||
|
private String value;
|
||||||
|
private AccessKeyType type;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,199 @@
|
|||||||
|
package com.ruoyi.gateway.ratelimit;
|
||||||
|
|
||||||
|
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.ruoyi.gateway.utils.GatewayUtils;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.cloud.gateway.filter.ratelimit.RedisRateLimiter;
|
||||||
|
import org.springframework.cloud.gateway.support.ConfigurationService;
|
||||||
|
import org.springframework.data.redis.core.ReactiveStringRedisTemplate;
|
||||||
|
import org.springframework.data.redis.core.script.DefaultRedisScript;
|
||||||
|
import org.springframework.data.redis.core.script.RedisScript;
|
||||||
|
import reactor.core.publisher.Flux;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.LocalTime;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-10-16
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class CustomerRedisRateLimiter extends RedisRateLimiter {
|
||||||
|
|
||||||
|
private final ReactiveStringRedisTemplate redisTemplate;
|
||||||
|
|
||||||
|
private final RedisScript<List<Long>> script;
|
||||||
|
private final RedisScript<Long> timeRedisScript;
|
||||||
|
|
||||||
|
private final AtomicBoolean initialized = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
public CustomerRedisRateLimiter(ReactiveStringRedisTemplate redisTemplate, RedisScript<List<Long>> script,
|
||||||
|
ConfigurationService configurationService, DefaultRedisScript<Long> timeRedisScript) {
|
||||||
|
super(redisTemplate, script, configurationService);
|
||||||
|
this.redisTemplate = redisTemplate;
|
||||||
|
this.script = script;
|
||||||
|
this.timeRedisScript = timeRedisScript;
|
||||||
|
this.initialized.compareAndSet(false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mono<Response> isAllowed(String routeId, String ak, Long replenishRate, TimeUnit timeUnit) {
|
||||||
|
Config routeConfig = new Config().setReplenishRate(replenishRate.intValue());
|
||||||
|
String id = GatewayUtils.getRouteKey(ak, routeId);
|
||||||
|
int time = 60;
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
List<String> keys;
|
||||||
|
switch (timeUnit) {
|
||||||
|
case DAYS:
|
||||||
|
time += LocalDateTimeUtil.between(now, LocalDateTime.now().with(LocalTime.MAX), ChronoUnit.SECONDS);
|
||||||
|
keys = getKeys(id, now.getDayOfMonth(), timeUnit);
|
||||||
|
break;
|
||||||
|
case HOURS:
|
||||||
|
time += (60 - now.getMinute()) * 60 - now.getSecond();
|
||||||
|
keys = getKeys(id, now.getHour(), timeUnit);
|
||||||
|
break;
|
||||||
|
case MINUTES:
|
||||||
|
time += 60 - now.getSecond();
|
||||||
|
keys = getKeys(id, now.getMinute(), timeUnit);
|
||||||
|
break;
|
||||||
|
case SECONDS:
|
||||||
|
return isAllowed(routeConfig, id);
|
||||||
|
default:
|
||||||
|
return Mono.just(new Response(true, getHeaders(routeConfig, -1L)));
|
||||||
|
}
|
||||||
|
return isAllowed(routeConfig, keys, time, timeUnit);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mono<Response> isAllowed(Config routeConfig, String id) {
|
||||||
|
if (!this.initialized.get()) {
|
||||||
|
throw new IllegalStateException("RedisRateLimiter is not initialized");
|
||||||
|
}
|
||||||
|
|
||||||
|
// How many requests per second do you want a user to be allowed to do?
|
||||||
|
int replenishRate = routeConfig.getReplenishRate();
|
||||||
|
|
||||||
|
// How much bursting do you want to allow?
|
||||||
|
int burstCapacity = routeConfig.getBurstCapacity();
|
||||||
|
|
||||||
|
// How many tokens are requested per request?
|
||||||
|
int requestedTokens = routeConfig.getRequestedTokens();
|
||||||
|
|
||||||
|
try {
|
||||||
|
List<String> keys = getKeys(id);
|
||||||
|
|
||||||
|
// The arguments to the LUA script. time() returns unixtime in seconds.
|
||||||
|
List<String> scriptArgs = Arrays.asList(replenishRate + "", burstCapacity + "",
|
||||||
|
Instant.now().getEpochSecond() + "", requestedTokens + "");
|
||||||
|
// allowed, tokens_left = redis.eval(SCRIPT, keys, args)
|
||||||
|
Flux<List<Long>> flux = this.redisTemplate.execute(this.script, keys, scriptArgs);
|
||||||
|
// .log("redisratelimiter", Level.FINER);
|
||||||
|
return flux.onErrorResume(throwable -> {
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("Error calling rate limiter lua", throwable);
|
||||||
|
}
|
||||||
|
return Flux.just(Arrays.asList(1L, -1L));
|
||||||
|
}).reduce(new ArrayList<Long>(), (longs, l) -> {
|
||||||
|
longs.addAll(l);
|
||||||
|
return longs;
|
||||||
|
}).map(results -> {
|
||||||
|
boolean allowed = results.get(0) == 1L;
|
||||||
|
Long tokensLeft = results.get(1);
|
||||||
|
|
||||||
|
Response response = new Response(allowed, getHeaders(routeConfig, tokensLeft));
|
||||||
|
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("response: " + response);
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
/*
|
||||||
|
* We don't want a hard dependency on Redis to allow traffic. Make sure to set
|
||||||
|
* an alert so you know if this is happening too much. Stripe's observed
|
||||||
|
* failure rate is 0.01%.
|
||||||
|
*/
|
||||||
|
log.error("Error determining if user allowed from redis", e);
|
||||||
|
}
|
||||||
|
return Mono.just(new Response(true, getHeaders(routeConfig, -1L)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Mono<Response> isAllowed(Config routeConfig, List<String> keys, int time, TimeUnit timeUnit) {
|
||||||
|
if (!this.initialized.get()) {
|
||||||
|
throw new IllegalStateException("RedisRateLimiter is not initialized");
|
||||||
|
}
|
||||||
|
|
||||||
|
// How many requests per second do you want a user to be allowed to do?
|
||||||
|
int replenishRate = routeConfig.getReplenishRate();
|
||||||
|
|
||||||
|
// How much bursting do you want to allow?
|
||||||
|
int burstCapacity = routeConfig.getBurstCapacity();
|
||||||
|
|
||||||
|
// How many tokens are requested per request?
|
||||||
|
int requestedTokens = routeConfig.getRequestedTokens();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// The arguments to the LUA script. time() returns unixtime in seconds.
|
||||||
|
List<String> scriptArgs = Arrays.asList(replenishRate + "", time + "");
|
||||||
|
// allowed, tokens_left = redis.eval(SCRIPT, keys, args)
|
||||||
|
Flux<Long> flux = this.redisTemplate.execute(this.timeRedisScript, keys, scriptArgs);
|
||||||
|
// .log("redisratelimiter", Level.FINER);
|
||||||
|
return flux.next().onErrorResume(throwable -> {
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("Error calling rate limiter lua", throwable);
|
||||||
|
}
|
||||||
|
return Mono.just(-1L);
|
||||||
|
}).map(tokensLeft -> {
|
||||||
|
boolean allowed = tokensLeft > 0 && tokensLeft < replenishRate;
|
||||||
|
Response response = new Response(allowed, getHeaders(routeConfig, tokensLeft, timeUnit));
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("response: " + response);
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
/*
|
||||||
|
* We don't want a hard dependency on Redis to allow traffic. Make sure to set
|
||||||
|
* an alert so you know if this is happening too much. Stripe's observed
|
||||||
|
* failure rate is 0.01%.
|
||||||
|
*/
|
||||||
|
log.error("Error determining if user allowed from redis", e);
|
||||||
|
}
|
||||||
|
return Mono.just(new Response(true, getHeaders(routeConfig, -1L, timeUnit)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getHeaders(Config config, Long tokensLeft, TimeUnit timeUnit) {
|
||||||
|
Map<String, String> headers = new HashMap<>();
|
||||||
|
if (isIncludeHeaders()) {
|
||||||
|
String suffix = StrUtil.upperFirst(timeUnit.name().toLowerCase());
|
||||||
|
headers.put(this.getRemainingHeader() + '-' + suffix, tokensLeft.toString());
|
||||||
|
headers.put(this.getReplenishRateHeader() + '-' + suffix, String.valueOf(config.getReplenishRate()));
|
||||||
|
}
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<String> getKeys(String id) {
|
||||||
|
// use `{}` around keys to use Redis Key hash tags
|
||||||
|
// this allows for using redis cluster
|
||||||
|
|
||||||
|
// Make a unique key per user.
|
||||||
|
String prefix = "rate_limiter.{" + id;
|
||||||
|
|
||||||
|
// You need two Redis keys for Token Bucket.
|
||||||
|
String tokenKey = prefix + "}.tokens";
|
||||||
|
String timestampKey = prefix + "}.timestamp";
|
||||||
|
return Arrays.asList(tokenKey, timestampKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
static List<String> getKeys(String id, int now, TimeUnit timeUnit) {
|
||||||
|
String tokenKey = "rate_limiter.{" + id + ':' + now + "}." + timeUnit.name();
|
||||||
|
return Arrays.asList(tokenKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,187 @@
|
|||||||
|
package com.ruoyi.gateway.utils;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
|
import cn.hutool.core.lang.Assert;
|
||||||
|
import cn.hutool.extra.spring.SpringUtil;
|
||||||
|
import com.ruoyi.gateway.utils.caching.CachingRule;
|
||||||
|
import com.ruoyi.isc.common.utils.beans.IscRule;
|
||||||
|
import org.redisson.api.RMap;
|
||||||
|
import org.redisson.api.RedissonClient;
|
||||||
|
import org.redisson.client.codec.Codec;
|
||||||
|
import org.redisson.codec.TypedJsonJacksonCodec;
|
||||||
|
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
|
||||||
|
import org.springframework.cloud.gateway.filter.factory.rewrite.CachedBodyOutputMessage;
|
||||||
|
import org.springframework.cloud.gateway.support.BodyInserterContext;
|
||||||
|
import org.springframework.core.io.buffer.DataBuffer;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.server.reactive.ServerHttpRequest;
|
||||||
|
import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.web.reactive.function.BodyInserter;
|
||||||
|
import org.springframework.web.reactive.function.BodyInserters;
|
||||||
|
import org.springframework.web.server.ServerWebExchange;
|
||||||
|
import reactor.core.publisher.Flux;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.sql.Date;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import static com.ruoyi.isc.common.constant.IscGatewayContants.RULE_CODES_INSTANCE;
|
||||||
|
import static com.ruoyi.isc.common.constant.IscRedisKeys.KEY_RULES;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-10-15
|
||||||
|
*/
|
||||||
|
public class GatewayUtils extends com.ruoyi.isc.common.utils.GatewayUtils {
|
||||||
|
private static RedissonClient client = SpringUtil.getBean(RedissonClient.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改请求Body
|
||||||
|
*
|
||||||
|
* @param exchange 当前服务交换器
|
||||||
|
* @param chain 当前过滤链
|
||||||
|
* @param publisher body体提供者
|
||||||
|
* @param newUri 新的URI(去掉AccessKey)
|
||||||
|
* @return 指示请求处理何时完成
|
||||||
|
*/
|
||||||
|
public static Mono<Void> modifyBody(ServerWebExchange exchange, GatewayFilterChain chain, Mono<String> publisher, URI newUri) {
|
||||||
|
BodyInserter bodyInserter = BodyInserters.fromPublisher(publisher, String.class);
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.putAll(exchange.getRequest().getHeaders());
|
||||||
|
headers.remove(HttpHeaders.CONTENT_LENGTH);
|
||||||
|
CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange, headers);
|
||||||
|
return bodyInserter.insert(outputMessage, new BodyInserterContext())
|
||||||
|
.then(Mono.defer(() -> {
|
||||||
|
ServerHttpRequest request = decorate(exchange, headers, outputMessage, newUri);
|
||||||
|
return chain.filter(exchange.mutate().request(request).build());
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static ServerHttpRequestDecorator decorate(ServerWebExchange exchange, HttpHeaders headers,
|
||||||
|
CachedBodyOutputMessage outputMessage, URI newUri) {
|
||||||
|
return new ServerHttpRequestDecorator(exchange.getRequest()) {
|
||||||
|
@Override
|
||||||
|
public HttpHeaders getHeaders() {
|
||||||
|
long contentLength = headers.getContentLength();
|
||||||
|
HttpHeaders httpHeaders = new HttpHeaders();
|
||||||
|
httpHeaders.putAll(super.getHeaders());
|
||||||
|
if (contentLength > 0L) {
|
||||||
|
httpHeaders.setContentLength(contentLength);
|
||||||
|
} else {
|
||||||
|
httpHeaders.set("Transfer-Encoding", "chunked");
|
||||||
|
}
|
||||||
|
return httpHeaders;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Flux<DataBuffer> getBody() {
|
||||||
|
return outputMessage.getBody();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public URI getURI()
|
||||||
|
{
|
||||||
|
return Objects.isNull(newUri) ? super.getURI() : newUri;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从 values 中获取第一个不为空 的值
|
||||||
|
*
|
||||||
|
* @param before 获取之前的值 如果不为空直接返回
|
||||||
|
* @param valueSupplier 值列表生产者
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getValue(String before, Supplier<List<String>> valueSupplier) {
|
||||||
|
return getValue(before, valueSupplier, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从 values 中获取第一个不为空 的值
|
||||||
|
*
|
||||||
|
* @param before 获取之前的值 如果不为空直接返回
|
||||||
|
* @param valueSupplier 值列表生产者
|
||||||
|
* @param errorMsgSupplier 异常信息生产者
|
||||||
|
* @param <X>
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static <X extends RuntimeException> String getValue(String before, Supplier<List<String>> valueSupplier,
|
||||||
|
Supplier<X> errorMsgSupplier) {
|
||||||
|
if (StringUtils.hasText(before)) {
|
||||||
|
return before;
|
||||||
|
}
|
||||||
|
final List<String> values = valueSupplier.get();
|
||||||
|
if (CollectionUtil.isNotEmpty(values)) {
|
||||||
|
for (String value : values) {
|
||||||
|
if (StringUtils.hasText(value)) {
|
||||||
|
before = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Objects.nonNull(errorMsgSupplier)) {
|
||||||
|
Assert.notBlank(before, errorMsgSupplier);
|
||||||
|
}
|
||||||
|
return before;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取必要值,可抛出异常
|
||||||
|
*
|
||||||
|
* @param valueSupplier
|
||||||
|
* @param errorMsgSupplier
|
||||||
|
* @param <T>
|
||||||
|
* @param <X>
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static <T, X extends RuntimeException> T getRequiredValue(Supplier<T> valueSupplier,
|
||||||
|
Supplier<X> errorMsgSupplier) {
|
||||||
|
final T value = valueSupplier.get();
|
||||||
|
if (Objects.nonNull(errorMsgSupplier)) {
|
||||||
|
Assert.notNull(value, errorMsgSupplier);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取规则
|
||||||
|
*
|
||||||
|
* @param ak AK
|
||||||
|
* @param routeId 路由ID
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static IscRule getRule(String ak, String routeId) {
|
||||||
|
String key = getRouteKey(ak, routeId);
|
||||||
|
return CachingRule.getRule(key, GatewayUtils::getRedisRule);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Redis Rule
|
||||||
|
* @param key
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static IscRule getRedisRule(String key) {
|
||||||
|
final RMap<String, IscRule> map = client.getMap(KEY_RULES, RULE_CODES_INSTANCE);
|
||||||
|
return map.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 断言是否超过结束时间
|
||||||
|
*
|
||||||
|
* @param rule
|
||||||
|
* @param errorMsgSupplier
|
||||||
|
* @param <X>
|
||||||
|
*/
|
||||||
|
public static <X extends RuntimeException> void isBefore(IscRule rule, Supplier<X> errorMsgSupplier) {
|
||||||
|
Assert.isTrue(Objects.nonNull(rule.getExpire()) && Date.from(Instant.now()).before(rule.getExpire()),
|
||||||
|
errorMsgSupplier);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,53 @@
|
|||||||
|
package com.ruoyi.gateway.utils.caching;
|
||||||
|
|
||||||
|
import com.ruoyi.isc.common.utils.beans.IscRule;
|
||||||
|
import org.springframework.cache.Cache;
|
||||||
|
import org.springframework.cache.concurrent.ConcurrentMapCache;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-10-22
|
||||||
|
*/
|
||||||
|
public class CachingRule {
|
||||||
|
public static final String RULE_CACHE_NAME = "RULE_CACHE";
|
||||||
|
public static final Cache RULE_CACHE = new ConcurrentMapCache(RULE_CACHE_NAME);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过 Key 获取缓存中的 Rule
|
||||||
|
*
|
||||||
|
* @param key 缓存key
|
||||||
|
* @param mapper 如果缓存中没有 key 从mapper 中获取
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static IscRule getRule(String key, Function<String, IscRule> mapper) {
|
||||||
|
Cache.ValueWrapper value = RULE_CACHE.get(key);
|
||||||
|
if (Objects.nonNull(value)) {
|
||||||
|
return (IscRule) value.get();
|
||||||
|
}
|
||||||
|
IscRule rule = mapper.apply(key);
|
||||||
|
RULE_CACHE.put(key, rule);
|
||||||
|
return rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清除 缓存 如果key存在
|
||||||
|
*
|
||||||
|
* @param key 缓存key
|
||||||
|
* @return 是否清除
|
||||||
|
*/
|
||||||
|
public static boolean evict(String key) {
|
||||||
|
return RULE_CACHE.evictIfPresent(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清除所有缓存 一刷新整个缓存
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean refresh() {
|
||||||
|
RULE_CACHE.clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,76 @@
|
|||||||
|
--- # 监控配置
|
||||||
|
spring:
|
||||||
|
boot:
|
||||||
|
admin:
|
||||||
|
# Spring Boot Admin Client 客户端的相关配置
|
||||||
|
client:
|
||||||
|
# 增加客户端开关
|
||||||
|
enabled: true
|
||||||
|
# 设置 Spring Boot Admin Server 地址
|
||||||
|
url: http://localhost:9090/admin
|
||||||
|
instance:
|
||||||
|
prefer-ip: true # 注册实例时,优先使用 IP
|
||||||
|
username: admin
|
||||||
|
password: admin123
|
||||||
|
|
||||||
|
--- # redis 配置
|
||||||
|
spring:
|
||||||
|
redis:
|
||||||
|
# 地址
|
||||||
|
host: 192.168.64.128
|
||||||
|
# 端口,默认为6379
|
||||||
|
port: 6379
|
||||||
|
# 数据库索引
|
||||||
|
database: 0
|
||||||
|
# 密码
|
||||||
|
password:
|
||||||
|
# 连接超时时间
|
||||||
|
timeout: 10s
|
||||||
|
# 是否开启ssl
|
||||||
|
ssl: false
|
||||||
|
|
||||||
|
redisson:
|
||||||
|
# 线程池数量
|
||||||
|
threads: 16
|
||||||
|
# Netty线程池数量
|
||||||
|
nettyThreads: 32
|
||||||
|
# 传输模式
|
||||||
|
transportMode: "NIO"
|
||||||
|
# 单节点配置
|
||||||
|
singleServerConfig:
|
||||||
|
# 客户端名称
|
||||||
|
clientName: ${ruoyi.name}
|
||||||
|
# 最小空闲连接数
|
||||||
|
connectionMinimumIdleSize: 32
|
||||||
|
# 连接池大小
|
||||||
|
connectionPoolSize: 64
|
||||||
|
# 连接空闲超时,单位:毫秒
|
||||||
|
idleConnectionTimeout: 10000
|
||||||
|
# 命令等待超时,单位:毫秒
|
||||||
|
timeout: 3000
|
||||||
|
# 如果尝试在此限制之内发送成功,则开始启用 timeout 计时。
|
||||||
|
retryAttempts: 3
|
||||||
|
# 命令重试发送时间间隔,单位:毫秒
|
||||||
|
retryInterval: 1500
|
||||||
|
# 发布和订阅连接的最小空闲连接数
|
||||||
|
subscriptionConnectionMinimumIdleSize: 1
|
||||||
|
# 发布和订阅连接池大小
|
||||||
|
subscriptionConnectionPoolSize: 50
|
||||||
|
# 单个连接最大订阅数量
|
||||||
|
subscriptionsPerConnection: 5
|
||||||
|
# DNS监测时间间隔,单位:毫秒
|
||||||
|
dnsMonitoringInterval: 5000
|
||||||
|
|
||||||
|
--- # Actuator 监控端点的配置项
|
||||||
|
management:
|
||||||
|
endpoints:
|
||||||
|
web:
|
||||||
|
# Actuator 提供的 API 接口的根目录。默认为 /actuator
|
||||||
|
base-path: /actuator
|
||||||
|
exposure:
|
||||||
|
# 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。
|
||||||
|
# 生产环境不建议放开所有 根据项目需求放开即可
|
||||||
|
include: @endpoints.include@
|
||||||
|
endpoint:
|
||||||
|
logfile:
|
||||||
|
external-file: ./logs/sys-console.log
|
||||||
@ -0,0 +1,76 @@
|
|||||||
|
--- # 监控配置
|
||||||
|
spring:
|
||||||
|
boot:
|
||||||
|
admin:
|
||||||
|
# Spring Boot Admin Client 客户端的相关配置
|
||||||
|
client:
|
||||||
|
# 增加客户端开关
|
||||||
|
enabled: true
|
||||||
|
# 设置 Spring Boot Admin Server 地址
|
||||||
|
url: http://localhost:9090/admin
|
||||||
|
instance:
|
||||||
|
prefer-ip: true # 注册实例时,优先使用 IP
|
||||||
|
username: admin
|
||||||
|
password: admin123
|
||||||
|
|
||||||
|
--- # redis 配置
|
||||||
|
spring:
|
||||||
|
redis:
|
||||||
|
# 地址
|
||||||
|
host: 127.0.0.1
|
||||||
|
# 端口,默认为6379
|
||||||
|
port: 6379
|
||||||
|
# 数据库索引
|
||||||
|
database: 11
|
||||||
|
# 密码
|
||||||
|
password:
|
||||||
|
# 连接超时时间
|
||||||
|
timeout: 10s
|
||||||
|
# 是否开启ssl
|
||||||
|
ssl: false
|
||||||
|
|
||||||
|
redisson:
|
||||||
|
# 线程池数量
|
||||||
|
threads: 16
|
||||||
|
# Netty线程池数量
|
||||||
|
nettyThreads: 32
|
||||||
|
# 传输模式
|
||||||
|
transportMode: "NIO"
|
||||||
|
# 单节点配置
|
||||||
|
singleServerConfig:
|
||||||
|
# 客户端名称
|
||||||
|
clientName: ${ruoyi.name}
|
||||||
|
# 最小空闲连接数
|
||||||
|
connectionMinimumIdleSize: 32
|
||||||
|
# 连接池大小
|
||||||
|
connectionPoolSize: 64
|
||||||
|
# 连接空闲超时,单位:毫秒
|
||||||
|
idleConnectionTimeout: 10000
|
||||||
|
# 命令等待超时,单位:毫秒
|
||||||
|
timeout: 3000
|
||||||
|
# 如果尝试在此限制之内发送成功,则开始启用 timeout 计时。
|
||||||
|
retryAttempts: 3
|
||||||
|
# 命令重试发送时间间隔,单位:毫秒
|
||||||
|
retryInterval: 1500
|
||||||
|
# 发布和订阅连接的最小空闲连接数
|
||||||
|
subscriptionConnectionMinimumIdleSize: 1
|
||||||
|
# 发布和订阅连接池大小
|
||||||
|
subscriptionConnectionPoolSize: 50
|
||||||
|
# 单个连接最大订阅数量
|
||||||
|
subscriptionsPerConnection: 5
|
||||||
|
# DNS监测时间间隔,单位:毫秒
|
||||||
|
dnsMonitoringInterval: 5000
|
||||||
|
|
||||||
|
--- # Actuator 监控端点的配置项
|
||||||
|
management:
|
||||||
|
endpoints:
|
||||||
|
web:
|
||||||
|
# Actuator 提供的 API 接口的根目录。默认为 /actuator
|
||||||
|
base-path: /actuator
|
||||||
|
exposure:
|
||||||
|
# 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。
|
||||||
|
# 生产环境不建议放开所有 根据项目需求放开即可
|
||||||
|
include: @endpoints.include@
|
||||||
|
endpoint:
|
||||||
|
logfile:
|
||||||
|
external-file: ./logs/sys-console.log
|
||||||
@ -0,0 +1,76 @@
|
|||||||
|
--- # 监控配置
|
||||||
|
spring:
|
||||||
|
boot:
|
||||||
|
admin:
|
||||||
|
# Spring Boot Admin Client 客户端的相关配置
|
||||||
|
client:
|
||||||
|
# 增加客户端开关
|
||||||
|
enabled: true
|
||||||
|
# 设置 Spring Boot Admin Server 地址
|
||||||
|
url: http://172.17.0.1:9090/admin
|
||||||
|
instance:
|
||||||
|
prefer-ip: true # 注册实例时,优先使用 IP
|
||||||
|
username: admin
|
||||||
|
password: admin@123456
|
||||||
|
|
||||||
|
--- # redis 配置
|
||||||
|
spring:
|
||||||
|
redis:
|
||||||
|
# 地址
|
||||||
|
host: 172.17.0.1
|
||||||
|
# 端口,默认为6379
|
||||||
|
port: 6379
|
||||||
|
# 数据库索引
|
||||||
|
database: 0
|
||||||
|
# 密码
|
||||||
|
password:
|
||||||
|
# 连接超时时间
|
||||||
|
timeout: 10s
|
||||||
|
# 是否开启ssl
|
||||||
|
ssl: false
|
||||||
|
|
||||||
|
redisson:
|
||||||
|
# 线程池数量
|
||||||
|
threads: 16
|
||||||
|
# Netty线程池数量
|
||||||
|
nettyThreads: 32
|
||||||
|
# 传输模式
|
||||||
|
transportMode: "NIO"
|
||||||
|
# 单节点配置
|
||||||
|
singleServerConfig:
|
||||||
|
# 客户端名称
|
||||||
|
clientName: ${ruoyi.name}
|
||||||
|
# 最小空闲连接数
|
||||||
|
connectionMinimumIdleSize: 32
|
||||||
|
# 连接池大小
|
||||||
|
connectionPoolSize: 64
|
||||||
|
# 连接空闲超时,单位:毫秒
|
||||||
|
idleConnectionTimeout: 10000
|
||||||
|
# 命令等待超时,单位:毫秒
|
||||||
|
timeout: 3000
|
||||||
|
# 如果尝试在此限制之内发送成功,则开始启用 timeout 计时。
|
||||||
|
retryAttempts: 3
|
||||||
|
# 命令重试发送时间间隔,单位:毫秒
|
||||||
|
retryInterval: 1500
|
||||||
|
# 发布和订阅连接的最小空闲连接数
|
||||||
|
subscriptionConnectionMinimumIdleSize: 1
|
||||||
|
# 发布和订阅连接池大小
|
||||||
|
subscriptionConnectionPoolSize: 50
|
||||||
|
# 单个连接最大订阅数量
|
||||||
|
subscriptionsPerConnection: 5
|
||||||
|
# DNS监测时间间隔,单位:毫秒
|
||||||
|
dnsMonitoringInterval: 5000
|
||||||
|
|
||||||
|
--- # Actuator 监控端点的配置项
|
||||||
|
management:
|
||||||
|
endpoints:
|
||||||
|
web:
|
||||||
|
# Actuator 提供的 API 接口的根目录。默认为 /actuator
|
||||||
|
base-path: /actuator
|
||||||
|
exposure:
|
||||||
|
# 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。
|
||||||
|
# 生产环境不建议放开所有 根据项目需求放开即可
|
||||||
|
include: @endpoints.include@
|
||||||
|
endpoint:
|
||||||
|
logfile:
|
||||||
|
external-file: ./logs/sys-console.log
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
# 项目相关配置
|
||||||
|
ruoyi:
|
||||||
|
# 名称
|
||||||
|
name: RuoYi-Vue-Plus
|
||||||
|
# 版本
|
||||||
|
version: ${ruoyi-vue-plus.version}
|
||||||
|
# 版权年份
|
||||||
|
copyrightYear: 2021
|
||||||
|
# 实例演示开关
|
||||||
|
demoEnabled: true
|
||||||
|
# 获取ip地址开关
|
||||||
|
addressEnabled: true
|
||||||
|
server:
|
||||||
|
port: 8090
|
||||||
|
# Spring配置
|
||||||
|
spring:
|
||||||
|
application:
|
||||||
|
name: RuoYi-Gateway
|
||||||
|
profiles:
|
||||||
|
active: @profiles.active@
|
||||||
114
ruoyi-extend/ruoyi-isc-gateway/src/main/resources/logback.xml
Normal file
114
ruoyi-extend/ruoyi-isc-gateway/src/main/resources/logback.xml
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
<property name="log.path" value="./logs"/>
|
||||||
|
<property name="console.log.pattern"
|
||||||
|
value="%red(%d{yyyy-MM-dd HH:mm:ss}) %highlight(%-5level) %green([%thread]) %boldMagenta(%logger{36}) - %msg%n"/>
|
||||||
|
<property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger{36} - %msg%n"/>
|
||||||
|
|
||||||
|
<!-- 控制台输出 -->
|
||||||
|
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>${console.log.pattern}</pattern>
|
||||||
|
<charset>utf-8</charset>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<!-- 控制台输出 -->
|
||||||
|
<appender name="file_console" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<file>${log.path}/sys-console.log</file>
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||||
|
<!-- 日志文件名格式 -->
|
||||||
|
<fileNamePattern>${log.path}/sys-console.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||||
|
<!-- 日志最大 1天 -->
|
||||||
|
<maxHistory>1</maxHistory>
|
||||||
|
</rollingPolicy>
|
||||||
|
<encoder>
|
||||||
|
<pattern>${log.pattern}</pattern>
|
||||||
|
<charset>utf-8</charset>
|
||||||
|
</encoder>
|
||||||
|
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||||
|
<!-- 过滤的级别 -->
|
||||||
|
<level>INFO</level>
|
||||||
|
</filter>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<!-- 系统日志输出 -->
|
||||||
|
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<file>${log.path}/sys-info.log</file>
|
||||||
|
<!-- 循环政策:基于时间创建日志文件 -->
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||||
|
<!-- 日志文件名格式 -->
|
||||||
|
<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||||
|
<!-- 日志最大的历史 60天 -->
|
||||||
|
<maxHistory>60</maxHistory>
|
||||||
|
</rollingPolicy>
|
||||||
|
<encoder>
|
||||||
|
<pattern>${log.pattern}</pattern>
|
||||||
|
</encoder>
|
||||||
|
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||||
|
<!-- 过滤的级别 -->
|
||||||
|
<level>INFO</level>
|
||||||
|
<!-- 匹配时的操作:接收(记录) -->
|
||||||
|
<onMatch>ACCEPT</onMatch>
|
||||||
|
<!-- 不匹配时的操作:拒绝(不记录) -->
|
||||||
|
<onMismatch>DENY</onMismatch>
|
||||||
|
</filter>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<file>${log.path}/sys-error.log</file>
|
||||||
|
<!-- 循环政策:基于时间创建日志文件 -->
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||||
|
<!-- 日志文件名格式 -->
|
||||||
|
<fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||||
|
<!-- 日志最大的历史 60天 -->
|
||||||
|
<maxHistory>60</maxHistory>
|
||||||
|
</rollingPolicy>
|
||||||
|
<encoder>
|
||||||
|
<pattern>${log.pattern}</pattern>
|
||||||
|
</encoder>
|
||||||
|
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||||
|
<!-- 过滤的级别 -->
|
||||||
|
<level>ERROR</level>
|
||||||
|
<!-- 匹配时的操作:接收(记录) -->
|
||||||
|
<onMatch>ACCEPT</onMatch>
|
||||||
|
<!-- 不匹配时的操作:拒绝(不记录) -->
|
||||||
|
<onMismatch>DENY</onMismatch>
|
||||||
|
</filter>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<!-- 用户访问日志输出 -->
|
||||||
|
<appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<file>${log.path}/sys-user.log</file>
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||||
|
<!-- 按天回滚 daily -->
|
||||||
|
<fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
|
||||||
|
<!-- 日志最大的历史 60天 -->
|
||||||
|
<maxHistory>60</maxHistory>
|
||||||
|
</rollingPolicy>
|
||||||
|
<encoder>
|
||||||
|
<pattern>${log.pattern}</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<!-- 系统模块日志级别控制 -->
|
||||||
|
<logger name="com.ruoyi" level="info" />
|
||||||
|
<!-- Spring日志级别控制 -->
|
||||||
|
<logger name="org.springframework" level="warn" />
|
||||||
|
|
||||||
|
<root level="info">
|
||||||
|
<appender-ref ref="console" />
|
||||||
|
</root>
|
||||||
|
|
||||||
|
<!--系统操作日志-->
|
||||||
|
<root level="info">
|
||||||
|
<appender-ref ref="file_info" />
|
||||||
|
<appender-ref ref="file_error" />
|
||||||
|
<appender-ref ref="file_console" />
|
||||||
|
</root>
|
||||||
|
|
||||||
|
<!--系统用户操作日志-->
|
||||||
|
<logger name="sys-user" level="info">
|
||||||
|
<appender-ref ref="sys-user"/>
|
||||||
|
</logger>
|
||||||
|
</configuration>
|
||||||
@ -28,6 +28,22 @@
|
|||||||
<groupId>de.codecentric</groupId>
|
<groupId>de.codecentric</groupId>
|
||||||
<artifactId>spring-boot-admin-starter-server</artifactId>
|
<artifactId>spring-boot-admin-starter-server</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-jdbc</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>mysql</groupId>
|
||||||
|
<artifactId>mysql-connector-java</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 阿里数据库连接池 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>druid-spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@ -1,13 +1,19 @@
|
|||||||
package com.ruoyi.monitor.admin.config;
|
package com.ruoyi.monitor.admin.config;
|
||||||
|
|
||||||
import de.codecentric.boot.admin.server.config.AdminServerProperties;
|
import de.codecentric.boot.admin.server.config.AdminServerProperties;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl;
|
||||||
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
|
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
|
||||||
|
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* admin 监控 安全配置
|
* admin 监控 安全配置
|
||||||
*
|
*
|
||||||
@ -45,4 +51,20 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
|||||||
.headers().frameOptions().disable();
|
.headers().frameOptions().disable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public UserDetailsService userDetailsService(DataSource dataSource) {
|
||||||
|
JdbcDaoImpl service = new JdbcDaoImpl();
|
||||||
|
service.setDataSource(dataSource);
|
||||||
|
return service;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 强散列哈希加密实现
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public BCryptPasswordEncoder bCryptPasswordEncoder()
|
||||||
|
{
|
||||||
|
return new BCryptPasswordEncoder();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,7 @@
|
|||||||
|
spring:
|
||||||
|
datasource:
|
||||||
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
|
type: com.alibaba.druid.pool.DruidDataSource
|
||||||
|
url: jdbc:mysql://192.168.64.128:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true
|
||||||
|
username: root
|
||||||
|
password: root
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
spring:
|
||||||
|
datasource:
|
||||||
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
|
type: com.alibaba.druid.pool.DruidDataSource
|
||||||
|
url: jdbc:mysql://127.0.0.1:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true
|
||||||
|
username: root
|
||||||
|
password: root
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
spring:
|
||||||
|
datasource:
|
||||||
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
|
type: com.alibaba.druid.pool.DruidDataSource
|
||||||
|
url: jdbc:mysql://172.17.0.1:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&autoReconnect=true
|
||||||
|
username: root
|
||||||
|
password: root
|
||||||
@ -1,11 +1,8 @@
|
|||||||
server:
|
server:
|
||||||
port: 9090
|
port: 9090
|
||||||
|
|
||||||
spring:
|
spring:
|
||||||
security:
|
|
||||||
user:
|
|
||||||
name: ruoyi
|
|
||||||
password: 123456
|
|
||||||
boot:
|
boot:
|
||||||
admin:
|
admin:
|
||||||
context-path: /admin
|
context-path: /admin
|
||||||
|
profiles:
|
||||||
|
active: @profiles.active@
|
||||||
@ -3,12 +3,12 @@ spring:
|
|||||||
datasource:
|
datasource:
|
||||||
type: com.zaxxer.hikari.HikariDataSource
|
type: com.zaxxer.hikari.HikariDataSource
|
||||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
url: jdbc:mysql://localhost:3306/ry-vue?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
|
url: jdbc:mysql://192.168.64.128:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true
|
||||||
username: root
|
username: root
|
||||||
password: root
|
password: root
|
||||||
hikari:
|
hikari:
|
||||||
auto-commit: true
|
auto-commit: true
|
||||||
connection-test-query: SELECT 1
|
connection-test-query: SELECT 1 FROM DUAL
|
||||||
connection-timeout: 10000
|
connection-timeout: 10000
|
||||||
idle-timeout: 30000
|
idle-timeout: 30000
|
||||||
max-lifetime: 900000
|
max-lifetime: 900000
|
||||||
|
|||||||
@ -0,0 +1,36 @@
|
|||||||
|
--- # 数据库配置
|
||||||
|
spring:
|
||||||
|
datasource:
|
||||||
|
type: com.zaxxer.hikari.HikariDataSource
|
||||||
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
|
url: jdbc:mysql://127.0.0.1:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true
|
||||||
|
username: root
|
||||||
|
password: root
|
||||||
|
hikari:
|
||||||
|
auto-commit: true
|
||||||
|
connection-test-query: SELECT 1 FROM DUAL
|
||||||
|
connection-timeout: 10000
|
||||||
|
idle-timeout: 30000
|
||||||
|
max-lifetime: 900000
|
||||||
|
maximum-pool-size: 30
|
||||||
|
minimum-idle: 10
|
||||||
|
pool-name: HikariCP
|
||||||
|
validation-timeout: 1000
|
||||||
|
|
||||||
|
--- # 邮件配置
|
||||||
|
spring:
|
||||||
|
mail:
|
||||||
|
from: xxx@qq.com
|
||||||
|
host: smtp.qq.com
|
||||||
|
username: xxx@qq.com
|
||||||
|
password: xxx
|
||||||
|
port: 25
|
||||||
|
properties:
|
||||||
|
mail:
|
||||||
|
smtp:
|
||||||
|
auth: true
|
||||||
|
socketFactory:
|
||||||
|
class: javax.net.ssl.SSLSocketFactory
|
||||||
|
starttls:
|
||||||
|
enable: true
|
||||||
|
required: true
|
||||||
@ -3,12 +3,12 @@ spring:
|
|||||||
datasource:
|
datasource:
|
||||||
type: com.zaxxer.hikari.HikariDataSource
|
type: com.zaxxer.hikari.HikariDataSource
|
||||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
url: jdbc:mysql://172.30.0.92:3306/ry-vue?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
|
url: jdbc:mysql://172.17.0.1:3306/ry-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&autoReconnect=true
|
||||||
username: root
|
username: root
|
||||||
password: root
|
password: root
|
||||||
hikari:
|
hikari:
|
||||||
auto-commit: true
|
auto-commit: true
|
||||||
connection-test-query: SELECT 1
|
connection-test-query: SELECT 1 FROM DUAL
|
||||||
connection-timeout: 10000
|
connection-timeout: 10000
|
||||||
idle-timeout: 30000
|
idle-timeout: 30000
|
||||||
max-lifetime: 900000
|
max-lifetime: 900000
|
||||||
|
|||||||
@ -18,43 +18,43 @@ import java.util.List;
|
|||||||
* @date ${datetime}
|
* @date ${datetime}
|
||||||
*/
|
*/
|
||||||
public interface I${ClassName}Service extends IServicePlus<${ClassName}, ${ClassName}Vo> {
|
public interface I${ClassName}Service extends IServicePlus<${ClassName}, ${ClassName}Vo> {
|
||||||
/**
|
/**
|
||||||
* 查询单个
|
* 查询单个
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
${ClassName}Vo queryById(${pkColumn.javaType} ${pkColumn.javaField});
|
${ClassName}Vo queryById(${pkColumn.javaType} ${pkColumn.javaField});
|
||||||
|
|
||||||
#if($table.crud || $table.sub)
|
#if($table.crud || $table.sub)
|
||||||
/**
|
/**
|
||||||
* 查询列表
|
* 查询列表
|
||||||
*/
|
*/
|
||||||
TableDataInfo<${ClassName}Vo> queryPageList(${ClassName}Bo bo);
|
TableDataInfo<${ClassName}Vo> queryPageList(${ClassName}Bo bo);
|
||||||
#end
|
#end
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询列表
|
* 查询列表
|
||||||
*/
|
*/
|
||||||
List<${ClassName}Vo> queryList(${ClassName}Bo bo);
|
List<${ClassName}Vo> queryList(${ClassName}Bo bo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据新增业务对象插入${functionName}
|
* 根据新增业务对象插入${functionName}
|
||||||
* @param bo ${functionName}新增业务对象
|
* @param bo ${functionName}新增业务对象
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
Boolean insertByBo(${ClassName}Bo bo);
|
Boolean insertByBo(${ClassName}Bo bo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据编辑业务对象修改${functionName}
|
* 根据编辑业务对象修改${functionName}
|
||||||
* @param bo ${functionName}编辑业务对象
|
* @param bo ${functionName}编辑业务对象
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
Boolean updateByBo(${ClassName}Bo bo);
|
Boolean updateByBo(${ClassName}Bo bo);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验并删除数据
|
* 校验并删除数据
|
||||||
* @param ids 主键集合
|
* @param ids 主键集合
|
||||||
* @param isValid 是否校验,true-删除前校验,false-不校验
|
* @param isValid 是否校验,true-删除前校验,false-不校验
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
Boolean deleteWithValidByIds(Collection<${pkColumn.javaType}> ids, Boolean isValid);
|
Boolean deleteWithValidByIds(Collection<${pkColumn.javaType}> ids, Boolean isValid);
|
||||||
}
|
}
|
||||||
|
|||||||
33
ruoyi-isc-parent/pom.xml
Normal file
33
ruoyi-isc-parent/pom.xml
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>ruoyi-vue-plus</artifactId>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<version>3.3.0</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>ruoyi-isc-parent</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<modules>
|
||||||
|
<module>ruoyi-isc-common</module>
|
||||||
|
<module>ruoyi-isc</module>
|
||||||
|
</modules>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<artifactId>ruoyi-isc-common</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<artifactId>ruoyi-isc</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
</project>
|
||||||
30
ruoyi-isc-parent/ruoyi-isc-common/pom.xml
Normal file
30
ruoyi-isc-parent/ruoyi-isc-common/pom.xml
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>ruoyi-isc-parent</artifactId>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<version>3.3.0</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>ruoyi-isc-common</artifactId>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-annotations</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.redisson</groupId>
|
||||||
|
<artifactId>redisson</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
package com.ruoyi.isc.common.constant;
|
||||||
|
|
||||||
|
import com.ruoyi.isc.common.utils.beans.IscRule;
|
||||||
|
import org.redisson.client.codec.Codec;
|
||||||
|
import org.redisson.codec.TypedJsonJacksonCodec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Isc Gateway 公共常量
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-10-30
|
||||||
|
*/
|
||||||
|
public interface IscGatewayContants {
|
||||||
|
|
||||||
|
/** AccessKey 默认名称 */
|
||||||
|
String ACCESS_KEY_NAME_DEFAULT = "ak";
|
||||||
|
|
||||||
|
/** 路由刷新通知主题 */
|
||||||
|
String TOPIC_GATEWAY_REFRESH_ROUTE = "TOPIC_GATEWAY_REFRESH_ROUTE";
|
||||||
|
|
||||||
|
/** 规则刷新通知主题 */
|
||||||
|
String TOPIC_GATEWAY_RULE = "TOPIC_GATEWAY_RULE";
|
||||||
|
|
||||||
|
/** AccessKeyName 路由配置名称 */
|
||||||
|
String CONFIG_ACCESS_KEY_NAME_KEY = "accessKeyName";
|
||||||
|
|
||||||
|
/** 添加参数 路由配置名称 */
|
||||||
|
String CONFIG_ADD_PARAM_KEY = "addParam";
|
||||||
|
|
||||||
|
/** 规则编解码器 */
|
||||||
|
Codec RULE_CODES_INSTANCE = new TypedJsonJacksonCodec(String.class, IscRule.class);
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
package com.ruoyi.isc.common.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redis Keys
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-10-30
|
||||||
|
*/
|
||||||
|
public interface IscRedisKeys {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gateway 路由信息Redis Key
|
||||||
|
*/
|
||||||
|
String KEY_ROUTES = "ROUTES:";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gateway 服务对应AK规则
|
||||||
|
*/
|
||||||
|
String KEY_RULES = "RULES:";
|
||||||
|
}
|
||||||
@ -0,0 +1,30 @@
|
|||||||
|
package com.ruoyi.isc.common.utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-10-30
|
||||||
|
*/
|
||||||
|
public class GatewayUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 路由Key
|
||||||
|
*
|
||||||
|
* @param ak AccessKey
|
||||||
|
* @param serviceId 服务ID
|
||||||
|
* @return 路由Key
|
||||||
|
*/
|
||||||
|
public static String getRouteKey(String ak, String serviceId) {
|
||||||
|
return ak + ':' + serviceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取 路由Key
|
||||||
|
*
|
||||||
|
* @param ak AccessKey
|
||||||
|
* @param serviceId 服务ID
|
||||||
|
* @return 路由Key
|
||||||
|
*/
|
||||||
|
public static String getRouteKey(String ak, Long serviceId) {
|
||||||
|
return getRouteKey(ak, String.valueOf(serviceId));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
package com.ruoyi.isc.common.utils.beans;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网关 规则信息(服务对应AK处理规则)
|
||||||
|
* @author Wechao Gong
|
||||||
|
* @date 2021-10-16
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class IscRule implements Serializable
|
||||||
|
{
|
||||||
|
@JsonIgnore
|
||||||
|
private String id;
|
||||||
|
private Date expire;
|
||||||
|
private Long daysLimit;
|
||||||
|
private Long hoursLimit;
|
||||||
|
private Long minutesLimit;
|
||||||
|
private Long secondsLimit;
|
||||||
|
}
|
||||||
@ -0,0 +1,37 @@
|
|||||||
|
package com.ruoyi.isc.common.utils.beans;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-10-26
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class TopicMsg implements Serializable {
|
||||||
|
/** 消息ID */
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
/** 消息内容 */
|
||||||
|
private String msg;
|
||||||
|
|
||||||
|
/** 消息类型 */
|
||||||
|
private Type type;
|
||||||
|
|
||||||
|
/** 消息类型枚举 */
|
||||||
|
public static enum Type {
|
||||||
|
/** 新增单条记录 */
|
||||||
|
ADD,
|
||||||
|
/** 更新单条记录 */
|
||||||
|
UPDATE,
|
||||||
|
/** 删除单条记录 */
|
||||||
|
DELETE,
|
||||||
|
/** 刷新所有 */
|
||||||
|
REFRESH
|
||||||
|
}
|
||||||
|
}
|
||||||
25
ruoyi-isc-parent/ruoyi-isc/pom.xml
Normal file
25
ruoyi-isc-parent/ruoyi-isc/pom.xml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>ruoyi-isc-parent</artifactId>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<version>3.3.0</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>ruoyi-isc</artifactId>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<artifactId>ruoyi-isc-common</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<artifactId>ruoyi-system</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
@ -0,0 +1,87 @@
|
|||||||
|
package com.ruoyi.isc.controller;
|
||||||
|
|
||||||
|
import com.ruoyi.common.annotation.Log;
|
||||||
|
import com.ruoyi.common.annotation.RepeatSubmit;
|
||||||
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
|
import com.ruoyi.common.core.domain.AjaxResult;
|
||||||
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
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.isc.domain.bo.IscAppServiceApplyBo;
|
||||||
|
import com.ruoyi.isc.domain.bo.IscAuditBo;
|
||||||
|
import com.ruoyi.isc.domain.vo.IscAppServiceApplyVo;
|
||||||
|
import com.ruoyi.isc.service.IIscAppServiceApplyService;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用服务申请信息Controller
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-09-09
|
||||||
|
*/
|
||||||
|
@Validated
|
||||||
|
@Api(value = "应用服务申请信息控制器", tags = {"应用服务申请信息管理"})
|
||||||
|
@RequiredArgsConstructor(onConstructor_ = @Autowired)
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/isc/serviceapply")
|
||||||
|
public class IscAppServiceApplyController extends BaseController {
|
||||||
|
|
||||||
|
private final IIscAppServiceApplyService iIscAppServiceApplyService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询应用服务申请信息列表
|
||||||
|
*/
|
||||||
|
@ApiOperation("查询应用服务申请信息列表")
|
||||||
|
@PreAuthorize("@ss.hasPermi('isc:serviceapply:list')")
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo<IscAppServiceApplyVo> list(@Validated(QueryGroup.class) IscAppServiceApplyBo bo) {
|
||||||
|
return iIscAppServiceApplyService.queryPageList(bo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出应用服务申请信息列表
|
||||||
|
*/
|
||||||
|
@ApiOperation("导出应用服务申请信息列表")
|
||||||
|
@PreAuthorize("@ss.hasPermi('isc:serviceapply:export')")
|
||||||
|
@Log(title = "应用服务申请信息", businessType = BusinessType.EXPORT)
|
||||||
|
@GetMapping("/export")
|
||||||
|
public void export(@Validated IscAppServiceApplyBo bo, HttpServletResponse response) {
|
||||||
|
List<IscAppServiceApplyVo> list = iIscAppServiceApplyService.queryList(bo);
|
||||||
|
ExcelUtil.exportExcel(list, "应用服务申请信息", IscAppServiceApplyVo.class, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取应用服务申请信息详细信息
|
||||||
|
*/
|
||||||
|
@ApiOperation("获取应用服务申请信息详细信息")
|
||||||
|
@PreAuthorize("@ss.hasPermi('isc:serviceapply:query')")
|
||||||
|
@GetMapping("/{applyId}")
|
||||||
|
public AjaxResult<IscAppServiceApplyVo> getInfo(@NotNull(message = "主键不能为空")
|
||||||
|
@PathVariable("applyId") Long applyId) {
|
||||||
|
return AjaxResult.success(iIscAppServiceApplyService.queryById(applyId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用服务申请信息审核
|
||||||
|
*/
|
||||||
|
@ApiOperation("应用服务申请信息审核")
|
||||||
|
@PreAuthorize("@ss.hasPermi('isc:serviceapply:audit')")
|
||||||
|
@Log(title = "应用服务申请信息审核", businessType = BusinessType.AUDIT)
|
||||||
|
@RepeatSubmit()
|
||||||
|
@PutMapping("/audit")
|
||||||
|
public AjaxResult<Void> audit(@Validated @RequestBody IscAuditBo bo) {
|
||||||
|
return toAjax(iIscAppServiceApplyService.audit(bo) ? 1 : 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,124 @@
|
|||||||
|
package com.ruoyi.isc.controller;
|
||||||
|
|
||||||
|
import cn.hutool.core.lang.tree.Tree;
|
||||||
|
import com.ruoyi.common.annotation.Log;
|
||||||
|
import com.ruoyi.common.annotation.RepeatSubmit;
|
||||||
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
|
import com.ruoyi.common.core.domain.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.isc.domain.bo.IscAppServiceBo;
|
||||||
|
import com.ruoyi.isc.domain.vo.IscAppServiceVo;
|
||||||
|
import com.ruoyi.isc.service.IIscAppServiceService;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用服务Controller
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-09-08
|
||||||
|
*/
|
||||||
|
@Validated
|
||||||
|
@Api(value = "应用服务控制器", tags = {"应用服务管理"})
|
||||||
|
@RequiredArgsConstructor(onConstructor_ = @Autowired)
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/isc/appservice")
|
||||||
|
public class IscAppServiceController extends BaseController {
|
||||||
|
|
||||||
|
private final IIscAppServiceService appServiceService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询应用服务列表
|
||||||
|
*/
|
||||||
|
@ApiOperation("查询应用服务列表")
|
||||||
|
@PreAuthorize("@ss.hasPermi('isc:appservice:list')")
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo<IscAppServiceVo> list(@Validated(QueryGroup.class) IscAppServiceBo bo) {
|
||||||
|
return appServiceService.queryPageList(bo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出应用服务列表
|
||||||
|
*/
|
||||||
|
@ApiOperation("导出应用服务列表")
|
||||||
|
@PreAuthorize("@ss.hasPermi('isc:appservice:export')")
|
||||||
|
@Log(title = "应用服务", businessType = BusinessType.EXPORT)
|
||||||
|
@GetMapping("/export")
|
||||||
|
public void export(@Validated IscAppServiceBo bo, HttpServletResponse response) {
|
||||||
|
List<IscAppServiceVo> list = appServiceService.queryList(bo);
|
||||||
|
ExcelUtil.exportExcel(list, "应用服务", IscAppServiceVo.class, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取应用服务详细信息
|
||||||
|
*/
|
||||||
|
@ApiOperation("获取应用服务详细信息")
|
||||||
|
@PreAuthorize("@ss.hasPermi('isc:appservice:query')")
|
||||||
|
@GetMapping("/{appServiceId}")
|
||||||
|
public AjaxResult<IscAppServiceVo> getInfo(@NotNull(message = "主键不能为空")
|
||||||
|
@PathVariable("appServiceId") Long appServiceId) {
|
||||||
|
return AjaxResult.success(appServiceService.queryById(appServiceId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增应用服务
|
||||||
|
*/
|
||||||
|
@ApiOperation("新增应用服务")
|
||||||
|
@PreAuthorize("@ss.hasPermi('isc:appservice:add')")
|
||||||
|
@Log(title = "应用服务", businessType = BusinessType.INSERT)
|
||||||
|
@RepeatSubmit()
|
||||||
|
@PostMapping()
|
||||||
|
public AjaxResult<Void> add(@Validated(AddGroup.class) @RequestBody IscAppServiceBo bo) {
|
||||||
|
return toAjax(appServiceService.insertByBo(bo) ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改应用服务
|
||||||
|
*/
|
||||||
|
@ApiOperation("修改应用服务")
|
||||||
|
@PreAuthorize("@ss.hasPermi('isc:appservice:edit')")
|
||||||
|
@Log(title = "应用服务", businessType = BusinessType.UPDATE)
|
||||||
|
@RepeatSubmit()
|
||||||
|
@PutMapping()
|
||||||
|
public AjaxResult<Void> edit(@Validated(EditGroup.class) @RequestBody IscAppServiceBo bo) {
|
||||||
|
return toAjax(appServiceService.updateByBo(bo) ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除应用服务
|
||||||
|
*/
|
||||||
|
@ApiOperation("删除应用服务")
|
||||||
|
@PreAuthorize("@ss.hasPermi('isc:appservice:remove')")
|
||||||
|
@Log(title = "应用服务" , businessType = BusinessType.DELETE)
|
||||||
|
@DeleteMapping("/{appServiceIds}")
|
||||||
|
public AjaxResult<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||||
|
@PathVariable Long[] appServiceIds) {
|
||||||
|
return toAjax(appServiceService.deleteWithValidByIds(Arrays.asList(appServiceIds), true) ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取应用服务下拉树列表
|
||||||
|
*/
|
||||||
|
@GetMapping("/treeselect/{applicationId}")
|
||||||
|
@ApiOperation("获取应用服务下拉树列表")
|
||||||
|
public AjaxResult<List<Tree<Long>>> treeselect(@NotNull(message = "应用主键不能为空") @PathVariable Long applicationId)
|
||||||
|
{
|
||||||
|
return AjaxResult.success(appServiceService.genAppServiceTree(applicationId));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,113 @@
|
|||||||
|
package com.ruoyi.isc.controller;
|
||||||
|
|
||||||
|
import com.ruoyi.common.annotation.Log;
|
||||||
|
import com.ruoyi.common.annotation.RepeatSubmit;
|
||||||
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
|
import com.ruoyi.common.core.domain.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.isc.domain.bo.IscApplicationBo;
|
||||||
|
import com.ruoyi.isc.domain.vo.IscApplicationVo;
|
||||||
|
import com.ruoyi.isc.service.IIscApplicationService;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用信息Controller
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-09-08
|
||||||
|
*/
|
||||||
|
@Validated
|
||||||
|
@Api(value = "应用信息控制器", tags = {"应用信息管理"})
|
||||||
|
@RequiredArgsConstructor(onConstructor_ = @Autowired)
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/isc/application")
|
||||||
|
public class IscApplicationController extends BaseController {
|
||||||
|
|
||||||
|
private final IIscApplicationService iIscApplicationService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询应用信息列表
|
||||||
|
*/
|
||||||
|
@ApiOperation("查询应用信息列表")
|
||||||
|
@PreAuthorize("@ss.hasPermi('isc:application:list')")
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo<IscApplicationVo> list(@Validated(QueryGroup.class) IscApplicationBo bo) {
|
||||||
|
return iIscApplicationService.queryPageList(bo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出应用信息列表
|
||||||
|
*/
|
||||||
|
@ApiOperation("导出应用信息列表")
|
||||||
|
@PreAuthorize("@ss.hasPermi('isc:application:export')")
|
||||||
|
@Log(title = "应用信息", businessType = BusinessType.EXPORT)
|
||||||
|
@GetMapping("/export")
|
||||||
|
public void export(@Validated IscApplicationBo bo, HttpServletResponse response) {
|
||||||
|
List<IscApplicationVo> list = iIscApplicationService.queryList(bo);
|
||||||
|
ExcelUtil.exportExcel(list, "应用信息", IscApplicationVo.class, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取应用信息详细信息
|
||||||
|
*/
|
||||||
|
@ApiOperation("获取应用信息详细信息")
|
||||||
|
@PreAuthorize("@ss.hasPermi('isc:application:query')")
|
||||||
|
@GetMapping("/{applicationId}")
|
||||||
|
public AjaxResult<IscApplicationVo> getInfo(@NotNull(message = "主键不能为空")
|
||||||
|
@PathVariable("applicationId") Long applicationId) {
|
||||||
|
return AjaxResult.success(iIscApplicationService.queryById(applicationId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增应用信息
|
||||||
|
*/
|
||||||
|
@ApiOperation("新增应用信息")
|
||||||
|
@PreAuthorize("@ss.hasPermi('isc:application:add')")
|
||||||
|
@Log(title = "应用信息", businessType = BusinessType.INSERT)
|
||||||
|
@RepeatSubmit()
|
||||||
|
@PostMapping()
|
||||||
|
public AjaxResult<Void> add(@Validated(AddGroup.class) @RequestBody IscApplicationBo bo) {
|
||||||
|
return toAjax(iIscApplicationService.insertByBo(bo) ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改应用信息
|
||||||
|
*/
|
||||||
|
@ApiOperation("修改应用信息")
|
||||||
|
@PreAuthorize("@ss.hasPermi('isc:application:edit')")
|
||||||
|
@Log(title = "应用信息", businessType = BusinessType.UPDATE)
|
||||||
|
@RepeatSubmit()
|
||||||
|
@PutMapping()
|
||||||
|
public AjaxResult<Void> edit(@Validated(EditGroup.class) @RequestBody IscApplicationBo bo) {
|
||||||
|
return toAjax(iIscApplicationService.updateByBo(bo) ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除应用信息
|
||||||
|
*/
|
||||||
|
@ApiOperation("删除应用信息")
|
||||||
|
@PreAuthorize("@ss.hasPermi('isc:application:remove')")
|
||||||
|
@Log(title = "应用信息" , businessType = BusinessType.DELETE)
|
||||||
|
@DeleteMapping("/{applicationIds}")
|
||||||
|
public AjaxResult<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||||
|
@PathVariable Long[] applicationIds) {
|
||||||
|
return toAjax(iIscApplicationService.deleteWithValidByIds(Arrays.asList(applicationIds), true) ? 1 : 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,135 @@
|
|||||||
|
package com.ruoyi.isc.controller;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import cn.hutool.core.lang.tree.Tree;
|
||||||
|
import cn.hutool.core.lang.tree.TreeUtil;
|
||||||
|
import cn.hutool.core.lang.tree.parser.NodeParser;
|
||||||
|
import com.ruoyi.common.core.domain.entity.SysMenu;
|
||||||
|
import com.ruoyi.common.utils.TreeUtils;
|
||||||
|
import com.ruoyi.isc.domain.IscServiceCate;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.validation.constraints.*;
|
||||||
|
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import com.ruoyi.common.annotation.RepeatSubmit;
|
||||||
|
import com.ruoyi.common.annotation.Log;
|
||||||
|
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.enums.BusinessType;
|
||||||
|
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||||
|
import com.ruoyi.isc.domain.vo.IscServiceCateVo;
|
||||||
|
import com.ruoyi.isc.domain.bo.IscServiceCateBo;
|
||||||
|
import com.ruoyi.isc.service.IIscServiceCateService;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务分类Controller
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-08-22
|
||||||
|
*/
|
||||||
|
@Validated
|
||||||
|
@Api(value = "服务分类控制器", tags = {"服务分类管理"})
|
||||||
|
@RequiredArgsConstructor(onConstructor_ = @Autowired)
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/isc/cate")
|
||||||
|
public class IscServiceCateController extends BaseController {
|
||||||
|
|
||||||
|
private final IIscServiceCateService cateService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询服务分类列表
|
||||||
|
*/
|
||||||
|
@ApiOperation("查询服务分类列表")
|
||||||
|
@PreAuthorize("@ss.hasPermi('isc:cate:list')")
|
||||||
|
@GetMapping("/list")
|
||||||
|
public AjaxResult<List<IscServiceCateVo>> list(@Validated IscServiceCateBo bo)
|
||||||
|
{
|
||||||
|
List<IscServiceCateVo> list = cateService.queryList(bo);
|
||||||
|
return AjaxResult.success(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取分类下拉树列表
|
||||||
|
*/
|
||||||
|
@GetMapping("/treeselect")
|
||||||
|
@ApiOperation("获取分类下拉树列表")
|
||||||
|
public AjaxResult<List<Tree<Long>>> treeselect()
|
||||||
|
{
|
||||||
|
List<IscServiceCate> cates = cateService.selectCateList();
|
||||||
|
return AjaxResult.success(cateService.genCateTree(cates));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出服务分类列表
|
||||||
|
*/
|
||||||
|
@ApiOperation("导出服务分类列表")
|
||||||
|
@PreAuthorize("@ss.hasPermi('isc:cate:export')")
|
||||||
|
@Log(title = "服务分类", businessType = BusinessType.EXPORT)
|
||||||
|
@GetMapping("/export")
|
||||||
|
public void export(@Validated IscServiceCateBo bo, HttpServletResponse response)
|
||||||
|
{
|
||||||
|
List<IscServiceCateVo> list = cateService.queryList(bo);
|
||||||
|
ExcelUtil.exportExcel(list, "服务分类", IscServiceCateVo.class, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取服务分类详细信息
|
||||||
|
*/
|
||||||
|
@ApiOperation("获取服务分类详细信息")
|
||||||
|
@PreAuthorize("@ss.hasPermi('isc:cate:query')")
|
||||||
|
@GetMapping("/{cateId}")
|
||||||
|
public AjaxResult<IscServiceCateVo> getInfo(@NotNull(message = "主键不能为空") @PathVariable("cateId") Long cateId)
|
||||||
|
{
|
||||||
|
return AjaxResult.success(cateService.queryById(cateId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增服务分类
|
||||||
|
*/
|
||||||
|
@ApiOperation("新增服务分类")
|
||||||
|
@PreAuthorize("@ss.hasPermi('isc:cate:add')")
|
||||||
|
@Log(title = "服务分类", businessType = BusinessType.INSERT)
|
||||||
|
@RepeatSubmit()
|
||||||
|
@PostMapping()
|
||||||
|
public AjaxResult<Void> add(@Validated(AddGroup.class) @RequestBody IscServiceCateBo bo)
|
||||||
|
{
|
||||||
|
return toAjax(cateService.insertByBo(bo) ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改服务分类
|
||||||
|
*/
|
||||||
|
@ApiOperation("修改服务分类")
|
||||||
|
@PreAuthorize("@ss.hasPermi('isc:cate:edit')")
|
||||||
|
@Log(title = "服务分类", businessType = BusinessType.UPDATE)
|
||||||
|
@RepeatSubmit()
|
||||||
|
@PutMapping()
|
||||||
|
public AjaxResult<Void> edit(@Validated(EditGroup.class) @RequestBody IscServiceCateBo bo)
|
||||||
|
{
|
||||||
|
return toAjax(cateService.updateByBo(bo) ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除服务分类
|
||||||
|
*/
|
||||||
|
@ApiOperation("删除服务分类")
|
||||||
|
@PreAuthorize("@ss.hasPermi('isc:cate:remove')")
|
||||||
|
@Log(title = "服务分类", businessType = BusinessType.DELETE)
|
||||||
|
@DeleteMapping("/{cateIds}")
|
||||||
|
public AjaxResult<Void> remove(@NotEmpty(message = "主键不能为空") @PathVariable Long[] cateIds)
|
||||||
|
{
|
||||||
|
return toAjax(cateService.deleteWithValidByIds(Arrays.asList(cateIds), true) ? 1 : 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,125 @@
|
|||||||
|
package com.ruoyi.isc.controller;
|
||||||
|
|
||||||
|
import com.ruoyi.common.annotation.Log;
|
||||||
|
import com.ruoyi.common.annotation.RepeatSubmit;
|
||||||
|
import com.ruoyi.common.core.controller.BaseController;
|
||||||
|
import com.ruoyi.common.core.domain.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.enums.BusinessType;
|
||||||
|
import com.ruoyi.common.utils.poi.ExcelUtil;
|
||||||
|
import com.ruoyi.isc.domain.bo.IscAuditBo;
|
||||||
|
import com.ruoyi.isc.domain.bo.IscServiceBo;
|
||||||
|
import com.ruoyi.isc.domain.vo.IscServiceVo;
|
||||||
|
import com.ruoyi.isc.service.IIscServiceService;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务信息Controller
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-08-22
|
||||||
|
*/
|
||||||
|
@Validated
|
||||||
|
@Api(value = "服务信息控制器", tags = {"服务信息管理"})
|
||||||
|
@RequiredArgsConstructor(onConstructor_ = @Autowired)
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/isc/service")
|
||||||
|
public class IscServiceController extends BaseController {
|
||||||
|
|
||||||
|
private final IIscServiceService iIscServiceService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询服务信息列表
|
||||||
|
*/
|
||||||
|
@ApiOperation("查询服务信息列表")
|
||||||
|
@PreAuthorize("@ss.hasPermi('isc:service:list')")
|
||||||
|
@GetMapping("/list")
|
||||||
|
public TableDataInfo<IscServiceVo> list(@Validated IscServiceBo bo) {
|
||||||
|
return iIscServiceService.queryPageList(bo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出服务信息列表
|
||||||
|
*/
|
||||||
|
@ApiOperation("导出服务信息列表")
|
||||||
|
@PreAuthorize("@ss.hasPermi('isc:service:export')")
|
||||||
|
@Log(title = "服务信息", businessType = BusinessType.EXPORT)
|
||||||
|
@GetMapping("/export")
|
||||||
|
public void export(@Validated IscServiceBo bo, HttpServletResponse response) {
|
||||||
|
List<IscServiceVo> list = iIscServiceService.queryList(bo);
|
||||||
|
ExcelUtil.exportExcel(list, "服务信息", IscServiceVo.class, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取服务信息详细信息
|
||||||
|
*/
|
||||||
|
@ApiOperation("获取服务信息详细信息")
|
||||||
|
@PreAuthorize("@ss.hasPermi('isc:service:query')")
|
||||||
|
@GetMapping("/{serviceId}")
|
||||||
|
public AjaxResult<IscServiceVo> getInfo(@NotNull(message = "主键不能为空")
|
||||||
|
@PathVariable("serviceId") Long serviceId) {
|
||||||
|
return AjaxResult.success(iIscServiceService.queryById(serviceId));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新增服务信息
|
||||||
|
*/
|
||||||
|
@ApiOperation("新增服务信息")
|
||||||
|
@PreAuthorize("@ss.hasPermi('isc:service:add')")
|
||||||
|
@Log(title = "服务信息", businessType = BusinessType.INSERT)
|
||||||
|
@RepeatSubmit()
|
||||||
|
@PostMapping()
|
||||||
|
public AjaxResult<Void> add(@Validated(AddGroup.class) @RequestBody IscServiceBo bo) {
|
||||||
|
return toAjax(iIscServiceService.insertByBo(bo) ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改服务信息
|
||||||
|
*/
|
||||||
|
@ApiOperation("修改服务信息")
|
||||||
|
@PreAuthorize("@ss.hasPermi('isc:service:edit')")
|
||||||
|
@Log(title = "服务信息", businessType = BusinessType.UPDATE)
|
||||||
|
@RepeatSubmit()
|
||||||
|
@PutMapping()
|
||||||
|
public AjaxResult<Void> edit(@Validated(EditGroup.class) @RequestBody IscServiceBo bo) {
|
||||||
|
return toAjax(iIscServiceService.updateByBo(bo) ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除服务信息
|
||||||
|
*/
|
||||||
|
@ApiOperation("删除服务信息")
|
||||||
|
@PreAuthorize("@ss.hasPermi('isc:service:remove')")
|
||||||
|
@Log(title = "服务信息" , businessType = BusinessType.DELETE)
|
||||||
|
@DeleteMapping("/{serviceIds}")
|
||||||
|
public AjaxResult<Void> remove(@NotEmpty(message = "主键不能为空")
|
||||||
|
@PathVariable Long[] serviceIds) {
|
||||||
|
return toAjax(iIscServiceService.deleteWithValidByIds(Arrays.asList(serviceIds), true) ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务信息审核
|
||||||
|
*/
|
||||||
|
@ApiOperation("服务信息审核")
|
||||||
|
@PreAuthorize("@ss.hasPermi('isc:service:audit')")
|
||||||
|
@Log(title = "服务信息审核", businessType = BusinessType.AUDIT)
|
||||||
|
@RepeatSubmit()
|
||||||
|
@PutMapping("/audit")
|
||||||
|
public AjaxResult<Void> audit(@Validated @RequestBody IscAuditBo bo) {
|
||||||
|
return toAjax(iIscServiceService.audit(bo) ? 1 : 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,127 @@
|
|||||||
|
package com.ruoyi.isc.domain;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用服务对象 isc_app_service
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-09-08
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@TableName("isc_app_service")
|
||||||
|
public class IscAppService implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID=1L;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用服务ID
|
||||||
|
*/
|
||||||
|
@TableId(value = "app_service_id")
|
||||||
|
private Long appServiceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务ID
|
||||||
|
*/
|
||||||
|
private Long serviceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用ID
|
||||||
|
*/
|
||||||
|
private Long applicationId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户ID
|
||||||
|
*/
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用状态(0启用 1停用)
|
||||||
|
*/
|
||||||
|
private String enabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审核状态(0待审核 1审核通过 2驳回)
|
||||||
|
*/
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审核意见
|
||||||
|
*/
|
||||||
|
private String auditMind;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 虚拟地址
|
||||||
|
*/
|
||||||
|
private String virtualAddr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 到期时间
|
||||||
|
*/
|
||||||
|
private Date endTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 天配额
|
||||||
|
*/
|
||||||
|
private Long quotaDays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小时配额
|
||||||
|
*/
|
||||||
|
private Long quotaHours;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分钟配额
|
||||||
|
*/
|
||||||
|
private Long quotaMinutes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秒配额
|
||||||
|
*/
|
||||||
|
private Long quotaSeconds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建者
|
||||||
|
*/
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private String createBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新者
|
||||||
|
*/
|
||||||
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新时间
|
||||||
|
*/
|
||||||
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
|
private Date updateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除标志(0代表存在 2代表删除)
|
||||||
|
*/
|
||||||
|
@TableLogic
|
||||||
|
private String delFlag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,112 @@
|
|||||||
|
package com.ruoyi.isc.domain;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用服务申请信息对象 isc_app_service_apply
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-09-09
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@TableName("isc_app_service_apply")
|
||||||
|
public class IscAppServiceApply implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID=1L;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 申请ID
|
||||||
|
*/
|
||||||
|
@TableId(value = "apply_id")
|
||||||
|
private Long applyId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用服务ID
|
||||||
|
*/
|
||||||
|
private Long appServiceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 申请类型(0申请 1续期)
|
||||||
|
*/
|
||||||
|
private String applyType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审核状态(0待审核 1审核通过 2驳回)
|
||||||
|
*/
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审核意见
|
||||||
|
*/
|
||||||
|
private String auditMind;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 续期时长(单位月)
|
||||||
|
*/
|
||||||
|
private Integer renewalDuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 天配额
|
||||||
|
*/
|
||||||
|
private Long quotaDays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小时配额
|
||||||
|
*/
|
||||||
|
private Long quotaHours;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分钟配额
|
||||||
|
*/
|
||||||
|
private Long quotaMinutes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秒配额
|
||||||
|
*/
|
||||||
|
private Long quotaSeconds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建者
|
||||||
|
*/
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private String createBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新者
|
||||||
|
*/
|
||||||
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新时间
|
||||||
|
*/
|
||||||
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
|
private Date updateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除标志(0代表存在 2代表删除)
|
||||||
|
*/
|
||||||
|
@TableLogic
|
||||||
|
private String delFlag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,82 @@
|
|||||||
|
package com.ruoyi.isc.domain;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用信息对象 isc_application
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-09-08
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@TableName("isc_application")
|
||||||
|
public class IscApplication implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID=1L;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用ID
|
||||||
|
*/
|
||||||
|
@TableId(value = "application_id")
|
||||||
|
private Long applicationId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用名称
|
||||||
|
*/
|
||||||
|
private String applicationName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用密钥
|
||||||
|
*/
|
||||||
|
private String accessKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户ID
|
||||||
|
*/
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建者
|
||||||
|
*/
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private String createBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新者
|
||||||
|
*/
|
||||||
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新时间
|
||||||
|
*/
|
||||||
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
|
private Date updateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除标志(0代表存在 2代表删除)
|
||||||
|
*/
|
||||||
|
@TableLogic
|
||||||
|
private String delFlag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,132 @@
|
|||||||
|
package com.ruoyi.isc.domain;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务信息对象 isc_service
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-08-22
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@TableName("isc_service")
|
||||||
|
public class IscService implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID=1L;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务ID
|
||||||
|
*/
|
||||||
|
@TableId(value = "service_id")
|
||||||
|
private Long serviceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务名称
|
||||||
|
*/
|
||||||
|
private String serviceName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务地址
|
||||||
|
*/
|
||||||
|
private String serviceAddr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 探活地址
|
||||||
|
*/
|
||||||
|
private String probeActiveAddr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求方式(默认GET)
|
||||||
|
*/
|
||||||
|
private String requestMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跨域标志(Y是 N否)
|
||||||
|
*/
|
||||||
|
private String corsFlag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 隐藏参数
|
||||||
|
*/
|
||||||
|
private String hiddenParams;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否在线(0离线 1在线)
|
||||||
|
*/
|
||||||
|
private String onlineStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审核状态(0待审核 1审核通过 2驳回)
|
||||||
|
*/
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JSON文档
|
||||||
|
*/
|
||||||
|
private String apiDoc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审核意见
|
||||||
|
*/
|
||||||
|
private String auditMind;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务状态(0启用 1停用)
|
||||||
|
*/
|
||||||
|
private String enabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务分类全路径
|
||||||
|
*/
|
||||||
|
private String cateFullPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户ID
|
||||||
|
*/
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建者
|
||||||
|
*/
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private String createBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新者
|
||||||
|
*/
|
||||||
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新时间
|
||||||
|
*/
|
||||||
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
|
private Date updateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除标志(0代表存在 2代表删除)
|
||||||
|
*/
|
||||||
|
@TableLogic
|
||||||
|
private String delFlag;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,101 @@
|
|||||||
|
package com.ruoyi.isc.domain;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
|
import com.ruoyi.common.core.domain.entity.SysMenu;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务分类对象 isc_service_cate
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-08-22
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Accessors(chain = true)
|
||||||
|
@TableName("isc_service_cate")
|
||||||
|
public class IscServiceCate implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID=1L;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分类ID
|
||||||
|
*/
|
||||||
|
@TableId(value = "cate_id")
|
||||||
|
private Long cateId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 父分类ID
|
||||||
|
*/
|
||||||
|
private Long parentId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分类名称
|
||||||
|
*/
|
||||||
|
private String cateName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 搜索全路径
|
||||||
|
*/
|
||||||
|
private String fullPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用状态(0启用 1停用)
|
||||||
|
*/
|
||||||
|
private String enabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建者
|
||||||
|
*/
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private String createBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示顺序
|
||||||
|
*/
|
||||||
|
private Long orderNum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新者
|
||||||
|
*/
|
||||||
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新时间
|
||||||
|
*/
|
||||||
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
|
private Date updateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除标志(0代表存在 2代表删除)
|
||||||
|
*/
|
||||||
|
@TableLogic
|
||||||
|
private String delFlag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 子分类
|
||||||
|
*/
|
||||||
|
@TableField(exist = false)
|
||||||
|
private List<SysMenu> children = new ArrayList<SysMenu>();
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,111 @@
|
|||||||
|
package com.ruoyi.isc.domain.bo;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.domain.BaseEntity;
|
||||||
|
import com.ruoyi.common.core.validate.AddGroup;
|
||||||
|
import com.ruoyi.common.core.validate.EditGroup;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用服务申请信息业务对象 isc_app_service_apply
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-09-09
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ApiModel("应用服务申请信息业务对象")
|
||||||
|
public class IscAppServiceApplyBo extends BaseEntity {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 申请ID
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "申请ID")
|
||||||
|
private Long applyId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用服务ID
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "应用服务ID", required = true)
|
||||||
|
@NotNull(message = "应用服务ID不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||||
|
private Long appServiceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 申请类型(0申请 1续期)
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "申请类型(0申请 1续期)")
|
||||||
|
private String applyType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审核状态(0待审核 1审核通过 2驳回)
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "审核状态(0待审核 1审核通过 2驳回)")
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 续期时长(单位月)
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "续期时长(单位月)")
|
||||||
|
private Integer renewalDuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 天配额
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "天配额")
|
||||||
|
private Long quotaDays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小时配额
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "小时配额")
|
||||||
|
private Long quotaHours;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分钟配额
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "分钟配额")
|
||||||
|
private Long quotaMinutes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秒配额
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "秒配额")
|
||||||
|
private Long quotaSeconds;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页大小
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("分页大小")
|
||||||
|
private Integer pageSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前页数
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("当前页数")
|
||||||
|
private Integer pageNum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序列
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("排序列")
|
||||||
|
private String orderByColumn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序的方向desc或者asc
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "排序的方向", example = "asc,desc")
|
||||||
|
private String isAsc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "备注")
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,132 @@
|
|||||||
|
package com.ruoyi.isc.domain.bo;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.domain.BaseEntity;
|
||||||
|
import com.ruoyi.common.core.validate.AddGroup;
|
||||||
|
import com.ruoyi.common.core.validate.EditGroup;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用服务业务对象 isc_app_service
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-09-08
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ApiModel("应用服务业务对象")
|
||||||
|
public class IscAppServiceBo extends BaseEntity {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用服务ID
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "应用服务ID")
|
||||||
|
private Long appServiceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务ID
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "服务ID", required = true)
|
||||||
|
@NotNull(message = "服务ID不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||||
|
private Long serviceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用ID
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "应用ID", required = true)
|
||||||
|
@NotNull(message = "应用ID不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||||
|
private Long applicationId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用状态(0启用 1停用)
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "启用状态(0启用 1停用)", required = true)
|
||||||
|
@NotBlank(message = "启用状态(0启用 1停用)不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||||
|
private String enabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审核状态(0待审核 1审核通过 2驳回)
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "审核状态(0待审核 1审核通过 2驳回)")
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 到期时间
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "到期时间")
|
||||||
|
private Date endTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 天配额
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "天配额")
|
||||||
|
private Long quotaDays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小时配额
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "小时配额")
|
||||||
|
private Long quotaHours;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分钟配额
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "分钟配额")
|
||||||
|
private Long quotaMinutes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秒配额
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "秒配额")
|
||||||
|
private Long quotaSeconds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 续期时长(单位月)
|
||||||
|
*/
|
||||||
|
@NotNull(message = "续期时长不能为空", groups = { AddGroup.class })
|
||||||
|
private Integer renewalDuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 申请类型(0申请 1续期)
|
||||||
|
*/
|
||||||
|
@NotBlank(message = "申请类型必填")
|
||||||
|
private String applyType;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页大小
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("分页大小")
|
||||||
|
private Integer pageSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前页数
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("当前页数")
|
||||||
|
private Integer pageNum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序列
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("排序列")
|
||||||
|
private String orderByColumn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序的方向desc或者asc
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "排序的方向", example = "asc,desc")
|
||||||
|
private String isAsc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "备注")
|
||||||
|
private String remark;
|
||||||
|
}
|
||||||
@ -0,0 +1,68 @@
|
|||||||
|
package com.ruoyi.isc.domain.bo;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.domain.BaseEntity;
|
||||||
|
import com.ruoyi.common.core.validate.AddGroup;
|
||||||
|
import com.ruoyi.common.core.validate.EditGroup;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用信息业务对象 isc_application
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-09-08
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ApiModel("应用信息业务对象")
|
||||||
|
public class IscApplicationBo extends BaseEntity {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用ID
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "应用ID")
|
||||||
|
private Long applicationId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用名称
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "应用名称", required = true)
|
||||||
|
@NotBlank(message = "应用名称不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||||
|
private String applicationName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用密钥
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "应用密钥", required = true)
|
||||||
|
private String accessKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页大小
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("分页大小")
|
||||||
|
private Integer pageSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前页数
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("当前页数")
|
||||||
|
private Integer pageNum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序列
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("排序列")
|
||||||
|
private String orderByColumn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序的方向desc或者asc
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "排序的方向", example = "asc,desc")
|
||||||
|
private String isAsc;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,50 @@
|
|||||||
|
package com.ruoyi.isc.domain.bo;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.domain.BaseEntity;
|
||||||
|
import com.ruoyi.common.core.validate.AddGroup;
|
||||||
|
import com.ruoyi.common.core.validate.EditGroup;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务管控审核
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-09-09
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@ApiModel("服务管控审核业务对象")
|
||||||
|
public class IscAuditBo implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ID集合
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "ID集合")
|
||||||
|
@NotEmpty(message = "请选择记录")
|
||||||
|
private List<Long> ids;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审核状态(0待审核 1审核通过 2驳回)
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "审核状态(0待审核 1审核通过 2驳回)")
|
||||||
|
@NotBlank(message = "请填写审核结果")
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "备注")
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,131 @@
|
|||||||
|
package com.ruoyi.isc.domain.bo;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.domain.BaseEntity;
|
||||||
|
import com.ruoyi.common.core.validate.AddGroup;
|
||||||
|
import com.ruoyi.common.core.validate.EditGroup;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务信息业务对象 isc_service
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-08-22
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ApiModel("服务信息业务对象")
|
||||||
|
public class IscServiceBo extends BaseEntity {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务ID
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "服务ID", required = true)
|
||||||
|
@NotNull(message = "服务ID不能为空", groups = { EditGroup.class })
|
||||||
|
private Long serviceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务名称
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "服务名称", required = true)
|
||||||
|
@NotBlank(message = "服务名称不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||||
|
private String serviceName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务地址
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "服务地址", required = true)
|
||||||
|
@NotBlank(message = "服务地址不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||||
|
private String serviceAddr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 探活地址
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "探活地址", required = true)
|
||||||
|
@NotBlank(message = "探活地址不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||||
|
private String probeActiveAddr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求方式(默认GET)
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "请求方式(默认GET)", required = true)
|
||||||
|
@NotBlank(message = "请求方式(默认GET)不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||||
|
private String requestMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跨域标志(Y是 N否)
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "跨域标志(Y是 N否)", required = true)
|
||||||
|
@NotBlank(message = "跨域标志(Y是 N否)不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||||
|
private String corsFlag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 隐藏参数
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "隐藏参数")
|
||||||
|
private String hiddenParams;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否在线(0离线 1在线)
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "是否在线(0离线 1在线)")
|
||||||
|
private String onlineStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审核状态(0待审核 1审核通过 2驳回)
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "审核状态(0待审核 1审核通过 2驳回)")
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JSON文档
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "JSON文档", required = true)
|
||||||
|
@NotBlank(message = "JSON文档不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||||
|
private String apiDoc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务状态(0启用 1停用)
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "服务状态(0启用 1停用)", required = true)
|
||||||
|
@NotBlank(message = "服务状态(0启用 1停用)不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||||
|
private String enabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务分类
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "服务分类", required = true)
|
||||||
|
@NotNull(message = "服务分类不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||||
|
private String cateFullPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页大小
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("分页大小")
|
||||||
|
private Integer pageSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前页数
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("当前页数")
|
||||||
|
private Integer pageNum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序列
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("排序列")
|
||||||
|
private String orderByColumn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序的方向desc或者asc
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "排序的方向", example = "asc,desc")
|
||||||
|
private String isAsc;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,69 @@
|
|||||||
|
package com.ruoyi.isc.domain.bo;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.domain.TreeEntity;
|
||||||
|
import com.ruoyi.common.core.validate.AddGroup;
|
||||||
|
import com.ruoyi.common.core.validate.EditGroup;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务分类业务对象 isc_service_cate
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-08-22
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@ApiModel("服务分类业务对象")
|
||||||
|
public class IscServiceCateBo extends TreeEntity {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分类ID
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "分类ID")
|
||||||
|
private Long cateId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分类名称
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "分类名称")
|
||||||
|
private String cateName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用状态(0启用 1停用)
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "启用状态(0启用 1停用)", required = true)
|
||||||
|
@NotBlank(message = "启用状态(0启用 1停用)不能为空", groups = { AddGroup.class, EditGroup.class })
|
||||||
|
private String enabled;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页大小
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("分页大小")
|
||||||
|
private Integer pageSize;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前页数
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("当前页数")
|
||||||
|
private Integer pageNum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序列
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("排序列")
|
||||||
|
private String orderByColumn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 排序的方向desc或者asc
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "排序的方向", example = "asc,desc")
|
||||||
|
private String isAsc;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,127 @@
|
|||||||
|
package com.ruoyi.isc.domain.vo;
|
||||||
|
|
||||||
|
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||||
|
import com.alibaba.excel.annotation.ExcelProperty;
|
||||||
|
import com.ruoyi.common.annotation.ExcelDictFormat;
|
||||||
|
import com.ruoyi.common.convert.ExcelDictConvert;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用服务申请信息视图对象 isc_app_service_apply
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-09-09
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@ApiModel("应用服务申请信息视图对象")
|
||||||
|
@ExcelIgnoreUnannotated
|
||||||
|
public class IscAppServiceApplyVo {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 申请ID
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("申请ID")
|
||||||
|
private Long applyId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用服务ID
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("应用服务ID")
|
||||||
|
private Long appServiceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用名称
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "应用名称")
|
||||||
|
@ApiModelProperty("应用名称")
|
||||||
|
private String applicationName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务名称
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "服务名称")
|
||||||
|
@ApiModelProperty("服务名称")
|
||||||
|
private String serviceName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 申请类型(0申请 1续期)
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "申请类型(0申请 1续期)", converter = ExcelDictConvert.class)
|
||||||
|
@ExcelDictFormat(dictType = "isc_apply_type")
|
||||||
|
@ApiModelProperty("申请类型(0申请 1续期)")
|
||||||
|
private String applyType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审核状态(0待审核 1审核通过 2驳回)
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "审核状态", converter = ExcelDictConvert.class)
|
||||||
|
@ExcelDictFormat(dictType = "sys_audit_status")
|
||||||
|
@ApiModelProperty("审核状态(0待审核 1审核通过 2驳回)")
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 续期时长(单位月)
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "续期时长", converter = ExcelDictConvert.class)
|
||||||
|
@ExcelDictFormat(readConverterExp = "单=位月")
|
||||||
|
@ApiModelProperty("续期时长(单位月)")
|
||||||
|
private Integer renewalDuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 天配额
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "天配额")
|
||||||
|
@ApiModelProperty("天配额")
|
||||||
|
private Long quotaDays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小时配额
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "小时配额")
|
||||||
|
@ApiModelProperty("小时配额")
|
||||||
|
private Long quotaHours;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分钟配额
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "分钟配额")
|
||||||
|
@ApiModelProperty("分钟配额")
|
||||||
|
private Long quotaMinutes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秒配额
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "秒配额")
|
||||||
|
@ApiModelProperty("秒配额")
|
||||||
|
private Long quotaSeconds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新者
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "更新者")
|
||||||
|
@ApiModelProperty("更新者")
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新时间
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "更新时间")
|
||||||
|
@ApiModelProperty("更新时间")
|
||||||
|
private Date updateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "备注")
|
||||||
|
@ApiModelProperty("备注")
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,150 @@
|
|||||||
|
package com.ruoyi.isc.domain.vo;
|
||||||
|
|
||||||
|
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||||
|
import com.alibaba.excel.annotation.ExcelProperty;
|
||||||
|
import com.ruoyi.common.annotation.ExcelDictFormat;
|
||||||
|
import com.ruoyi.common.convert.ExcelDictConvert;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用服务视图对象 isc_app_service
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-09-08
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@ApiModel("应用服务视图对象")
|
||||||
|
@ExcelIgnoreUnannotated
|
||||||
|
public class IscAppServiceVo {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用服务ID
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("应用服务ID")
|
||||||
|
private Long appServiceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务ID
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("服务ID")
|
||||||
|
private Long serviceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务名称
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "服务名称")
|
||||||
|
@ApiModelProperty("服务名称")
|
||||||
|
private String serviceName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用ID
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "应用ID")
|
||||||
|
@ApiModelProperty("应用ID")
|
||||||
|
private Long applicationId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户ID
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "用户ID")
|
||||||
|
@ApiModelProperty("用户ID")
|
||||||
|
private Long userId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用状态(0启用 1停用)
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "启用状态", converter = ExcelDictConvert.class)
|
||||||
|
@ExcelDictFormat(dictType = "sys_normal_disable")
|
||||||
|
@ApiModelProperty("启用状态(0启用 1停用)")
|
||||||
|
private String enabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 申请类型(0申请 1续期)
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "申请类型(0申请 1续期)", converter = ExcelDictConvert.class)
|
||||||
|
@ExcelDictFormat(dictType = "isc_apply_type")
|
||||||
|
@ApiModelProperty("申请类型(0申请 1续期)")
|
||||||
|
private String applyType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审核状态(0待审核 1审核通过 2驳回)
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "审核状态", converter = ExcelDictConvert.class)
|
||||||
|
@ExcelDictFormat(dictType = "sys_audit_status")
|
||||||
|
@ApiModelProperty("审核状态(0待审核 1审核通过 2驳回)")
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审核意见
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("审核意见")
|
||||||
|
private String auditMind;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 虚拟地址
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "虚拟地址")
|
||||||
|
@ApiModelProperty("虚拟地址")
|
||||||
|
private String virtualAddr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 到期时间
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "到期时间")
|
||||||
|
@ApiModelProperty("到期时间")
|
||||||
|
private Date endTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 天配额
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "天配额")
|
||||||
|
private Long quotaDays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 小时配额
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "小时配额")
|
||||||
|
private Long quotaHours;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分钟配额
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "分钟配额")
|
||||||
|
private Long quotaMinutes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秒配额
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "秒配额")
|
||||||
|
private Long quotaSeconds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "备注")
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新者
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "更新者")
|
||||||
|
@ApiModelProperty("更新者")
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新时间
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "更新时间")
|
||||||
|
@ApiModelProperty("更新时间")
|
||||||
|
private Date updateTime;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
package com.ruoyi.isc.domain.vo;
|
||||||
|
|
||||||
|
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||||
|
import com.alibaba.excel.annotation.ExcelProperty;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用信息视图对象 isc_application
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-09-08
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@ApiModel("应用信息视图对象")
|
||||||
|
@ExcelIgnoreUnannotated
|
||||||
|
public class IscApplicationVo {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用ID
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("应用ID")
|
||||||
|
private Long applicationId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用名称
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "应用名称")
|
||||||
|
@ApiModelProperty("应用名称")
|
||||||
|
private String applicationName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用密钥
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "应用密钥")
|
||||||
|
@ApiModelProperty("应用密钥")
|
||||||
|
private String accessKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "备注")
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新者
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "更新者")
|
||||||
|
@ApiModelProperty("更新者")
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新时间
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "更新时间")
|
||||||
|
@ApiModelProperty("更新时间")
|
||||||
|
private Date updateTime;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,84 @@
|
|||||||
|
package com.ruoyi.isc.domain.vo;
|
||||||
|
|
||||||
|
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||||
|
import com.alibaba.excel.annotation.ExcelProperty;
|
||||||
|
import com.ruoyi.common.annotation.ExcelDictFormat;
|
||||||
|
import com.ruoyi.common.convert.ExcelDictConvert;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务分类视图对象 isc_service_cate
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-08-22
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@ApiModel("服务分类视图对象")
|
||||||
|
@ExcelIgnoreUnannotated
|
||||||
|
public class IscServiceCateVo {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分类ID
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("分类ID")
|
||||||
|
private Long cateId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 父分类ID
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "父分类ID")
|
||||||
|
@ApiModelProperty("父分类ID")
|
||||||
|
private Long parentId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分类名称
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "分类名称")
|
||||||
|
@ApiModelProperty("分类名称")
|
||||||
|
private String cateName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 启用状态(0启用 1停用)
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "启用状态", converter = ExcelDictConvert.class)
|
||||||
|
@ExcelDictFormat(dictType = "sys_normal_disable")
|
||||||
|
@ApiModelProperty("启用状态(0启用 1停用)")
|
||||||
|
private String enabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示顺序
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "显示顺序")
|
||||||
|
@ApiModelProperty("显示顺序")
|
||||||
|
private Long orderNum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新者
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "更新者")
|
||||||
|
@ApiModelProperty("更新者")
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新时间
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "更新时间")
|
||||||
|
@ApiModelProperty("更新时间")
|
||||||
|
private Date updateTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "备注")
|
||||||
|
@ApiModelProperty("备注")
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,138 @@
|
|||||||
|
package com.ruoyi.isc.domain.vo;
|
||||||
|
|
||||||
|
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||||
|
import com.alibaba.excel.annotation.ExcelProperty;
|
||||||
|
import com.ruoyi.common.annotation.ExcelDictFormat;
|
||||||
|
import com.ruoyi.common.convert.ExcelDictConvert;
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务信息视图对象 isc_service
|
||||||
|
*
|
||||||
|
* @author ruoyi
|
||||||
|
* @date 2021-08-22
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@ApiModel("服务信息视图对象")
|
||||||
|
@ExcelIgnoreUnannotated
|
||||||
|
public class IscServiceVo {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务ID
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("服务ID")
|
||||||
|
private Long serviceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务名称
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "服务名称")
|
||||||
|
@ApiModelProperty("服务名称")
|
||||||
|
private String serviceName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务地址
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "服务地址")
|
||||||
|
@ApiModelProperty("服务地址")
|
||||||
|
private String serviceAddr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 探活地址
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "探活地址")
|
||||||
|
@ApiModelProperty("探活地址")
|
||||||
|
private String probeActiveAddr;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求方式(默认GET)
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "请求方式")
|
||||||
|
@ApiModelProperty("请求方式(默认GET)")
|
||||||
|
private String requestMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("备注")
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 跨域标志(Y是 N否)
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "跨域标志", converter = ExcelDictConvert.class)
|
||||||
|
@ExcelDictFormat(dictType = "sys_yes_no")
|
||||||
|
@ApiModelProperty("跨域标志(Y是 N否)")
|
||||||
|
private String corsFlag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 隐藏参数
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("隐藏参数")
|
||||||
|
private String hiddenParams;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JSON文档
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("JSON文档")
|
||||||
|
private String apiDoc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否在线(0离线 1在线)
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "是否在线", converter = ExcelDictConvert.class)
|
||||||
|
@ExcelDictFormat(dictType = "isc_online_status")
|
||||||
|
@ApiModelProperty("是否在线(0离线 1在线)")
|
||||||
|
private String onlineStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审核状态(0待审核 1审核通过 2驳回)
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "审核状态", converter = ExcelDictConvert.class)
|
||||||
|
@ExcelDictFormat(dictType = "sys_audit_status")
|
||||||
|
@ApiModelProperty("审核状态(0待审核 1审核通过 2驳回)")
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务状态(0启用 1停用)
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "服务状态", converter = ExcelDictConvert.class)
|
||||||
|
@ExcelDictFormat(dictType = "sys_normal_disable")
|
||||||
|
@ApiModelProperty("服务状态(0启用 1停用)")
|
||||||
|
private String enabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务分类
|
||||||
|
*/
|
||||||
|
@ApiModelProperty("服务分类")
|
||||||
|
private String cateFullPath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务分类名称
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "服务分类")
|
||||||
|
@ApiModelProperty("服务分类名称")
|
||||||
|
private String cateName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新人
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "更新人")
|
||||||
|
@ApiModelProperty("更新人")
|
||||||
|
private String updateBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新时间
|
||||||
|
*/
|
||||||
|
@ExcelProperty(value = "更新时间")
|
||||||
|
@ApiModelProperty("更新时间")
|
||||||
|
private Date updateTime;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
package com.ruoyi.isc.mapper;
|
||||||
|
|
||||||
|
import com.ruoyi.isc.domain.IscAppServiceApply;
|
||||||
|
import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus;
|
||||||
|
import com.ruoyi.common.core.mybatisplus.cache.MybatisPlusRedisCache;
|
||||||
|
import org.apache.ibatis.annotations.CacheNamespace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用服务申请信息Mapper接口
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-09-09
|
||||||
|
*/
|
||||||
|
public interface IscAppServiceApplyMapper extends BaseMapperPlus<IscAppServiceApply> {
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
package com.ruoyi.isc.mapper;
|
||||||
|
|
||||||
|
import com.ruoyi.isc.domain.IscAppService;
|
||||||
|
import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus;
|
||||||
|
import com.ruoyi.common.core.mybatisplus.cache.MybatisPlusRedisCache;
|
||||||
|
import org.apache.ibatis.annotations.CacheNamespace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用服务Mapper接口
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-09-08
|
||||||
|
*/
|
||||||
|
public interface IscAppServiceMapper extends BaseMapperPlus<IscAppService> {
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
package com.ruoyi.isc.mapper;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus;
|
||||||
|
import com.ruoyi.isc.domain.IscApplication;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用信息Mapper接口
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-09-08
|
||||||
|
*/
|
||||||
|
public interface IscApplicationMapper extends BaseMapperPlus<IscApplication> {
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
package com.ruoyi.isc.mapper;
|
||||||
|
|
||||||
|
import com.ruoyi.isc.domain.IscServiceCate;
|
||||||
|
import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus;
|
||||||
|
import com.ruoyi.common.core.mybatisplus.cache.MybatisPlusRedisCache;
|
||||||
|
import org.apache.ibatis.annotations.CacheNamespace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务分类Mapper接口
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-08-22
|
||||||
|
*/
|
||||||
|
public interface IscServiceCateMapper extends BaseMapperPlus<IscServiceCate> {
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,16 @@
|
|||||||
|
package com.ruoyi.isc.mapper;
|
||||||
|
|
||||||
|
import com.ruoyi.isc.domain.IscService;
|
||||||
|
import com.ruoyi.common.core.mybatisplus.core.BaseMapperPlus;
|
||||||
|
import com.ruoyi.common.core.mybatisplus.cache.MybatisPlusRedisCache;
|
||||||
|
import org.apache.ibatis.annotations.CacheNamespace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务信息Mapper接口
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-08-22
|
||||||
|
*/
|
||||||
|
public interface IscServiceMapper extends BaseMapperPlus<IscService> {
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,64 @@
|
|||||||
|
package com.ruoyi.isc.service;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.mybatisplus.core.IServicePlus;
|
||||||
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
import com.ruoyi.isc.domain.IscAppServiceApply;
|
||||||
|
import com.ruoyi.isc.domain.bo.IscAppServiceApplyBo;
|
||||||
|
import com.ruoyi.isc.domain.bo.IscAuditBo;
|
||||||
|
import com.ruoyi.isc.domain.vo.IscAppServiceApplyVo;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用服务申请信息Service接口
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-09-09
|
||||||
|
*/
|
||||||
|
public interface IIscAppServiceApplyService extends IServicePlus<IscAppServiceApply, IscAppServiceApplyVo> {
|
||||||
|
/**
|
||||||
|
* 查询单个
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
IscAppServiceApplyVo queryById(Long applyId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询列表
|
||||||
|
*/
|
||||||
|
TableDataInfo<IscAppServiceApplyVo> queryPageList(IscAppServiceApplyBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询列表
|
||||||
|
*/
|
||||||
|
List<IscAppServiceApplyVo> queryList(IscAppServiceApplyBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据新增业务对象插入应用服务申请信息
|
||||||
|
* @param bo 应用服务申请信息新增业务对象
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Boolean insertByBo(IscAppServiceApplyBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据编辑业务对象修改应用服务申请信息
|
||||||
|
* @param bo 应用服务申请信息编辑业务对象
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Boolean updateByBo(IscAppServiceApplyBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验并删除数据
|
||||||
|
* @param ids 主键集合
|
||||||
|
* @param isValid 是否校验,true-删除前校验,false-不校验
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用服务审核
|
||||||
|
* @param bo 审核业务数据
|
||||||
|
* @return 是否审核成功
|
||||||
|
*/
|
||||||
|
Boolean audit(IscAuditBo bo);
|
||||||
|
}
|
||||||
@ -0,0 +1,76 @@
|
|||||||
|
package com.ruoyi.isc.service;
|
||||||
|
|
||||||
|
import cn.hutool.core.lang.tree.Tree;
|
||||||
|
import com.ruoyi.common.core.mybatisplus.core.IServicePlus;
|
||||||
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
import com.ruoyi.isc.domain.IscAppService;
|
||||||
|
import com.ruoyi.isc.domain.bo.IscAppServiceBo;
|
||||||
|
import com.ruoyi.isc.domain.vo.IscAppServiceVo;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用服务Service接口
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-09-08
|
||||||
|
*/
|
||||||
|
public interface IIscAppServiceService extends IServicePlus<IscAppService, IscAppServiceVo> {
|
||||||
|
/**
|
||||||
|
* 查询单个
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
IscAppServiceVo queryById(Long appServiceId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询列表
|
||||||
|
*/
|
||||||
|
TableDataInfo<IscAppServiceVo> queryPageList(IscAppServiceBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询列表
|
||||||
|
*/
|
||||||
|
List<IscAppServiceVo> queryList(IscAppServiceBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据新增业务对象插入应用服务
|
||||||
|
* @param bo 应用服务新增业务对象
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Boolean insertByBo(IscAppServiceBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据编辑业务对象修改应用服务
|
||||||
|
* @param bo 应用服务编辑业务对象
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Boolean updateByBo(IscAppServiceBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验并删除数据
|
||||||
|
* @param ids 主键集合
|
||||||
|
* @param isValid 是否校验,true-删除前校验,false-不校验
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造 应用服务树结构
|
||||||
|
* @param applicationId 应用ID
|
||||||
|
* @return 应用服务树结构 (标识服务是否存在)
|
||||||
|
*/
|
||||||
|
List<Tree<Long>> genAppServiceTree(Long applicationId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过 Id集合 返回列表
|
||||||
|
* @param ids 应用服务ID
|
||||||
|
* @return 应用服务列表
|
||||||
|
*/
|
||||||
|
List<IscAppService> getAppServiceListByIds(Collection<Long> ids);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新规则信息(服务对应AK)
|
||||||
|
*/
|
||||||
|
void refreshRules();
|
||||||
|
}
|
||||||
@ -0,0 +1,64 @@
|
|||||||
|
package com.ruoyi.isc.service;
|
||||||
|
|
||||||
|
import com.ruoyi.common.core.mybatisplus.core.IServicePlus;
|
||||||
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
import com.ruoyi.isc.domain.IscApplication;
|
||||||
|
import com.ruoyi.isc.domain.bo.IscApplicationBo;
|
||||||
|
import com.ruoyi.isc.domain.vo.IscApplicationVo;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用信息Service接口
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-09-08
|
||||||
|
*/
|
||||||
|
public interface IIscApplicationService extends IServicePlus<IscApplication, IscApplicationVo> {
|
||||||
|
/**
|
||||||
|
* 查询单个
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
IscApplicationVo queryById(Long applicationId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询列表
|
||||||
|
*/
|
||||||
|
TableDataInfo<IscApplicationVo> queryPageList(IscApplicationBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询列表
|
||||||
|
*/
|
||||||
|
List<IscApplicationVo> queryList(IscApplicationBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据新增业务对象插入应用信息
|
||||||
|
* @param bo 应用信息新增业务对象
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Boolean insertByBo(IscApplicationBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据编辑业务对象修改应用信息
|
||||||
|
* @param bo 应用信息编辑业务对象
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Boolean updateByBo(IscApplicationBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验并删除数据
|
||||||
|
* @param ids 主键集合
|
||||||
|
* @param isValid 是否校验,true-删除前校验,false-不校验
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过应用ID集合批量查询 应用名称
|
||||||
|
* @param applicationIds 应用ID集合
|
||||||
|
* @return 应用名称Map
|
||||||
|
*/
|
||||||
|
Map<Long, String> getNameMap(Collection<Long> applicationIds);
|
||||||
|
}
|
||||||
@ -0,0 +1,84 @@
|
|||||||
|
package com.ruoyi.isc.service;
|
||||||
|
|
||||||
|
import cn.hutool.core.lang.tree.Tree;
|
||||||
|
import com.ruoyi.common.core.mybatisplus.core.IServicePlus;
|
||||||
|
import com.ruoyi.isc.domain.IscService;
|
||||||
|
import com.ruoyi.isc.domain.IscServiceCate;
|
||||||
|
import com.ruoyi.isc.domain.bo.IscServiceCateBo;
|
||||||
|
import com.ruoyi.isc.domain.vo.IscServiceCateVo;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务分类Service接口
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-08-22
|
||||||
|
*/
|
||||||
|
public interface IIscServiceCateService extends IServicePlus<IscServiceCate, IscServiceCateVo> {
|
||||||
|
/**
|
||||||
|
* 查询单个
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
IscServiceCateVo queryById(Long cateId);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询列表
|
||||||
|
*/
|
||||||
|
List<IscServiceCateVo> queryList(IscServiceCateBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据新增业务对象插入服务分类
|
||||||
|
* @param bo 服务分类新增业务对象
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Boolean insertByBo(IscServiceCateBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据编辑业务对象修改服务分类
|
||||||
|
* @param bo 服务分类编辑业务对象
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Boolean updateByBo(IscServiceCateBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验并删除数据
|
||||||
|
* @param ids 主键集合
|
||||||
|
* @param isValid 是否校验,true-删除前校验,false-不校验
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取分类信息
|
||||||
|
* @return 分类列表
|
||||||
|
*/
|
||||||
|
List<IscServiceCate> selectCateList();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量获取分类名称
|
||||||
|
* @param fullPathList
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Map<String, String> batchCateName(Set<String> fullPathList);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组装 服务分类 树结构
|
||||||
|
* @param cates 所有分类
|
||||||
|
* @return 树结构信息
|
||||||
|
*/
|
||||||
|
List<Tree<Long>> genCateTree(List<IscServiceCate> cates);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组装 服务分类 树结构
|
||||||
|
* @param cates 所有分类
|
||||||
|
* @param serviceList 可用服务列表
|
||||||
|
* @param exitsIds 已存在服务ID集合
|
||||||
|
* @return 树结构信息
|
||||||
|
*/
|
||||||
|
List<Tree<Long>> genCateTree(List<IscServiceCate> cates, List<IscService> serviceList, Set<Long> exitsIds);
|
||||||
|
}
|
||||||
@ -0,0 +1,98 @@
|
|||||||
|
package com.ruoyi.isc.service;
|
||||||
|
|
||||||
|
import cn.hutool.core.lang.tree.Tree;
|
||||||
|
import com.ruoyi.common.core.mybatisplus.core.IServicePlus;
|
||||||
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
import com.ruoyi.isc.domain.IscService;
|
||||||
|
import com.ruoyi.isc.domain.bo.IscAuditBo;
|
||||||
|
import com.ruoyi.isc.domain.bo.IscServiceBo;
|
||||||
|
import com.ruoyi.isc.domain.vo.IscServiceVo;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务信息Service接口
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-08-22
|
||||||
|
*/
|
||||||
|
public interface IIscServiceService extends IServicePlus<IscService, IscServiceVo> {
|
||||||
|
/**
|
||||||
|
* 查询单个
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
IscServiceVo queryById(Long serviceId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询列表
|
||||||
|
*/
|
||||||
|
TableDataInfo<IscServiceVo> queryPageList(IscServiceBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询列表
|
||||||
|
*/
|
||||||
|
List<IscServiceVo> queryList(IscServiceBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据新增业务对象插入服务信息
|
||||||
|
* @param bo 服务信息新增业务对象
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Boolean insertByBo(IscServiceBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据编辑业务对象修改服务信息
|
||||||
|
* @param bo 服务信息编辑业务对象
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Boolean updateByBo(IscServiceBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验并删除数据
|
||||||
|
* @param ids 主键集合
|
||||||
|
* @param isValid 是否校验,true-删除前校验,false-不校验
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过服务ID集合 查询服务名称map
|
||||||
|
* @param serviceIds 服务ID集合
|
||||||
|
* @return 服务名称map
|
||||||
|
*/
|
||||||
|
Map<Long, String> getNameMap(Collection<Long> serviceIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组装 服务树结构
|
||||||
|
* @return 服务树结构
|
||||||
|
*/
|
||||||
|
List<Tree<Long>> genServiceTree();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组装 服务树结构
|
||||||
|
* @param exitsIds 已存在服务ID集合
|
||||||
|
* @return 服务树结构
|
||||||
|
*/
|
||||||
|
List<Tree<Long>> genServiceTree(Set<Long> exitsIds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务信息审核
|
||||||
|
* @param bo 审核信息
|
||||||
|
* @return 操作结果
|
||||||
|
*/
|
||||||
|
Boolean audit(IscAuditBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验 审核参数
|
||||||
|
* @param bo 审核业务对象
|
||||||
|
*/
|
||||||
|
void checkAuditBO(IscAuditBo bo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新路由信息
|
||||||
|
*/
|
||||||
|
void refreshRoutes();
|
||||||
|
}
|
||||||
@ -0,0 +1,263 @@
|
|||||||
|
package com.ruoyi.isc.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
|
import cn.hutool.core.lang.Assert;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import com.ruoyi.common.constant.Constants;
|
||||||
|
import com.ruoyi.common.constant.IscConstants;
|
||||||
|
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
|
||||||
|
import com.ruoyi.common.core.page.PagePlus;
|
||||||
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
|
import com.ruoyi.common.utils.DateUtils;
|
||||||
|
import com.ruoyi.common.utils.PageUtils;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.isc.domain.IscAppService;
|
||||||
|
import com.ruoyi.isc.domain.IscAppServiceApply;
|
||||||
|
import com.ruoyi.isc.domain.IscApplication;
|
||||||
|
import com.ruoyi.isc.domain.IscService;
|
||||||
|
import com.ruoyi.isc.domain.bo.IscAppServiceApplyBo;
|
||||||
|
import com.ruoyi.isc.domain.bo.IscAuditBo;
|
||||||
|
import com.ruoyi.isc.domain.vo.IscAppServiceApplyVo;
|
||||||
|
import com.ruoyi.isc.mapper.IscAppServiceApplyMapper;
|
||||||
|
import com.ruoyi.isc.service.IIscAppServiceApplyService;
|
||||||
|
import com.ruoyi.isc.service.IIscAppServiceService;
|
||||||
|
import com.ruoyi.isc.service.IIscApplicationService;
|
||||||
|
import com.ruoyi.isc.service.IIscServiceService;
|
||||||
|
import com.ruoyi.isc.utils.RouteUtils;
|
||||||
|
import com.ruoyi.isc.utils.beans.IscRouteDefinition;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用服务申请信息Service业务层处理
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-09-09
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class IscAppServiceApplyServiceImpl extends ServicePlusImpl<IscAppServiceApplyMapper, IscAppServiceApply, IscAppServiceApplyVo> implements IIscAppServiceApplyService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IIscAppServiceService appServiceService;
|
||||||
|
@Resource
|
||||||
|
private IIscApplicationService applicationService;
|
||||||
|
@Resource
|
||||||
|
private IIscServiceService serviceService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IscAppServiceApplyVo queryById(Long applyId){
|
||||||
|
IscAppServiceApplyVo vo = getVoById(applyId);
|
||||||
|
genServiceNameAndApplicationName(Arrays.asList(vo));
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TableDataInfo<IscAppServiceApplyVo> queryPageList(IscAppServiceApplyBo bo) {
|
||||||
|
PagePlus<IscAppServiceApply, IscAppServiceApplyVo> result = pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(bo));
|
||||||
|
genServiceNameAndApplicationName(result.getRecordsVo());
|
||||||
|
return PageUtils.buildDataInfo(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<IscAppServiceApplyVo> queryList(IscAppServiceApplyBo bo) {
|
||||||
|
List<IscAppServiceApplyVo> results = listVo(buildQueryWrapper(bo));
|
||||||
|
genServiceNameAndApplicationName(results);
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组装服务、应用名称
|
||||||
|
* @param list 申请记录
|
||||||
|
*/
|
||||||
|
private void genServiceNameAndApplicationName(List<IscAppServiceApplyVo> list)
|
||||||
|
{
|
||||||
|
if(CollectionUtil.isEmpty(list)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Set<Long> appServiceIds = list.stream().map(IscAppServiceApplyVo::getAppServiceId).collect(Collectors.toSet());
|
||||||
|
List<IscAppService> appServiceList = appServiceService.getAppServiceListByIds(appServiceIds);
|
||||||
|
if(CollectionUtil.isEmpty(appServiceList)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Map<Long, IscAppService> appServiceMap = appServiceList.stream()
|
||||||
|
.collect(Collectors.toMap(IscAppService::getAppServiceId, Function.identity()));
|
||||||
|
Map<Long, String> serviceNameMap = serviceService.getNameMap(appServiceList.stream()
|
||||||
|
.map(IscAppService::getServiceId).collect(Collectors.toSet()));
|
||||||
|
Map<Long, String> applicationNameMap = applicationService.getNameMap(appServiceList.stream()
|
||||||
|
.map(IscAppService::getApplicationId).collect(Collectors.toSet()));
|
||||||
|
for (IscAppServiceApplyVo vo : list) {
|
||||||
|
IscAppService appService = appServiceMap.get(vo.getAppServiceId());
|
||||||
|
if(Objects.isNull(appService)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
vo.setServiceName(serviceNameMap.get(appService.getServiceId()));
|
||||||
|
vo.setApplicationName(applicationNameMap.get(appService.getApplicationId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private LambdaQueryWrapper<IscAppServiceApply> buildQueryWrapper(IscAppServiceApplyBo bo) {
|
||||||
|
Map<String, Object> params = bo.getParams();
|
||||||
|
LambdaQueryWrapper<IscAppServiceApply> lqw = Wrappers.lambdaQuery();
|
||||||
|
lqw.eq(StringUtils.isNotBlank(bo.getApplyType()), IscAppServiceApply::getApplyType, bo.getApplyType());
|
||||||
|
lqw.eq(StringUtils.isNotBlank(bo.getStatus()), IscAppServiceApply::getStatus, bo.getStatus());
|
||||||
|
return lqw;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean insertByBo(IscAppServiceApplyBo bo) {
|
||||||
|
IscAppServiceApply add = BeanUtil.toBean(bo, IscAppServiceApply.class);
|
||||||
|
validEntityBeforeSave(add);
|
||||||
|
return save(add);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean updateByBo(IscAppServiceApplyBo bo) {
|
||||||
|
IscAppServiceApply update = BeanUtil.toBean(bo, IscAppServiceApply.class);
|
||||||
|
validEntityBeforeSave(update);
|
||||||
|
return updateById(update);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存前的数据校验
|
||||||
|
*
|
||||||
|
* @param entity 实体类数据
|
||||||
|
*/
|
||||||
|
private void validEntityBeforeSave(IscAppServiceApply entity){
|
||||||
|
//TODO 做一些数据校验,如唯一约束
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||||
|
if(isValid){
|
||||||
|
//TODO 做一些业务上的校验,判断是否需要校验
|
||||||
|
}
|
||||||
|
return removeByIds(ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean audit(IscAuditBo bo)
|
||||||
|
{
|
||||||
|
serviceService.checkAuditBO(bo);
|
||||||
|
boolean result = true;
|
||||||
|
for (Long id : bo.getIds())
|
||||||
|
{
|
||||||
|
IscAppServiceApply apply = getOne(Wrappers.<IscAppServiceApply>lambdaQuery()
|
||||||
|
.eq(IscAppServiceApply::getApplyId, id)
|
||||||
|
.eq(IscAppServiceApply::getStatus, Constants.AUDIT_WAIT), false);
|
||||||
|
if(Objects.isNull(apply)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result = updateById(new IscAppServiceApply().setApplyId(id).setStatus(bo.getStatus())
|
||||||
|
.setAuditMind(bo.getRemark()));
|
||||||
|
IscAppService appService = appServiceService.getById(apply.getAppServiceId());
|
||||||
|
Assert.notNull(appService, () -> new ServiceException("申请信息不存在"));
|
||||||
|
|
||||||
|
IscAppService updateData = null;
|
||||||
|
IscService service = null;
|
||||||
|
if(Constants.AUDIT_PASS.equals(bo.getStatus())) {
|
||||||
|
service = serviceService.getById(appService.getServiceId());
|
||||||
|
Assert.notNull(service, () -> new ServiceException("服务信息不存在"));
|
||||||
|
updateData = genAuditPassData(apply, appService, service, bo.getStatus());
|
||||||
|
updateData.setAuditMind(bo.getRemark());
|
||||||
|
}else{
|
||||||
|
//如果 应用服务 状态为不通过 时需要同步状态
|
||||||
|
updateData = genAuditRejectData(appService, bo);
|
||||||
|
}
|
||||||
|
if(Objects.nonNull(updateData)) {
|
||||||
|
result = appServiceService.updateById(updateData);
|
||||||
|
if(Objects.nonNull(service)) {
|
||||||
|
IscAppService dbAppService = appServiceService.getById(apply.getAppServiceId());
|
||||||
|
IscApplication application = applicationService.getById(dbAppService.getApplicationId());
|
||||||
|
RouteUtils.saveRule(RouteUtils.generateRule(dbAppService, application.getAccessKey()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审核通过处理
|
||||||
|
* @param apply 申请信息
|
||||||
|
* @param appService 应用服务信息
|
||||||
|
* @param service 服务信息
|
||||||
|
* @param status 操作状态
|
||||||
|
* @return 更新数据
|
||||||
|
*/
|
||||||
|
private IscAppService genAuditPassData(IscAppServiceApply apply, IscAppService appService, IscService service,
|
||||||
|
String status)
|
||||||
|
{
|
||||||
|
IscAppService updateData = new IscAppService().setAppServiceId(appService.getAppServiceId());
|
||||||
|
//如果是 服务申请 修改 应用服务 审核状态、生成虚拟地址、服务到期时间
|
||||||
|
//如果是续期申请 修改 服务到期时间
|
||||||
|
switch (apply.getApplyType()) {
|
||||||
|
case IscConstants.APPLY_TYPE_APPLY:
|
||||||
|
genServicePassInit(apply, appService, status, updateData, service);
|
||||||
|
break;
|
||||||
|
case IscConstants.APPLY_TYPE_MODIFY:
|
||||||
|
//如果 应用服务 状态不为通过 则修改状态(如果是通过:续期不能影响使用)
|
||||||
|
if(!Constants.AUDIT_PASS.equals(appService.getStatus())) {
|
||||||
|
genServicePassInit(apply, appService, status, updateData, service);
|
||||||
|
}
|
||||||
|
updateData.setQuotaDays(apply.getQuotaDays());
|
||||||
|
updateData.setQuotaHours(apply.getQuotaHours());
|
||||||
|
updateData.setQuotaMinutes(apply.getQuotaMinutes());
|
||||||
|
updateData.setQuotaSeconds(apply.getQuotaSeconds());
|
||||||
|
break;
|
||||||
|
case IscConstants.APPLY_TYPE_RENEWAL:
|
||||||
|
Date startDate = Objects.isNull(appService.getEndTime()) ? DateUtils.getNowDate() : appService.getEndTime();
|
||||||
|
updateData.setEndTime(DateUtils.beginOfDay(DateUtils.addMonths(startDate, apply.getRenewalDuration())));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ServiceException("申请类型异常");
|
||||||
|
}
|
||||||
|
return updateData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审核通过 初始化生成 虚拟地址、服务结束时间
|
||||||
|
* @param apply 申请信息
|
||||||
|
* @param appService 应用服务信息
|
||||||
|
* @param status 审核状态
|
||||||
|
* @param updateData 需要修改的数据
|
||||||
|
* @param service 服务信息
|
||||||
|
*/
|
||||||
|
private void genServicePassInit(IscAppServiceApply apply, IscAppService appService, String status,
|
||||||
|
IscAppService updateData, IscService service)
|
||||||
|
{
|
||||||
|
updateData.setStatus(status);
|
||||||
|
Integer renewalDuration = apply.getRenewalDuration();
|
||||||
|
//如果 申请时长为空,需要查询审核记录 中的审核时长
|
||||||
|
if(Objects.isNull(renewalDuration)) {
|
||||||
|
IscAppServiceApply log = getOne(Wrappers.<IscAppServiceApply>lambdaQuery()
|
||||||
|
.eq(IscAppServiceApply::getAppServiceId, appService.getAppServiceId())
|
||||||
|
.eq(IscAppServiceApply::getApplyType, IscConstants.APPLY_TYPE_APPLY)
|
||||||
|
.last("LIMIT 1"), false);
|
||||||
|
renewalDuration = Objects.nonNull(log) ? log.getRenewalDuration() : 1;
|
||||||
|
}
|
||||||
|
updateData.setEndTime(DateUtils.beginOfDay(DateUtils.addMonths(DateUtils.getNowDate(), renewalDuration)));
|
||||||
|
updateData.setVirtualAddr(RouteUtils.genVirtualAddrPath(service.getServiceAddr()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 审核不通过处理
|
||||||
|
* @param appService 应用服务信息
|
||||||
|
* @param bo 审核数据
|
||||||
|
* @return 需要更新的信息
|
||||||
|
*/
|
||||||
|
private IscAppService genAuditRejectData(IscAppService appService, IscAuditBo bo) {
|
||||||
|
if(!Constants.AUDIT_PASS.equals(appService.getStatus())) {
|
||||||
|
IscAppService updateData = new IscAppService().setAppServiceId(appService.getAppServiceId());
|
||||||
|
updateData.setStatus(bo.getStatus());
|
||||||
|
updateData.setAuditMind(bo.getRemark());
|
||||||
|
return updateData;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,262 @@
|
|||||||
|
package com.ruoyi.isc.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
|
import cn.hutool.core.lang.Assert;
|
||||||
|
import cn.hutool.core.lang.tree.Tree;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
|
||||||
|
import com.ruoyi.common.constant.Constants;
|
||||||
|
import com.ruoyi.common.constant.IscConstants;
|
||||||
|
import com.ruoyi.common.constant.UserConstants;
|
||||||
|
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
|
||||||
|
import com.ruoyi.common.core.page.PagePlus;
|
||||||
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
|
import com.ruoyi.common.utils.DateUtils;
|
||||||
|
import com.ruoyi.common.utils.PageUtils;
|
||||||
|
import com.ruoyi.common.utils.SecurityUtils;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.isc.common.utils.beans.IscRule;
|
||||||
|
import com.ruoyi.isc.domain.IscAppService;
|
||||||
|
import com.ruoyi.isc.domain.IscAppServiceApply;
|
||||||
|
import com.ruoyi.isc.domain.IscApplication;
|
||||||
|
import com.ruoyi.isc.domain.bo.IscAppServiceApplyBo;
|
||||||
|
import com.ruoyi.isc.domain.bo.IscAppServiceBo;
|
||||||
|
import com.ruoyi.isc.domain.vo.IscAppServiceVo;
|
||||||
|
import com.ruoyi.isc.mapper.IscAppServiceMapper;
|
||||||
|
import com.ruoyi.isc.service.IIscAppServiceApplyService;
|
||||||
|
import com.ruoyi.isc.service.IIscAppServiceService;
|
||||||
|
import com.ruoyi.isc.service.IIscApplicationService;
|
||||||
|
import com.ruoyi.isc.service.IIscServiceService;
|
||||||
|
import com.ruoyi.isc.utils.RouteUtils;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用服务Service业务层处理
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-09-08
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class IscAppServiceServiceImpl extends ServicePlusImpl<IscAppServiceMapper, IscAppService, IscAppServiceVo> implements IIscAppServiceService
|
||||||
|
{
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IIscServiceService serviceService;
|
||||||
|
@Resource
|
||||||
|
private IIscAppServiceApplyService applyService;
|
||||||
|
@Resource
|
||||||
|
private IIscApplicationService applicationService;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void init() {
|
||||||
|
refreshRules();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IscAppServiceVo queryById(Long appServiceId)
|
||||||
|
{
|
||||||
|
IscAppServiceVo vo = getVoById(appServiceId);
|
||||||
|
genServiceName(Arrays.asList(vo));
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TableDataInfo<IscAppServiceVo> queryPageList(IscAppServiceBo bo)
|
||||||
|
{
|
||||||
|
PagePlus<IscAppService, IscAppServiceVo> result = pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(bo));
|
||||||
|
genServiceName(result.getRecordsVo());
|
||||||
|
return PageUtils.buildDataInfo(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<IscAppServiceVo> queryList(IscAppServiceBo bo)
|
||||||
|
{
|
||||||
|
final List<IscAppServiceVo> results = listVo(buildQueryWrapper(bo));
|
||||||
|
genServiceName(results);
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组装服务名称
|
||||||
|
*
|
||||||
|
* @param results 应用服务列表
|
||||||
|
*/
|
||||||
|
private void genServiceName(List<IscAppServiceVo> results)
|
||||||
|
{
|
||||||
|
if (CollectionUtil.isEmpty(results)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Set<Long> serviceIds = results.stream().map(IscAppServiceVo::getServiceId).collect(Collectors.toSet());
|
||||||
|
Map<Long, String> nameMap = serviceService.getNameMap(serviceIds);
|
||||||
|
for (IscAppServiceVo result : results) {
|
||||||
|
result.setServiceName(nameMap.get(result.getServiceId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private LambdaQueryWrapper<IscAppService> buildQueryWrapper(IscAppServiceBo bo)
|
||||||
|
{
|
||||||
|
Map<String, Object> params = bo.getParams();
|
||||||
|
Long userId = SecurityUtils.getUserId();
|
||||||
|
LambdaQueryWrapper<IscAppService> lqw = Wrappers.lambdaQuery();
|
||||||
|
lqw.eq(bo.getServiceId() != null, IscAppService::getServiceId, bo.getServiceId());
|
||||||
|
lqw.eq(bo.getApplicationId() != null, IscAppService::getApplicationId, bo.getApplicationId());
|
||||||
|
lqw.eq(!SecurityUtils.isAdmin(userId), IscAppService::getUserId, userId);
|
||||||
|
lqw.eq(StringUtils.isNotBlank(bo.getEnabled()), IscAppService::getEnabled, bo.getEnabled());
|
||||||
|
lqw.eq(StringUtils.isNotBlank(bo.getStatus()), IscAppService::getStatus, bo.getStatus());
|
||||||
|
return lqw;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean insertByBo(IscAppServiceBo bo)
|
||||||
|
{
|
||||||
|
IscAppService add = BeanUtil.toBean(bo, IscAppService.class);
|
||||||
|
validEntityBeforeSave(add);
|
||||||
|
add.setStatus(Constants.AUDIT_WAIT);
|
||||||
|
add.setUserId(SecurityUtils.getUserId());
|
||||||
|
boolean result = save(add);
|
||||||
|
addApplyRecord(bo, IscConstants.APPLY_TYPE_APPLY, add.getAppServiceId());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean updateByBo(IscAppServiceBo bo)
|
||||||
|
{
|
||||||
|
IscAppService appService = getById(bo.getAppServiceId());
|
||||||
|
Assert.notNull(appService, () -> new ServiceException("申请信息不存在"));
|
||||||
|
IscAppService update = new IscAppService().setAppServiceId(bo.getAppServiceId());
|
||||||
|
validEntityBeforeSave(update);
|
||||||
|
boolean result = true;
|
||||||
|
boolean changeStatus = !Constants.AUDIT_PASS.equals(appService.getStatus());
|
||||||
|
boolean changeRemark = !IscConstants.APPLY_TYPE_RENEWAL.equals(bo.getApplyType());
|
||||||
|
if (changeStatus || changeRemark)
|
||||||
|
{
|
||||||
|
if (changeStatus)
|
||||||
|
{
|
||||||
|
update.setStatus(Constants.AUDIT_WAIT);
|
||||||
|
}
|
||||||
|
if (changeRemark)
|
||||||
|
{
|
||||||
|
update.setRemark(bo.getRemark());
|
||||||
|
}
|
||||||
|
result = updateById(update);
|
||||||
|
}
|
||||||
|
String applyType = IscConstants.APPLY_TYPE_RENEWAL.equals(bo.getApplyType())
|
||||||
|
? IscConstants.APPLY_TYPE_RENEWAL : IscConstants.APPLY_TYPE_MODIFY;
|
||||||
|
addApplyRecord(bo, applyType, bo.getAppServiceId());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存前的数据校验
|
||||||
|
*
|
||||||
|
* @param entity 实体类数据
|
||||||
|
*/
|
||||||
|
private void validEntityBeforeSave(IscAppService entity)
|
||||||
|
{
|
||||||
|
//判断是否有申请未审核
|
||||||
|
if (Objects.nonNull(entity.getAppServiceId())) {
|
||||||
|
long count = applyService.count(Wrappers.<IscAppServiceApply>lambdaQuery()
|
||||||
|
.eq(IscAppServiceApply::getAppServiceId, entity.getAppServiceId())
|
||||||
|
.eq(IscAppServiceApply::getStatus, Constants.AUDIT_WAIT));
|
||||||
|
Assert.isFalse(SqlHelper.retBool(count), () -> new ServiceException("有申请未审核, 不能再申请"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid)
|
||||||
|
{
|
||||||
|
if (isValid) {
|
||||||
|
//TODO 做一些业务上的校验,判断是否需要校验
|
||||||
|
}
|
||||||
|
applyService.remove(Wrappers.<IscAppServiceApply>lambdaQuery().in(IscAppServiceApply::getAppServiceId, ids));
|
||||||
|
return removeByIds(ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Tree<Long>> genAppServiceTree(Long applicationId)
|
||||||
|
{
|
||||||
|
List<Long> serviceIds = listObjs(Wrappers.<IscAppService>lambdaQuery()
|
||||||
|
.select(IscAppService::getServiceId)
|
||||||
|
.eq(IscAppService::getApplicationId, applicationId), o -> (Long) o);
|
||||||
|
return serviceService.genServiceTree(CollectionUtil.newHashSet(serviceIds));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<IscAppService> getAppServiceListByIds(Collection<Long> ids)
|
||||||
|
{
|
||||||
|
return list(Wrappers.<IscAppService>lambdaQuery()
|
||||||
|
.select(IscAppService::getAppServiceId, IscAppService::getApplicationId, IscAppService::getServiceId)
|
||||||
|
.in(IscAppService::getAppServiceId, ids));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refreshRules()
|
||||||
|
{
|
||||||
|
List<IscAppService> list = list(Wrappers.<IscAppService>lambdaQuery()
|
||||||
|
.eq(IscAppService::getEnabled, UserConstants.NORMAL)
|
||||||
|
.eq(IscAppService::getStatus, Constants.AUDIT_PASS)
|
||||||
|
.gt(IscAppService::getEndTime, DateUtils.getNowDate()));
|
||||||
|
if(CollectionUtil.isEmpty(list)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Set<Long> applicationIds = list.stream().map(IscAppService::getApplicationId).collect(Collectors.toSet());
|
||||||
|
Map<Long, String> accessKeyMap = applicationService.list(Wrappers.<IscApplication>lambdaQuery()
|
||||||
|
.select(IscApplication::getApplicationId, IscApplication::getAccessKey)
|
||||||
|
.in(IscApplication::getApplicationId, applicationIds)).stream()
|
||||||
|
.collect(Collectors.toMap(IscApplication::getApplicationId, IscApplication::getAccessKey));
|
||||||
|
List<IscRule> routes = new ArrayList<>();
|
||||||
|
|
||||||
|
for (IscAppService appService : list)
|
||||||
|
{
|
||||||
|
String ak = accessKeyMap.get(appService.getApplicationId());
|
||||||
|
if(StringUtils.isBlank(ak)) {
|
||||||
|
log.error("路由初始化失败: id:[{}],ak[{}]信息不存在!", appService.getAppServiceId(), appService.getApplicationId());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
routes.add(RouteUtils.generateRule(appService, ak));
|
||||||
|
}
|
||||||
|
RouteUtils.refreshRules(routes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加 服务申请记录
|
||||||
|
*
|
||||||
|
* @param appService 应用服务信息
|
||||||
|
* @param applyType 申请类型
|
||||||
|
* @param appServiceId 应用服务ID
|
||||||
|
* @return 是否添加成功
|
||||||
|
*/
|
||||||
|
private Boolean addApplyRecord(IscAppServiceBo appService, String applyType, Long appServiceId)
|
||||||
|
{
|
||||||
|
IscAppServiceApplyBo entity = new IscAppServiceApplyBo();
|
||||||
|
entity.setAppServiceId(appServiceId);
|
||||||
|
entity.setApplyType(applyType);
|
||||||
|
entity.setStatus(Constants.AUDIT_WAIT);
|
||||||
|
entity.setRemark(appService.getRemark());
|
||||||
|
switch (applyType) {
|
||||||
|
case IscConstants.APPLY_TYPE_APPLY:
|
||||||
|
case IscConstants.APPLY_TYPE_MODIFY:
|
||||||
|
entity.setRenewalDuration(appService.getRenewalDuration());
|
||||||
|
entity.setQuotaDays(appService.getQuotaDays());
|
||||||
|
entity.setQuotaHours(appService.getQuotaHours());
|
||||||
|
entity.setQuotaMinutes(appService.getQuotaMinutes());
|
||||||
|
entity.setQuotaSeconds(appService.getQuotaSeconds());
|
||||||
|
break;
|
||||||
|
case IscConstants.APPLY_TYPE_RENEWAL:
|
||||||
|
entity.setRenewalDuration(appService.getRenewalDuration());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
return applyService.insertByBo(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,106 @@
|
|||||||
|
package com.ruoyi.isc.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
|
import cn.hutool.core.map.MapUtil;
|
||||||
|
import cn.hutool.core.util.IdUtil;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
|
||||||
|
import com.ruoyi.common.core.page.PagePlus;
|
||||||
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
import com.ruoyi.common.utils.PageUtils;
|
||||||
|
import com.ruoyi.common.utils.SecurityUtils;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.isc.domain.IscApplication;
|
||||||
|
import com.ruoyi.isc.domain.bo.IscApplicationBo;
|
||||||
|
import com.ruoyi.isc.domain.vo.IscApplicationVo;
|
||||||
|
import com.ruoyi.isc.mapper.IscApplicationMapper;
|
||||||
|
import com.ruoyi.isc.service.IIscApplicationService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用信息Service业务层处理
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-09-08
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class IscApplicationServiceImpl extends ServicePlusImpl<IscApplicationMapper, IscApplication, IscApplicationVo> implements IIscApplicationService {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IscApplicationVo queryById(Long applicationId){
|
||||||
|
return getVoById(applicationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TableDataInfo<IscApplicationVo> queryPageList(IscApplicationBo bo) {
|
||||||
|
PagePlus<IscApplication, IscApplicationVo> result = pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(bo));
|
||||||
|
return PageUtils.buildDataInfo(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<IscApplicationVo> queryList(IscApplicationBo bo) {
|
||||||
|
return listVo(buildQueryWrapper(bo));
|
||||||
|
}
|
||||||
|
|
||||||
|
private LambdaQueryWrapper<IscApplication> buildQueryWrapper(IscApplicationBo bo) {
|
||||||
|
Map<String, Object> params = bo.getParams();
|
||||||
|
LambdaQueryWrapper<IscApplication> lqw = Wrappers.lambdaQuery();
|
||||||
|
lqw.like(StringUtils.isNotBlank(bo.getApplicationName()), IscApplication::getApplicationName, bo.getApplicationName());
|
||||||
|
lqw.eq(StringUtils.isNotBlank(bo.getAccessKey()), IscApplication::getAccessKey, bo.getAccessKey());
|
||||||
|
Long userId = SecurityUtils.getUserId();
|
||||||
|
lqw.eq(!SecurityUtils.isAdmin(userId), IscApplication::getUserId, userId);
|
||||||
|
return lqw;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean insertByBo(IscApplicationBo bo) {
|
||||||
|
IscApplication add = BeanUtil.toBean(bo, IscApplication.class);
|
||||||
|
validEntityBeforeSave(add);
|
||||||
|
add.setAccessKey(IdUtil.simpleUUID());
|
||||||
|
add.setUserId(SecurityUtils.getUserId());
|
||||||
|
return save(add);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean updateByBo(IscApplicationBo bo) {
|
||||||
|
IscApplication update = BeanUtil.toBean(bo, IscApplication.class);
|
||||||
|
validEntityBeforeSave(update);
|
||||||
|
return updateById(update);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存前的数据校验
|
||||||
|
*
|
||||||
|
* @param entity 实体类数据
|
||||||
|
*/
|
||||||
|
private void validEntityBeforeSave(IscApplication entity){
|
||||||
|
//TODO 做一些数据校验,如唯一约束
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||||
|
if(isValid){
|
||||||
|
//TODO 做一些业务上的校验,判断是否需要校验
|
||||||
|
}
|
||||||
|
return removeByIds(ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<Long, String> getNameMap(Collection<Long> applicationIds)
|
||||||
|
{
|
||||||
|
if(CollectionUtil.isEmpty(applicationIds)) {
|
||||||
|
return MapUtil.empty();
|
||||||
|
}
|
||||||
|
return list(Wrappers.<IscApplication>lambdaQuery()
|
||||||
|
.select(IscApplication::getApplicationId, IscApplication::getApplicationName)
|
||||||
|
.in(IscApplication::getApplicationId, applicationIds)).stream()
|
||||||
|
.collect(Collectors.toMap(IscApplication::getApplicationId, IscApplication::getApplicationName));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,221 @@
|
|||||||
|
package com.ruoyi.isc.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
|
import cn.hutool.core.lang.tree.Tree;
|
||||||
|
import cn.hutool.core.lang.tree.parser.NodeParser;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import com.ruoyi.common.constant.UserConstants;
|
||||||
|
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
|
||||||
|
import com.ruoyi.common.utils.FullPathUtils;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.common.utils.TreeUtils;
|
||||||
|
import com.ruoyi.isc.domain.IscService;
|
||||||
|
import com.ruoyi.isc.domain.IscServiceCate;
|
||||||
|
import com.ruoyi.isc.domain.bo.IscServiceCateBo;
|
||||||
|
import com.ruoyi.isc.domain.vo.IscServiceCateVo;
|
||||||
|
import com.ruoyi.isc.mapper.IscServiceCateMapper;
|
||||||
|
import com.ruoyi.isc.service.IIscServiceCateService;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务分类Service业务层处理
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-08-22
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class IscServiceCateServiceImpl extends ServicePlusImpl<IscServiceCateMapper, IscServiceCate, IscServiceCateVo> implements IIscServiceCateService {
|
||||||
|
|
||||||
|
public static final String FIELD_FULL_PATH = "fullPath";
|
||||||
|
public static final String FIELD_NODE_TYPE = "type";
|
||||||
|
public static final int NODE_TYPE_SERVICE = 1;
|
||||||
|
public static final int NODE_TYPE_CATE = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IscServiceCateVo queryById(Long cateId){
|
||||||
|
return getVoById(cateId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<IscServiceCateVo> queryList(IscServiceCateBo bo) {
|
||||||
|
return listVo(buildQueryWrapper(bo));
|
||||||
|
}
|
||||||
|
|
||||||
|
private LambdaQueryWrapper<IscServiceCate> buildQueryWrapper(IscServiceCateBo bo) {
|
||||||
|
Map<String, Object> params = bo.getParams();
|
||||||
|
LambdaQueryWrapper<IscServiceCate> lqw = Wrappers.lambdaQuery();
|
||||||
|
lqw.like(StringUtils.isNotBlank(bo.getCateName()), IscServiceCate::getCateName, bo.getCateName());
|
||||||
|
lqw.eq(StringUtils.isNotBlank(bo.getEnabled()), IscServiceCate::getEnabled, bo.getEnabled());
|
||||||
|
return lqw;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean insertByBo(IscServiceCateBo bo) {
|
||||||
|
IscServiceCate add = BeanUtil.toBean(bo, IscServiceCate.class);
|
||||||
|
validEntityBeforeSave(add);
|
||||||
|
add.setFullPath(getFullPath(bo.getParentId()));
|
||||||
|
return save(add);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过父ID生成 FULL_PATH
|
||||||
|
* @param parentId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private String getFullPath(Long parentId)
|
||||||
|
{
|
||||||
|
final boolean isRoot = parentId == 0L;
|
||||||
|
IscServiceCate cate = getOne(Wrappers.<IscServiceCate>lambdaQuery()
|
||||||
|
.select(IscServiceCate::getCateId, IscServiceCate::getFullPath)
|
||||||
|
.eq(isRoot, IscServiceCate::getParentId, 0L).and(!isRoot, w -> w
|
||||||
|
.eq(IscServiceCate::getParentId, parentId)
|
||||||
|
.or()
|
||||||
|
.eq(IscServiceCate::getCateId, parentId))
|
||||||
|
.orderByDesc(IscServiceCate::getFullPath)
|
||||||
|
.last("LIMIT 1"));
|
||||||
|
String parentFullPath = null;
|
||||||
|
String maxFullPath = null;
|
||||||
|
if(Objects.nonNull(cate)){
|
||||||
|
if(cate.getCateId().intValue() == parentId)
|
||||||
|
{
|
||||||
|
parentFullPath = cate.getFullPath();
|
||||||
|
}else{
|
||||||
|
maxFullPath = cate.getFullPath();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final String fullPath = FullPathUtils.genFullPath(parentFullPath, maxFullPath);
|
||||||
|
return fullPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean updateByBo(IscServiceCateBo bo) {
|
||||||
|
IscServiceCate update = BeanUtil.toBean(bo, IscServiceCate.class);
|
||||||
|
validEntityBeforeSave(update);
|
||||||
|
return updateById(update);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存前的数据校验
|
||||||
|
*
|
||||||
|
* @param entity 实体类数据
|
||||||
|
*/
|
||||||
|
private void validEntityBeforeSave(IscServiceCate entity){
|
||||||
|
//TODO 做一些数据校验,如唯一约束
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
|
||||||
|
if(isValid){
|
||||||
|
//TODO 做一些业务上的校验,判断是否需要校验
|
||||||
|
}
|
||||||
|
return removeByIds(ids);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<IscServiceCate> selectCateList()
|
||||||
|
{
|
||||||
|
return list(Wrappers.<IscServiceCate>lambdaQuery()
|
||||||
|
.eq(IscServiceCate::getEnabled, UserConstants.DICT_NORMAL)
|
||||||
|
.orderByAsc(IscServiceCate::getParentId)
|
||||||
|
.orderByAsc(IscServiceCate::getOrderNum));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> batchCateName(Set<String> fullPathList)
|
||||||
|
{
|
||||||
|
Map<String, String> results = new HashMap<>();
|
||||||
|
if(CollectionUtils.isEmpty(fullPathList)) {
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
final List<IscServiceCate> list = list(Wrappers.<IscServiceCate>lambdaQuery()
|
||||||
|
.select(IscServiceCate::getCateId, IscServiceCate::getCateName, IscServiceCate::getFullPath, IscServiceCate::getParentId)
|
||||||
|
.in(IscServiceCate::getFullPath, fullPathList));
|
||||||
|
Map<Long, String> cateNameMap = batchCateName(list);
|
||||||
|
for (IscServiceCate cate : list)
|
||||||
|
{
|
||||||
|
results.put(cate.getFullPath(), cateNameMap.get(cate.getCateId()));
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Tree<Long>> genCateTree(List<IscServiceCate> cates)
|
||||||
|
{
|
||||||
|
return genCateTree(cates, null, CollectionUtil.newHashSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Tree<Long>> genCateTree(List<IscServiceCate> cates, List<IscService> serviceList, Set<Long> exitsIds)
|
||||||
|
{
|
||||||
|
boolean isServiceTree = Objects.nonNull(serviceList);
|
||||||
|
final Map<String, List<IscService>> cateServiceMap = isServiceTree ? serviceList.stream()
|
||||||
|
.collect(Collectors.groupingBy(IscService::getCateFullPath)) : null;
|
||||||
|
|
||||||
|
NodeParser<IscServiceCate, Long> parser = (cate, tree) -> {
|
||||||
|
tree.setId(cate.getCateId());
|
||||||
|
tree.setParentId(cate.getParentId());
|
||||||
|
tree.setName(cate.getCateName());
|
||||||
|
tree.setWeight(cate.getOrderNum());
|
||||||
|
tree.putExtra(FIELD_FULL_PATH, cate.getFullPath());
|
||||||
|
if(isServiceTree) {
|
||||||
|
tree.putExtra(FIELD_NODE_TYPE, NODE_TYPE_CATE);
|
||||||
|
boolean exist = true;
|
||||||
|
List<IscService> services = cateServiceMap.get(cate.getFullPath());
|
||||||
|
if(CollectionUtil.isEmpty(services)) {
|
||||||
|
tree.putExtra(TreeUtils.FIELD_NODE_EXIST, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (int index = 0; index < services.size(); index++)
|
||||||
|
{
|
||||||
|
IscService service = services.get(index);
|
||||||
|
List<Tree<Long>> children = tree.getChildren();
|
||||||
|
if(Objects.isNull(children)) {
|
||||||
|
children = CollectionUtil.newArrayList();
|
||||||
|
tree.setChildren(children);
|
||||||
|
}
|
||||||
|
final Tree<Long> child = new Tree<>(TreeUtils.DEFAULT_TREE_NODE_CONFIG);
|
||||||
|
child.setId(service.getServiceId());
|
||||||
|
child.setName(service.getServiceName());
|
||||||
|
child.setWeight(index);
|
||||||
|
child.putExtra(FIELD_NODE_TYPE, NODE_TYPE_SERVICE);
|
||||||
|
boolean contains = exitsIds.contains(service.getServiceId());
|
||||||
|
child.putExtra(TreeUtils.FIELD_NODE_EXIST, contains);
|
||||||
|
children.add(child);
|
||||||
|
if(exist && !contains) {
|
||||||
|
exist = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tree.putExtra(TreeUtils.FIELD_NODE_EXIST, exist);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return TreeUtils.build(cates, TreeUtils.DEFAULT_PARENT_ID, parser, isServiceTree);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<Long, String> batchCateName(List<IscServiceCate> list) {
|
||||||
|
Map<Long, String> results = new HashMap<>();
|
||||||
|
final Set<Long> parentIds = list.stream().filter(m -> m.getParentId() != 0L).map(IscServiceCate::getParentId).collect(Collectors.toSet());
|
||||||
|
if(CollectionUtils.isNotEmpty(parentIds)) {
|
||||||
|
final List<IscServiceCate> parentList = list(Wrappers.<IscServiceCate>lambdaQuery()
|
||||||
|
.select(IscServiceCate::getCateId, IscServiceCate::getCateName, IscServiceCate::getFullPath, IscServiceCate::getParentId)
|
||||||
|
.in(IscServiceCate::getCateId, parentIds));
|
||||||
|
results.putAll(batchCateName(parentList));
|
||||||
|
}
|
||||||
|
for (IscServiceCate cate : list)
|
||||||
|
{
|
||||||
|
final String parentName = results.get(cate.getParentId());
|
||||||
|
if(StringUtils.isBlank(parentName)) {
|
||||||
|
results.put(cate.getCateId(), cate.getCateName());
|
||||||
|
}else{
|
||||||
|
results.put(cate.getCateId(), String.format("%s/%s", parentName, cate.getCateName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,236 @@
|
|||||||
|
package com.ruoyi.isc.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
|
import cn.hutool.core.collection.ListUtil;
|
||||||
|
import cn.hutool.core.lang.Assert;
|
||||||
|
import cn.hutool.core.lang.tree.Tree;
|
||||||
|
import cn.hutool.core.map.MapUtil;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||||
|
import com.ruoyi.common.constant.Constants;
|
||||||
|
import com.ruoyi.common.constant.IscConstants;
|
||||||
|
import com.ruoyi.common.constant.UserConstants;
|
||||||
|
import com.ruoyi.common.core.mybatisplus.core.ServicePlusImpl;
|
||||||
|
import com.ruoyi.common.core.page.PagePlus;
|
||||||
|
import com.ruoyi.common.core.page.TableDataInfo;
|
||||||
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
|
import com.ruoyi.common.utils.FullPathUtils;
|
||||||
|
import com.ruoyi.common.utils.PageUtils;
|
||||||
|
import com.ruoyi.common.utils.SecurityUtils;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.isc.domain.IscService;
|
||||||
|
import com.ruoyi.isc.domain.bo.IscAuditBo;
|
||||||
|
import com.ruoyi.isc.domain.bo.IscServiceBo;
|
||||||
|
import com.ruoyi.isc.domain.vo.IscServiceVo;
|
||||||
|
import com.ruoyi.isc.mapper.IscServiceMapper;
|
||||||
|
import com.ruoyi.isc.service.IIscServiceCateService;
|
||||||
|
import com.ruoyi.isc.service.IIscServiceService;
|
||||||
|
import com.ruoyi.isc.utils.RouteUtils;
|
||||||
|
import com.ruoyi.isc.utils.beans.IscRouteDefinition;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import javax.annotation.PostConstruct;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务信息Service业务层处理
|
||||||
|
*
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-08-22
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
public class IscServiceServiceImpl extends ServicePlusImpl<IscServiceMapper, IscService, IscServiceVo> implements IIscServiceService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IIscServiceCateService cateService;
|
||||||
|
|
||||||
|
@PostConstruct
|
||||||
|
public void init() {
|
||||||
|
refreshRoutes();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IscServiceVo queryById(Long serviceId)
|
||||||
|
{
|
||||||
|
final IscServiceVo vo = getVoById(serviceId);
|
||||||
|
genVoInfo(Arrays.asList(vo));
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TableDataInfo<IscServiceVo> queryPageList(IscServiceBo bo)
|
||||||
|
{
|
||||||
|
PagePlus<IscService, IscServiceVo> result = pageVo(PageUtils.buildPagePlus(), buildQueryWrapper(bo));
|
||||||
|
genVoInfo(result.getRecordsVo());
|
||||||
|
return PageUtils.buildDataInfo(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<IscServiceVo> queryList(IscServiceBo bo)
|
||||||
|
{
|
||||||
|
final List<IscServiceVo> results = listVo(buildQueryWrapper(bo));
|
||||||
|
genVoInfo(results);
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void genVoInfo(List<IscServiceVo> results)
|
||||||
|
{
|
||||||
|
if (CollectionUtils.isNotEmpty(results))
|
||||||
|
{
|
||||||
|
Map<String, String> cateNameMap = cateService.batchCateName(results.stream()
|
||||||
|
.map(IscServiceVo::getCateFullPath).collect(Collectors.toSet()));
|
||||||
|
for (IscServiceVo result : results)
|
||||||
|
{
|
||||||
|
result.setCateName(cateNameMap.get(result.getCateFullPath()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private LambdaQueryWrapper<IscService> buildQueryWrapper(IscServiceBo bo)
|
||||||
|
{
|
||||||
|
Map<String, Object> params = bo.getParams();
|
||||||
|
LambdaQueryWrapper<IscService> lqw = Wrappers.lambdaQuery();
|
||||||
|
lqw.like(StringUtils.isNotBlank(bo.getServiceName()), IscService::getServiceName, bo.getServiceName());
|
||||||
|
lqw.eq(StringUtils.isNotBlank(bo.getOnlineStatus()), IscService::getOnlineStatus, bo.getOnlineStatus());
|
||||||
|
lqw.eq(StringUtils.isNotBlank(bo.getStatus()), IscService::getStatus, bo.getStatus());
|
||||||
|
lqw.eq(StringUtils.isNotBlank(bo.getEnabled()), IscService::getEnabled, bo.getEnabled());
|
||||||
|
lqw.ge(StringUtils.isNotBlank(bo.getCateFullPath()), IscService::getCateFullPath, bo.getCateFullPath());
|
||||||
|
lqw.le(StringUtils.isNotBlank(bo.getCateFullPath()), IscService::getCateFullPath, FullPathUtils.genMaxFullPath(bo.getCateFullPath()));
|
||||||
|
Long userId = SecurityUtils.getUserId();
|
||||||
|
lqw.eq(!SecurityUtils.isAdmin(userId), IscService::getUserId, userId);
|
||||||
|
return lqw;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean insertByBo(IscServiceBo bo)
|
||||||
|
{
|
||||||
|
IscService add = BeanUtil.toBean(bo, IscService.class);
|
||||||
|
validEntityBeforeSave(add);
|
||||||
|
add.setUserId(SecurityUtils.getUserId());
|
||||||
|
add.setOnlineStatus(IscConstants.ONLINE_STATUS_ON);
|
||||||
|
add.setStatus(Constants.AUDIT_WAIT);
|
||||||
|
return save(add);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean updateByBo(IscServiceBo bo)
|
||||||
|
{
|
||||||
|
IscService update = BeanUtil.toBean(bo, IscService.class);
|
||||||
|
validEntityBeforeSave(update);
|
||||||
|
boolean result = updateById(update);
|
||||||
|
RouteUtils.updateRoute(RouteUtils.generateRoute(update));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存前的数据校验
|
||||||
|
*
|
||||||
|
* @param entity 实体类数据
|
||||||
|
*/
|
||||||
|
private void validEntityBeforeSave(IscService entity)
|
||||||
|
{
|
||||||
|
//TODO 做一些数据校验,如唯一约束
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid)
|
||||||
|
{
|
||||||
|
if (isValid)
|
||||||
|
{
|
||||||
|
//TODO 做一些业务上的校验,判断是否需要校验
|
||||||
|
}
|
||||||
|
boolean result = removeByIds(ids);
|
||||||
|
RouteUtils.deleteRoute(ids.stream().map(String::valueOf).collect(Collectors.toSet()));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<Long, String> getNameMap(Collection<Long> serviceIds)
|
||||||
|
{
|
||||||
|
if(CollectionUtil.isEmpty(serviceIds)) {
|
||||||
|
return MapUtil.empty();
|
||||||
|
}
|
||||||
|
return list(Wrappers.<IscService>lambdaQuery()
|
||||||
|
.select(IscService::getServiceId, IscService::getServiceName)
|
||||||
|
.in(IscService::getServiceId, serviceIds)).stream()
|
||||||
|
.collect(Collectors.toMap(IscService::getServiceId, IscService::getServiceName));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Tree<Long>> genServiceTree()
|
||||||
|
{
|
||||||
|
return genServiceTree(CollectionUtil.newHashSet());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Tree<Long>> genServiceTree(Set<Long> exitsIds)
|
||||||
|
{
|
||||||
|
List<IscService> serviceList = list(Wrappers.<IscService>lambdaQuery()
|
||||||
|
.select(IscService::getServiceId, IscService::getServiceName, IscService::getCateFullPath)
|
||||||
|
.eq(IscService::getStatus, Constants.AUDIT_PASS)
|
||||||
|
.eq(IscService::getEnabled, UserConstants.DICT_NORMAL)
|
||||||
|
.orderByDesc(IscService::getUpdateTime));
|
||||||
|
return cateService.genCateTree(cateService.selectCateList(), serviceList, exitsIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean audit(IscAuditBo bo)
|
||||||
|
{
|
||||||
|
checkAuditBO(bo);
|
||||||
|
boolean result = true;
|
||||||
|
boolean pass = Constants.AUDIT_PASS.equals(bo.getStatus());
|
||||||
|
Collection<IscRouteDefinition> routes = pass ? ListUtil.list(false) : null;
|
||||||
|
for (Long id : bo.getIds())
|
||||||
|
{
|
||||||
|
IscService service = getOne(Wrappers.<IscService>lambdaQuery()
|
||||||
|
.eq(IscService::getServiceId, id)
|
||||||
|
.eq(IscService::getStatus, Constants.AUDIT_WAIT), false);
|
||||||
|
if(Objects.isNull(service)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
result = updateById(new IscService().setServiceId(id).setStatus(bo.getStatus())
|
||||||
|
.setAuditMind(bo.getRemark()));
|
||||||
|
if(pass) {
|
||||||
|
//生成路由
|
||||||
|
routes.add(RouteUtils.generateRoute(service));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(pass) {
|
||||||
|
//保存路由信息
|
||||||
|
RouteUtils.saveRoute(routes);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkAuditBO(IscAuditBo bo)
|
||||||
|
{
|
||||||
|
switch (bo.getStatus()) {
|
||||||
|
case Constants.AUDIT_PASS:
|
||||||
|
break;
|
||||||
|
case Constants.AUDIT_REJECT:
|
||||||
|
Assert.notBlank(bo.getRemark(), () -> new ServiceException("审核意见不能为空"));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ServiceException("审核状态异常");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void refreshRoutes()
|
||||||
|
{
|
||||||
|
final List<IscService> serviceList = list(Wrappers.<IscService>lambdaQuery()
|
||||||
|
.select(IscService::getServiceId, IscService::getServiceAddr, IscService::getHiddenParams, IscService::getRequestMethod)
|
||||||
|
.eq(IscService::getStatus, Constants.AUDIT_PASS));
|
||||||
|
List<IscRouteDefinition> routes = new ArrayList<>();
|
||||||
|
for (IscService service : serviceList)
|
||||||
|
{
|
||||||
|
routes.add(RouteUtils.generateRoute(service));
|
||||||
|
}
|
||||||
|
RouteUtils.refreshRoute(routes);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,330 @@
|
|||||||
|
package com.ruoyi.isc.utils;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import com.ruoyi.common.exception.ServiceException;
|
||||||
|
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||||
|
import com.ruoyi.isc.common.constant.IscRedisKeys;
|
||||||
|
import com.ruoyi.isc.common.utils.GatewayUtils;
|
||||||
|
import com.ruoyi.isc.common.utils.beans.IscRule;
|
||||||
|
import com.ruoyi.isc.common.utils.beans.TopicMsg;
|
||||||
|
import com.ruoyi.isc.common.utils.beans.TopicMsg.Type;
|
||||||
|
import com.ruoyi.isc.domain.IscAppService;
|
||||||
|
import com.ruoyi.isc.domain.IscService;
|
||||||
|
import com.ruoyi.isc.utils.beans.*;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.redisson.api.RMap;
|
||||||
|
import org.redisson.api.RTopic;
|
||||||
|
import org.redisson.api.RedissonClient;
|
||||||
|
import org.redisson.client.codec.Codec;
|
||||||
|
import org.redisson.codec.TypedJsonJacksonCodec;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static com.ruoyi.isc.common.constant.IscGatewayContants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021/9/10 14:46
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class RouteUtils {
|
||||||
|
|
||||||
|
public static final Codec ROUTE_CODES_INSTANCE = new TypedJsonJacksonCodec(String.class, IscRouteDefinition.class);
|
||||||
|
/**
|
||||||
|
* Gateway 虚拟路径前缀
|
||||||
|
*/
|
||||||
|
public static final String PATH_PREFIX = "/proxy";
|
||||||
|
private static final RedissonClient CLIENT = SpringUtils.getBean(RedissonClient.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取虚拟URL Path 部分
|
||||||
|
*
|
||||||
|
* @param serviceAddr 服务地址
|
||||||
|
* @return 虚拟地址Path
|
||||||
|
*/
|
||||||
|
public static String genVirtualAddrPath(String serviceAddr)
|
||||||
|
{
|
||||||
|
return PATH_PREFIX + getPathUri(serviceAddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回URI 的Path部分
|
||||||
|
*
|
||||||
|
* @param uri URI
|
||||||
|
* @return path
|
||||||
|
*/
|
||||||
|
public static String getPathUri(String uri)
|
||||||
|
{
|
||||||
|
return getURI(uri).getPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过 URI字符串 生成URI对象
|
||||||
|
*
|
||||||
|
* @param uri URI字符串
|
||||||
|
* @return URI
|
||||||
|
*/
|
||||||
|
public static URI getURI(String uri)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return new URI(uri);
|
||||||
|
} catch (URISyntaxException e)
|
||||||
|
{
|
||||||
|
throw new ServiceException("URL格式异常");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发布通道消息
|
||||||
|
*
|
||||||
|
* @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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发布路由刷新通知
|
||||||
|
* @param consumer 发送消息后执行
|
||||||
|
*/
|
||||||
|
public static void sendRefreshRouteToGateway(String id, Type type, Consumer<TopicMsg> consumer) {
|
||||||
|
publish(TOPIC_GATEWAY_REFRESH_ROUTE, new TopicMsg(id, DateUtil.now(), type), consumer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发布规则通知
|
||||||
|
* @param consumer 发送消息后执行
|
||||||
|
*/
|
||||||
|
public static void sendRuleNoticeToGateway(String id, Type type, Consumer<TopicMsg> consumer) {
|
||||||
|
publish(TOPIC_GATEWAY_RULE, new TopicMsg(id, DateUtil.now(), type), consumer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新路由信息 先清空再批量新增
|
||||||
|
*
|
||||||
|
* @param routes 路由信息
|
||||||
|
* @return 是否成功
|
||||||
|
*/
|
||||||
|
public static boolean refreshRoute(List<IscRouteDefinition> routes)
|
||||||
|
{
|
||||||
|
Map<String, IscRouteDefinition> routeMap = routes.stream().collect(Collectors.toMap(IscRouteDefinition::getId,
|
||||||
|
Function.identity(), (o1, o2) -> o2));
|
||||||
|
final RMap<String, IscRouteDefinition> map = CLIENT.getMap(IscRedisKeys.KEY_ROUTES, ROUTE_CODES_INSTANCE);
|
||||||
|
map.clear();
|
||||||
|
map.putAll(routeMap);
|
||||||
|
sendRefreshRouteToGateway(null, TopicMsg.Type.REFRESH,
|
||||||
|
(msg) -> log.info("路由刷新完成,通知网关刷新路由![{}]", msg.getMsg()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存路由信息
|
||||||
|
*
|
||||||
|
* @param routes 路由信息
|
||||||
|
* @return 是否成功
|
||||||
|
*/
|
||||||
|
public static boolean saveRoute(Collection<IscRouteDefinition> routes) {
|
||||||
|
return saveRoute(routes, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存路由信息
|
||||||
|
*
|
||||||
|
* @param routes 路由信息
|
||||||
|
* @param consumer 回调操作
|
||||||
|
* @return 是否成功
|
||||||
|
*/
|
||||||
|
public static boolean saveRoute(Collection<IscRouteDefinition> routes, Consumer<TopicMsg> consumer)
|
||||||
|
{
|
||||||
|
if(CollectionUtil.isEmpty(routes)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
final RMap<String, IscRouteDefinition> map = CLIENT.getMap(IscRedisKeys.KEY_ROUTES, ROUTE_CODES_INSTANCE);
|
||||||
|
Map<String, IscRouteDefinition> collect = routes.stream().collect(Collectors.toMap(IscRouteDefinition::getId, Function.identity()));
|
||||||
|
map.putAll(collect);
|
||||||
|
final String id = String.join(",", collect.keySet());
|
||||||
|
Type type = Type.UPDATE;
|
||||||
|
if(Objects.isNull(consumer)) {
|
||||||
|
type = Type.ADD;
|
||||||
|
consumer = (msg) -> log.info("保存[{}]路由[{}]完成,通知网关刷新路由![{}]", msg.getType(), msg.getId(), msg.getMsg());
|
||||||
|
}
|
||||||
|
sendRefreshRouteToGateway(id, type, consumer);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除路由信息
|
||||||
|
*
|
||||||
|
* @param routeIds 路由ID
|
||||||
|
* @return 是否成功
|
||||||
|
*/
|
||||||
|
public static boolean deleteRoute(Collection<String> routeIds)
|
||||||
|
{
|
||||||
|
final RMap<String, IscRouteDefinition> map = CLIENT.getMap(IscRedisKeys.KEY_ROUTES, ROUTE_CODES_INSTANCE);
|
||||||
|
final String[] ids = routeIds.toArray(new String[0]);
|
||||||
|
map.fastRemove(ids);
|
||||||
|
final String id = String.join(",", routeIds);
|
||||||
|
sendRefreshRouteToGateway(id, Type.DELETE,
|
||||||
|
(msg) -> log.info("删除[{}]路由[{}]完成,通知网关刷新路由![{}]", msg.getType(), msg.getId(), msg.getMsg()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新路由信息
|
||||||
|
*
|
||||||
|
* @param route 路由信息
|
||||||
|
* @return 是否成功
|
||||||
|
*/
|
||||||
|
public static boolean updateRoute(IscRouteDefinition route)
|
||||||
|
{
|
||||||
|
return saveRoute(Collections.singletonList(route),
|
||||||
|
(msg) -> log.info("保存[{}]路由[{}]完成,通知网关刷新路由![{}]", msg.getType(), msg.getId(), msg.getMsg()));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成 路由信息
|
||||||
|
*
|
||||||
|
* @param service 服务信息
|
||||||
|
* @return 路由信息
|
||||||
|
*/
|
||||||
|
public static IscRouteDefinition generateRoute(IscService service)
|
||||||
|
{
|
||||||
|
IscRouteDefinition route = new IscRouteDefinition();
|
||||||
|
route.setId(String.valueOf(service.getServiceId()));
|
||||||
|
final String serviceAddr = service.getServiceAddr();
|
||||||
|
route.setUri(getURI(serviceAddr.substring(0, serviceAddr.length() - getPathUri(serviceAddr).length())));
|
||||||
|
|
||||||
|
//断言
|
||||||
|
IscPredicateDefinition methodPredicate = new IscPredicateDefinition();
|
||||||
|
methodPredicate.setName("Method");
|
||||||
|
methodPredicate.getArgs().put("methods", service.getRequestMethod());
|
||||||
|
|
||||||
|
IscPredicateDefinition pathPredicate = new IscPredicateDefinition();
|
||||||
|
pathPredicate.setName("Path");
|
||||||
|
pathPredicate.getArgs().put("pattern", genVirtualAddrPath(service.getServiceAddr()));
|
||||||
|
route.setPredicates(Arrays.asList(methodPredicate, pathPredicate));
|
||||||
|
|
||||||
|
//过滤器
|
||||||
|
List<IscFilterDefinition> filters = new ArrayList<>();
|
||||||
|
IscFilterDefinition stripPrefixFilter = new IscFilterDefinition();
|
||||||
|
stripPrefixFilter.setName("StripPrefix");
|
||||||
|
stripPrefixFilter.getArgs().put("parts", "1");
|
||||||
|
filters.add(stripPrefixFilter);
|
||||||
|
|
||||||
|
IscFilterDefinition retryFilter = new IscFilterDefinition();
|
||||||
|
retryFilter.setName("Retry");
|
||||||
|
retryFilter.getArgs().put("retries", "1");
|
||||||
|
filters.add(retryFilter);
|
||||||
|
route.setFilters(filters);
|
||||||
|
|
||||||
|
//其他信息
|
||||||
|
Map<String, Object> metadata = route.getMetadata();
|
||||||
|
metadata.put(CONFIG_ACCESS_KEY_NAME_KEY, ACCESS_KEY_NAME_DEFAULT);
|
||||||
|
metadata.put(CONFIG_ADD_PARAM_KEY, service.getHiddenParams());
|
||||||
|
return route;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 生成 服务对应AK调用规则
|
||||||
|
*
|
||||||
|
* @param appService 服务申请信息
|
||||||
|
* @param accessKey AccessKey
|
||||||
|
* @return 规则信息
|
||||||
|
*/
|
||||||
|
public static IscRule generateRule(IscAppService appService, String accessKey)
|
||||||
|
{
|
||||||
|
IscRule rule = new IscRule();
|
||||||
|
rule.setId(GatewayUtils.getRouteKey(accessKey, appService.getServiceId()));
|
||||||
|
rule.setExpire(appService.getEndTime());
|
||||||
|
rule.setDaysLimit(appService.getQuotaDays());
|
||||||
|
rule.setHoursLimit(appService.getQuotaHours());
|
||||||
|
rule.setMinutesLimit(appService.getQuotaMinutes());
|
||||||
|
rule.setSecondsLimit(appService.getQuotaSeconds());
|
||||||
|
return rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 刷新规则信息 先清空再批量新增
|
||||||
|
*
|
||||||
|
* @param rules 规则信息
|
||||||
|
* @return 是否成功
|
||||||
|
*/
|
||||||
|
public static boolean refreshRules(List<IscRule> rules)
|
||||||
|
{
|
||||||
|
Map<String, IscRule> ruleMap = rules.stream().collect(Collectors.toMap(IscRule::getId, Function.identity(), (o1, o2) -> o2));
|
||||||
|
final RMap<String, IscRule> map = CLIENT.getMap(IscRedisKeys.KEY_RULES, RULE_CODES_INSTANCE);
|
||||||
|
map.clear();
|
||||||
|
map.putAll(ruleMap);
|
||||||
|
final String id = String.join(",", ruleMap.keySet());
|
||||||
|
sendRuleNoticeToGateway(id, Type.REFRESH,
|
||||||
|
(msg) -> log.info("刷新[{}]所有规则[{}]完成,通知网关刷新规则![{}]", msg.getType(), msg.getId(), msg.getMsg()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存规则信息
|
||||||
|
*
|
||||||
|
* @param rule 规则信息
|
||||||
|
* @return 是否成功
|
||||||
|
*/
|
||||||
|
public static boolean saveRule(IscRule rule) {
|
||||||
|
return saveRule(rule, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存规则信息
|
||||||
|
*
|
||||||
|
* @param rule 规则信息
|
||||||
|
* @param consumer 回调
|
||||||
|
* @return 是否成功
|
||||||
|
*/
|
||||||
|
public static boolean saveRule(IscRule rule, Consumer<TopicMsg> consumer)
|
||||||
|
{
|
||||||
|
final RMap<String, IscRule> map = CLIENT.getMap(IscRedisKeys.KEY_RULES, RULE_CODES_INSTANCE);
|
||||||
|
map.put(rule.getId(), rule);
|
||||||
|
Type type = Type.UPDATE;
|
||||||
|
if(Objects.isNull(consumer)) {
|
||||||
|
type = Type.ADD;
|
||||||
|
consumer = (msg) -> log.info("新增[{}]规则[{}]完成,通知网关刷新规则![{}]", msg.getType(), msg.getId(), msg.getMsg());
|
||||||
|
}
|
||||||
|
sendRuleNoticeToGateway(rule.getId(), type, consumer);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除规则信息
|
||||||
|
*
|
||||||
|
* @param ruleId 规则ID
|
||||||
|
* @return 是否成功
|
||||||
|
*/
|
||||||
|
public static boolean deleteRule(String ruleId)
|
||||||
|
{
|
||||||
|
final RMap<String, IscRule> map = CLIENT.getMap(IscRedisKeys.KEY_RULES, RULE_CODES_INSTANCE);
|
||||||
|
map.remove(ruleId);
|
||||||
|
sendRuleNoticeToGateway(ruleId, Type.DELETE,
|
||||||
|
(msg) -> log.info("删除[{}]规则[{}]完成,通知网关刷新规则![{}]", msg.getType(), msg.getId(), msg.getMsg()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新规则信息
|
||||||
|
*
|
||||||
|
* @param rule 规则信息
|
||||||
|
* @return 是否成功
|
||||||
|
*/
|
||||||
|
public static boolean updateRule(IscRule rule)
|
||||||
|
{
|
||||||
|
return saveRule(rule,
|
||||||
|
(msg) -> log.info("更新[{}]规则[{}]完成,通知网关刷新规则![{}]", msg.getType(), msg.getId(), msg.getMsg()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
package com.ruoyi.isc.utils.beans;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-09-28
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Validated
|
||||||
|
public class IscFilterDefinition {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private Map<String, String> args = new LinkedHashMap<>();
|
||||||
|
}
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
package com.ruoyi.isc.utils.beans;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-09-28
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Validated
|
||||||
|
public class IscPredicateDefinition {
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private Map<String, String> args = new LinkedHashMap<>();
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
package com.ruoyi.isc.utils.beans;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import javax.validation.constraints.NotEmpty;
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Wenchao Gong
|
||||||
|
* @date 2021-09-28
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Validated
|
||||||
|
public class IscRouteDefinition {
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@NotEmpty
|
||||||
|
@Valid
|
||||||
|
private List<IscPredicateDefinition> predicates = new ArrayList<>();
|
||||||
|
|
||||||
|
@Valid
|
||||||
|
private List<IscFilterDefinition> filters = new ArrayList<>();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private URI uri;
|
||||||
|
|
||||||
|
private Map<String, Object> metadata = new HashMap<>();
|
||||||
|
|
||||||
|
private int order = 0;
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user