commit
27da4e7d20
|
|
@ -2,7 +2,7 @@
|
|||
<configuration default="false" name="ruoyi-auth" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="ruoyi/ruoyi-auth:2.1.2" />
|
||||
<option name="imageTag" value="ruoyi/ruoyi-auth:2.2.0" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-auth/Dockerfile" />
|
||||
</settings>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<configuration default="false" name="ruoyi-gateway" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="ruoyi/ruoyi-gateway:2.1.2" />
|
||||
<option name="imageTag" value="ruoyi/ruoyi-gateway:2.2.0" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-gateway/Dockerfile" />
|
||||
</settings>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<configuration default="false" name="ruoyi-gen" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="ruoyi/ruoyi-gen:2.1.2" />
|
||||
<option name="imageTag" value="ruoyi/ruoyi-gen:2.2.0" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-modules/ruoyi-gen/Dockerfile" />
|
||||
</settings>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<configuration default="false" name="ruoyi-job" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="ruoyi/ruoyi-job:2.1.2" />
|
||||
<option name="imageTag" value="ruoyi/ruoyi-job:2.2.0" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-modules/ruoyi-job/Dockerfile" />
|
||||
</settings>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<configuration default="false" name="ruoyi-monitor" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="ruoyi/ruoyi-monitor:2.1.2" />
|
||||
<option name="imageTag" value="ruoyi/ruoyi-monitor:2.2.0" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-visual/ruoyi-monitor/Dockerfile" />
|
||||
</settings>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<configuration default="false" name="ruoyi-nacos" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="ruoyi/ruoyi-nacos:2.1.2" />
|
||||
<option name="imageTag" value="ruoyi/ruoyi-nacos:2.2.0" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-visual/ruoyi-nacos/Dockerfile" />
|
||||
</settings>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<configuration default="false" name="ruoyi-resource" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="ruoyi/ruoyi-resource:2.1.2" />
|
||||
<option name="imageTag" value="ruoyi/ruoyi-resource:2.2.0" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-modules/ruoyi-resource/Dockerfile" />
|
||||
</settings>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<configuration default="false" name="ruoyi-seata-server" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="ruoyi/ruoyi-seata-server:2.1.2" />
|
||||
<option name="imageTag" value="ruoyi/ruoyi-seata-server:2.2.0" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-visual/ruoyi-seata-server/Dockerfile" />
|
||||
</settings>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<configuration default="false" name="ruoyi-sentinel-dashboard" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="ruoyi/ruoyi-sentinel-dashboard:2.1.2" />
|
||||
<option name="imageTag" value="ruoyi/ruoyi-sentinel-dashboard:2.2.0" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-visual/ruoyi-sentinel-dashboard/Dockerfile" />
|
||||
</settings>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="ruoyi-powerjob-server" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<configuration default="false" name="ruoyi-snailjob-server" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="ruoyi/ruoyi-powerjob-server:2.1.2" />
|
||||
<option name="imageTag" value="ruoyi/ruoyi-snailjob-server:2.2.0" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-visual/ruoyi-powerjob-server/Dockerfile" />
|
||||
<option name="sourceFilePath" value="ruoyi-visual/ruoyi-snailjob-server/Dockerfile" />
|
||||
</settings>
|
||||
</deployment>
|
||||
<method v="2" />
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
<configuration default="false" name="ruoyi-system" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="ruoyi/ruoyi-system:2.1.2" />
|
||||
<option name="imageTag" value="ruoyi/ruoyi-system:2.2.0" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-modules/ruoyi-system/Dockerfile" />
|
||||
</settings>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="ruoyi-workflow" type="docker-deploy" factoryName="dockerfile" server-name="Docker">
|
||||
<deployment type="dockerfile">
|
||||
<settings>
|
||||
<option name="imageTag" value="ruoyi/ruoyi-workflow:2.2.0" />
|
||||
<option name="buildOnly" value="true" />
|
||||
<option name="sourceFilePath" value="ruoyi-modules/ruoyi-workflow/Dockerfile" />
|
||||
</settings>
|
||||
</deployment>
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
12
README.md
12
README.md
|
|
@ -9,7 +9,7 @@
|
|||
[](https://gitee.com/dromara/RuoYi-Cloud-Plus/blob/master/LICENSE)
|
||||
[](https://www.jetbrains.com/?from=RuoYi-Cloud-Plus)
|
||||
<br>
|
||||
[](https://gitee.com/dromara/RuoYi-Cloud-Plus)
|
||||
[](https://gitee.com/dromara/RuoYi-Cloud-Plus)
|
||||
[]()
|
||||
[]()
|
||||
[]()
|
||||
|
|
@ -27,8 +27,10 @@
|
|||
|
||||
## 赞助商
|
||||
|
||||
MaxKey - https://gitee.com/dromara/MaxKey <br>
|
||||
CCFlow - https://gitee.com/opencc/RuoYi-JFlow <br>
|
||||
MaxKey 业界领先单点登录产品 - https://gitee.com/dromara/MaxKey <br>
|
||||
CCFlow 驰聘低代码-流程-表单 - https://gitee.com/opencc/RuoYi-JFlow <br>
|
||||
数舵科技 软件定制开发APP小程序等 - http://www.shuduokeji.com/ <br>
|
||||
引迈信息 软件开发平台 - https://www.jnpfsoft.com/index.html?from=plus-doc <br>
|
||||
[如何成为赞助商 加群联系作者详谈](https://plus-doc.dromara.org/#/common/add_group)
|
||||
|
||||
# 本框架与RuoYi的功能差异
|
||||
|
|
@ -66,10 +68,10 @@ CCFlow - https://gitee.com/opencc/RuoYi-JFlow <br>
|
|||
| WebSocket协议 | 基于 Spring 封装的 WebSocket 协议 扩展了Token鉴权与分布式会话同步 不再只是基于单机的废物 | 无 |
|
||||
| 序列化 | 采用 Jackson Spring官方内置序列化 靠谱!!! | 采用 fastjson bugjson 远近闻名 |
|
||||
| 分布式幂等 | 参考美团GTIS防重系统简化实现(细节可看文档) | 手动编写注解基于aop实现 |
|
||||
| 分布式任务调度 | 采用 PowerJob 天生支持分布式 统一的管理中心 底层基于JPA实现 支持多种数据库 | 采用 Quartz 基于数据库锁性能差 集群需要做很多配置与改造 |
|
||||
| 分布式任务调度 | 采用 SnailJob 天生支持分布式 统一的管理中心 支持多种数据库 支持分片重试DAG任务流等 | 采用 Quartz 基于数据库锁性能差 集群需要做很多配置与改造 |
|
||||
| 分布式日志中心 | 采用 ELK 业界成熟解决方案 实时收集所有服务的运行日志 快速发现定位问题 | 无 |
|
||||
| 分布式搜索引擎 | 采用 ElasticSearch、Easy-Es 以 Mybatis-Plus 方式操作 ElasticSearch | 无 |
|
||||
| 分布式消息队列 | 采用 SpringCloud-Stream 支持 Kafka、RocketMQ、RabbitMQ | 无 |
|
||||
| 分布式消息队列 | 采用 支持 Kafka、RocketMQ、RabbitMQ 各种 延迟消息 事务消息 流消息 | 无 |
|
||||
| 分库分表功能 | 采用 Apache Sharding-Proxy 代理服务无入侵支持分库分表 只需编写分库分表规则即可 | 无 |
|
||||
| 文件存储 | 采用 Minio 分布式文件存储 天生支持多机、多硬盘、多分片、多副本存储<br/>支持权限管理 安全可靠 文件可加密存储 | 采用 本机文件存储 文件裸漏 易丢失泄漏 不支持集群有单点效应 |
|
||||
| 云存储 | 采用 AWS S3 协议客户端 支持 七牛、阿里、腾讯 等一切支持S3协议的厂家 | 不支持 |
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -30,9 +30,6 @@ dubbo:
|
|||
consumer:
|
||||
# 超时时间
|
||||
timeout: 3000
|
||||
scan:
|
||||
# 接口实现类扫描
|
||||
base-packages: org.dromara.**.dubbo
|
||||
# 自定义配置
|
||||
custom:
|
||||
# 全局请求log
|
||||
|
|
@ -41,6 +38,10 @@ dubbo:
|
|||
log-level: info
|
||||
|
||||
spring:
|
||||
threads:
|
||||
# 开启虚拟线程 仅jdk21可用
|
||||
virtual:
|
||||
enabled: false
|
||||
# 资源信息
|
||||
messages:
|
||||
# 国际化资源文件路径
|
||||
|
|
@ -52,6 +53,8 @@ spring:
|
|||
# 上传单个文件大小限制
|
||||
max-file-size: 10MB
|
||||
mvc:
|
||||
# 设置静态资源路径 防止所有请求都去查静态资源
|
||||
static-path-pattern: /static/**
|
||||
format:
|
||||
date-time: yyyy-MM-dd HH:mm:ss
|
||||
#jackson配置
|
||||
|
|
@ -141,7 +144,10 @@ logging:
|
|||
org.springframework: warn
|
||||
org.apache.dubbo: warn
|
||||
com.alibaba.nacos: warn
|
||||
tech.powerjob.worker.background: warn
|
||||
org.mybatis.spring.mapper: error
|
||||
org.apache.dubbo.config: error
|
||||
# 临时处理 spring 调整日志级别导致启动警告问题 不影响使用等待 alibaba 适配
|
||||
org.springframework.context.support.PostProcessorRegistrationDelegate: error
|
||||
config: classpath:logback-plus.xml
|
||||
|
||||
# Sa-Token配置
|
||||
|
|
@ -160,8 +166,7 @@ sa-token:
|
|||
# MyBatisPlus配置
|
||||
# https://baomidou.com/config/
|
||||
mybatis-plus:
|
||||
# 不支持多包, 如有需要可在注解配置 或 提升扫包等级
|
||||
# 例如 com.**.**.mapper
|
||||
# 多包名使用 例如 org.dromara.**.mapper,org.xxx.**.mapper
|
||||
mapperPackage: org.dromara.**.mapper
|
||||
# 对应的 XML 文件位置
|
||||
mapperLocations: classpath*:mapper/**/*Mapper.xml
|
||||
|
|
|
|||
|
|
@ -13,6 +13,10 @@ datasource:
|
|||
url: jdbc:mysql://localhost:3306/ry-job?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
|
||||
username: root
|
||||
password: password
|
||||
workflow:
|
||||
url: jdbc:mysql://localhost:3306/ry-workflow?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
|
||||
username: root
|
||||
password: password
|
||||
# system-oracle:
|
||||
# url: jdbc:oracle:thin:@//localhost:1521/XE
|
||||
# username: ROOT
|
||||
|
|
|
|||
|
|
@ -21,9 +21,8 @@ user:
|
|||
# 密码锁定时间(默认10分钟)
|
||||
lockTime: 10
|
||||
|
||||
--- # 三方授权
|
||||
# 三方授权
|
||||
justauth:
|
||||
enabled: true
|
||||
# 前端外网访问地址
|
||||
address: http://localhost:80
|
||||
type:
|
||||
|
|
@ -34,6 +33,13 @@ justauth:
|
|||
client-id: 876892492581044224
|
||||
client-secret: x1Y5MTMwNzIwMjMxNTM4NDc3Mzche8
|
||||
redirect-uri: ${justauth.address}/social-callback?source=maxkey
|
||||
topiam:
|
||||
# topiam 服务器地址
|
||||
server-url: http://127.0.0.1:1989/api/v1/authorize/y0q************spq***********8ol
|
||||
client-id: 449c4*********937************759
|
||||
client-secret: ac7***********1e0************28d
|
||||
redirect-uri: ${justauth.address}/social-callback?source=topiam
|
||||
scopes: [ openid, email, phone, profile ]
|
||||
qq:
|
||||
client-id: 10**********6
|
||||
client-secret: 1f7d08**********5b7**********29e
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ security:
|
|||
enabled: true
|
||||
excludeUrls:
|
||||
- /system/notice
|
||||
- /workflow/model/editModelXml
|
||||
# 不校验白名单
|
||||
ignore:
|
||||
whites:
|
||||
|
|
@ -59,6 +60,11 @@ spring:
|
|||
- Path=/resource/**
|
||||
filters:
|
||||
- StripPrefix=1
|
||||
# workflow服务
|
||||
- id: ruoyi-workflow
|
||||
uri: lb://ruoyi-workflow
|
||||
predicates:
|
||||
- Path=/workflow/**
|
||||
# 演示服务
|
||||
- id: ruoyi-demo
|
||||
uri: lb://ruoyi-demo
|
||||
|
|
@ -67,10 +73,10 @@ spring:
|
|||
filters:
|
||||
- StripPrefix=1
|
||||
# MQ演示服务
|
||||
- id: ruoyi-stream-mq
|
||||
uri: lb://ruoyi-stream-mq
|
||||
- id: ruoyi-test-mq
|
||||
uri: lb://ruoyi-test-mq
|
||||
predicates:
|
||||
- Path=/stream-mq/**
|
||||
- Path=/test-mq/**
|
||||
filters:
|
||||
- StripPrefix=1
|
||||
|
||||
|
|
|
|||
|
|
@ -13,21 +13,17 @@ spring:
|
|||
username: ${datasource.job.username}
|
||||
password: ${datasource.job.password}
|
||||
|
||||
# powerjob 配置
|
||||
powerjob:
|
||||
worker:
|
||||
# 如何开启调度中心请查看文档教程
|
||||
enabled: true
|
||||
# 需要先在 powerjob 登录页执行应用注册后才能使用
|
||||
app-name: ruoyi-worker
|
||||
allow-lazy-connect-server: false
|
||||
max-appended-wf-context-length: 4096
|
||||
max-result-length: 4096
|
||||
# 29203 端口 随着主应用端口飘逸 避免集群冲突
|
||||
port: 2${server.port}
|
||||
protocol: http
|
||||
# 调度中心地址:如调度中心集群部署存在多个地址则用逗号分隔。
|
||||
# server-address: 127.0.0.1:7700
|
||||
# 调度中心应用名 通过服务名连接调度中心(启用 server-name 会导致 server-address 不生效)
|
||||
server-name: ruoyi-powerjob-server
|
||||
store-strategy: disk
|
||||
snail-job:
|
||||
enabled: true
|
||||
# 需要在 SnailJob 后台组管理创建对应名称的组,然后创建任务的时候选择对应的组,才能正确分派任务
|
||||
group: "ruoyi_group"
|
||||
# SnailJob 接入验证令牌
|
||||
token: "SJ_cKqBTPzCsWA3VyuCfFoccmuIEGXjr5KT"
|
||||
server:
|
||||
# 从 nacos 获取服务
|
||||
server-name: ruoyi-snailjob-server
|
||||
# 服务名优先 ip垫底
|
||||
host: 127.0.0.1
|
||||
port: 1788
|
||||
# 详见 script/sql/ry_job.sql `sj_namespace` 表
|
||||
namespace: ${spring.profiles.active}
|
||||
|
|
|
|||
|
|
@ -1,47 +0,0 @@
|
|||
oms.env=${spring.profiles.active}
|
||||
|
||||
####### Database properties(Configure according to the the environment) #######
|
||||
spring.datasource.core.driver-class-name=com.mysql.cj.jdbc.Driver
|
||||
spring.datasource.core.jdbc-url=${datasource.job.url}
|
||||
spring.datasource.core.username=${datasource.job.username}
|
||||
spring.datasource.core.password=${datasource.job.password}
|
||||
spring.datasource.core.maximum-pool-size=20
|
||||
spring.datasource.core.minimum-idle=5
|
||||
|
||||
####### MongoDB properties(Non-core configuration properties) #######
|
||||
####### delete mongodb config to disable mongodb #######
|
||||
oms.mongodb.enable=false
|
||||
#spring.data.mongodb.uri=mongodb+srv://zqq:No1Bug2Please3!@cluster0.wie54.gcp.mongodb.net/powerjob_daily?retryWrites=true&w=majority
|
||||
|
||||
####### Email properties(Non-core configuration properties) #######
|
||||
####### Delete the following code to disable the mail #######
|
||||
#spring.mail.host=smtp.163.com
|
||||
#spring.mail.username=zqq@163.com
|
||||
#spring.mail.password=GOFZPNARMVKCGONV
|
||||
#spring.mail.properties.mail.smtp.auth=true
|
||||
#spring.mail.properties.mail.smtp.starttls.enable=true
|
||||
#spring.mail.properties.mail.smtp.starttls.required=true
|
||||
|
||||
####### DingTalk properties(Non-core configuration properties) #######
|
||||
####### Delete the following code to disable the DingTalk #######
|
||||
#oms.alarm.ding.app-key=dingauqwkvxxnqskknfv
|
||||
#oms.alarm.ding.app-secret=XWrEPdAZMPgJeFtHuL0LH73LRj-74umF2_0BFcoXMfvnX0pCQvt0rpb1JOJU_HLl
|
||||
#oms.alarm.ding.agent-id=847044348
|
||||
|
||||
####### Resource cleaning properties #######
|
||||
oms.instanceinfo.retention=1
|
||||
oms.container.retention.local=1
|
||||
oms.container.retention.remote=-1
|
||||
|
||||
####### Cache properties #######
|
||||
oms.instance.metadata.cache.size=1024
|
||||
|
||||
# 生产配置
|
||||
#oms.instanceinfo.retention=7
|
||||
#oms.container.retention.local=7
|
||||
#oms.container.retention.remote=-1
|
||||
#oms.instance.metadata.cache.size=2048
|
||||
|
||||
####### Threshold in precise fetching server(0~100). 100 means full detection of server, in which #######
|
||||
####### split-brain could be avoided while performance overhead would increase. #######
|
||||
oms.accurate.select.server.percentage = 50
|
||||
|
|
@ -54,28 +54,33 @@ mail:
|
|||
connectionTimeout: 0
|
||||
|
||||
# sms 短信 支持 阿里云 腾讯云 云片 等等各式各样的短信服务商
|
||||
# https://wind.kim/doc/start 文档地址 各个厂商可同时使用
|
||||
# https://sms4j.com/doc3/ 差异配置文档地址 支持单厂商多配置,可以配置多个同时使用
|
||||
sms:
|
||||
# 阿里云 dysmsapi.aliyuncs.com
|
||||
alibaba:
|
||||
#请求地址 默认为 dysmsapi.aliyuncs.com 如无特殊改变可以不用设置
|
||||
requestUrl: dysmsapi.aliyuncs.com
|
||||
#阿里云的accessKey
|
||||
accessKeyId: xxxxxxx
|
||||
#阿里云的accessKeySecret
|
||||
accessKeySecret: xxxxxxx
|
||||
#短信签名
|
||||
signature: 测试
|
||||
tencent:
|
||||
#请求地址默认为 sms.tencentcloudapi.com 如无特殊改变可不用设置
|
||||
requestUrl: sms.tencentcloudapi.com
|
||||
#腾讯云的accessKey
|
||||
accessKeyId: xxxxxxx
|
||||
#腾讯云的accessKeySecret
|
||||
accessKeySecret: xxxxxxx
|
||||
#短信签名
|
||||
signature: 测试
|
||||
#短信sdkAppId
|
||||
sdkAppId: appid
|
||||
#地域信息默认为 ap-guangzhou 如无特殊改变可不用设置
|
||||
territory: ap-guangzhou
|
||||
# 配置源类型用于标定配置来源(interface,yaml)
|
||||
config-type: yaml
|
||||
# 用于标定yml中的配置是否开启短信拦截,接口配置不受此限制
|
||||
restricted: true
|
||||
# 短信拦截限制单手机号每分钟最大发送,只对开启了拦截的配置有效
|
||||
minute-max: 1
|
||||
# 短信拦截限制单手机号每日最大发送量,只对开启了拦截的配置有效
|
||||
account-max: 30
|
||||
# 以下配置来自于 org.dromara.sms4j.provider.config.BaseConfig类中
|
||||
blends:
|
||||
# 唯一ID 用于发送短信寻找具体配置 随便定义别用中文即可
|
||||
# 可以同时存在两个相同厂商 例如: ali1 ali2 两个不同的阿里短信账号 也可用于区分租户
|
||||
config1:
|
||||
# 框架定义的厂商名称标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分
|
||||
supplier: alibaba
|
||||
# 有些称为accessKey有些称之为apiKey,也有称为sdkKey或者appId。
|
||||
access-key-id: 您的accessKey
|
||||
# 称为accessSecret有些称之为apiSecret
|
||||
access-key-secret: 您的accessKeySecret
|
||||
signature: 您的短信签名
|
||||
sdk-app-id: 您的sdkAppId
|
||||
config2:
|
||||
# 厂商标识,标定此配置是哪个厂商,详细请看厂商标识介绍部分
|
||||
supplier: tencent
|
||||
access-key-id: 您的accessKey
|
||||
access-key-secret: 您的accessKeySecret
|
||||
signature: 您的短信签名
|
||||
sdk-app-id: 您的sdkAppId
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
spring:
|
||||
datasource:
|
||||
type: com.zaxxer.hikari.HikariDataSource
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: ${datasource.job.url}
|
||||
username: ${datasource.job.username}
|
||||
password: ${datasource.job.password}
|
||||
hikari:
|
||||
connection-timeout: 30000
|
||||
validation-timeout: 5000
|
||||
minimum-idle: 10
|
||||
maximum-pool-size: 20
|
||||
idle-timeout: 600000
|
||||
max-lifetime: 900000
|
||||
keepaliveTime: 30000
|
||||
|
||||
# snail-job 服务端配置
|
||||
snail-job:
|
||||
# 拉取重试数据的每批次的大小
|
||||
retry-pull-page-size: 1000
|
||||
# 拉取重试数据的每批次的大小
|
||||
job-pull-page-size: 1000
|
||||
# 服务端 netty 端口
|
||||
netty-port: 1788
|
||||
# 重试和死信表的分区总数
|
||||
total-partition: 2
|
||||
# 一个客户端每秒最多接收的重试数量指令
|
||||
limiter: 1000
|
||||
# 号段模式下步长配置
|
||||
step: 100
|
||||
# 日志保存时间(单位: day)
|
||||
log-storage: 90
|
||||
# 回调配置
|
||||
callback:
|
||||
#回调最大执行次数
|
||||
max-count: 288
|
||||
#间隔时间
|
||||
trigger-interval: 900
|
||||
retry-max-pull-count: 10
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
spring:
|
||||
datasource:
|
||||
dynamic:
|
||||
# 设置默认的数据源或者数据源组,默认值即为 master
|
||||
primary: master
|
||||
datasource:
|
||||
# 主库数据源
|
||||
master:
|
||||
type: ${spring.datasource.type}
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: ${datasource.workflow.url}
|
||||
username: ${datasource.workflow.username}
|
||||
password: ${datasource.workflow.password}
|
||||
# oracle:
|
||||
# type: ${spring.datasource.type}
|
||||
# driverClassName: oracle.jdbc.OracleDriver
|
||||
# url: ${datasource.system-oracle.url}
|
||||
# username: ${datasource.system-oracle.username}
|
||||
# password: ${datasource.system-oracle.password}
|
||||
# postgres:
|
||||
# type: ${spring.datasource.type}
|
||||
# driverClassName: org.postgresql.Driver
|
||||
# url: ${datasource.system-postgres.url}
|
||||
# username: ${datasource.system-postgres.username}
|
||||
# password: ${datasource.system-postgres.password}
|
||||
|
||||
# flowable配置
|
||||
flowable:
|
||||
# 关闭定时任务JOB
|
||||
async-executor-activate: false
|
||||
# 将databaseSchemaUpdate设置为true。当Flowable发现库与数据库表结构不一致时,会自动将数据库表结构升级至新版本。
|
||||
database-schema-update: true
|
||||
activity-font-name: 宋体
|
||||
label-font-name: 宋体
|
||||
annotation-font-name: 宋体
|
||||
# 关闭各个模块生成表,目前只使用工作流基础表
|
||||
idm:
|
||||
enabled: false
|
||||
cmmn:
|
||||
enabled: false
|
||||
dmn:
|
||||
enabled: false
|
||||
app:
|
||||
enabled: false
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
service.vgroupMapping.ruoyi-auth-group=default
|
||||
service.vgroupMapping.ruoyi-system-group=default
|
||||
service.vgroupMapping.ruoyi-resource-group=default
|
||||
service.vgroupMapping.ruoyi-workflow-group=default
|
||||
|
||||
service.enableDegrade=false
|
||||
service.disableGlobalTransaction=false
|
||||
|
|
@ -10,7 +11,7 @@ store.mode=db
|
|||
store.lock.mode=db
|
||||
store.session.mode=db
|
||||
#Used for password encryption
|
||||
store.publicKey=
|
||||
#store.publicKey=
|
||||
|
||||
#These configurations are required if the `store mode` is `db`. If `store.mode,store.lock.mode,store.session.mode` are not equal to `db`, you can remove the configuration block.
|
||||
store.db.datasource=hikari
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ services:
|
|||
network_mode: "host"
|
||||
|
||||
nacos:
|
||||
image: ruoyi/ruoyi-nacos:2.1.2
|
||||
image: ruoyi/ruoyi-nacos:2.2.0
|
||||
container_name: nacos
|
||||
ports:
|
||||
- "8848:8848"
|
||||
|
|
@ -96,7 +96,7 @@ services:
|
|||
network_mode: "host"
|
||||
|
||||
seata-server:
|
||||
image: ruoyi/ruoyi-seata-server:2.1.2
|
||||
image: ruoyi/ruoyi-seata-server:2.2.0
|
||||
container_name: seata-server
|
||||
ports:
|
||||
- "7091:7091"
|
||||
|
|
@ -135,7 +135,7 @@ services:
|
|||
network_mode: "host"
|
||||
|
||||
sentinel:
|
||||
image: ruoyi/ruoyi-sentinel-dashboard:2.1.2
|
||||
image: ruoyi/ruoyi-sentinel-dashboard:2.2.0
|
||||
container_name: sentinel
|
||||
environment:
|
||||
TZ: Asia/Shanghai
|
||||
|
|
@ -150,7 +150,7 @@ services:
|
|||
network_mode: "host"
|
||||
|
||||
ruoyi-monitor:
|
||||
image: ruoyi/ruoyi-monitor:2.1.2
|
||||
image: ruoyi/ruoyi-monitor:2.2.0
|
||||
container_name: ruoyi-monitor
|
||||
environment:
|
||||
# 时区上海
|
||||
|
|
@ -165,23 +165,22 @@ services:
|
|||
privileged: true
|
||||
network_mode: "host"
|
||||
|
||||
ruoyi-powerjob-server:
|
||||
image: ruoyi/ruoyi-powerjob-server:2.1.2
|
||||
container_name: ruoyi-powerjob-server
|
||||
ruoyi-snailjob-server:
|
||||
image: ruoyi/ruoyi-snailjob-server:2.2.0
|
||||
container_name: ruoyi-snailjob-server
|
||||
environment:
|
||||
# 时区上海
|
||||
TZ: Asia/Shanghai
|
||||
ports:
|
||||
- "7700:7700"
|
||||
- "10086:10086"
|
||||
- "10010:10010"
|
||||
- "8800:8800"
|
||||
- "1788:1788"
|
||||
volumes:
|
||||
- /docker/powerjob/logs/:/ruoyi/powerjob/logs
|
||||
- /docker/snailjob/logs/:/ruoyi/snailjob/logs
|
||||
privileged: true
|
||||
network_mode: "host"
|
||||
|
||||
ruoyi-gateway:
|
||||
image: ruoyi/ruoyi-gateway:2.1.2
|
||||
image: ruoyi/ruoyi-gateway:2.2.0
|
||||
container_name: ruoyi-gateway
|
||||
environment:
|
||||
# 时区上海
|
||||
|
|
@ -197,7 +196,7 @@ services:
|
|||
network_mode: "host"
|
||||
|
||||
ruoyi-auth:
|
||||
image: ruoyi/ruoyi-auth:2.1.2
|
||||
image: ruoyi/ruoyi-auth:2.2.0
|
||||
container_name: ruoyi-auth
|
||||
environment:
|
||||
# 时区上海
|
||||
|
|
@ -213,7 +212,7 @@ services:
|
|||
network_mode: "host"
|
||||
|
||||
ruoyi-system:
|
||||
image: ruoyi/ruoyi-system:2.1.2
|
||||
image: ruoyi/ruoyi-system:2.2.0
|
||||
container_name: ruoyi-system
|
||||
environment:
|
||||
# 时区上海
|
||||
|
|
@ -229,7 +228,7 @@ services:
|
|||
network_mode: "host"
|
||||
|
||||
ruoyi-gen:
|
||||
image: ruoyi/ruoyi-gen:2.1.2
|
||||
image: ruoyi/ruoyi-gen:2.2.0
|
||||
container_name: ruoyi-gen
|
||||
environment:
|
||||
# 时区上海
|
||||
|
|
@ -245,7 +244,7 @@ services:
|
|||
network_mode: "host"
|
||||
|
||||
ruoyi-job:
|
||||
image: ruoyi/ruoyi-job:2.1.2
|
||||
image: ruoyi/ruoyi-job:2.2.0
|
||||
container_name: ruoyi-job
|
||||
environment:
|
||||
# 时区上海
|
||||
|
|
@ -261,7 +260,7 @@ services:
|
|||
network_mode: "host"
|
||||
|
||||
ruoyi-resource:
|
||||
image: ruoyi/ruoyi-resource:2.1.2
|
||||
image: ruoyi/ruoyi-resource:2.2.0
|
||||
container_name: ruoyi-resource
|
||||
environment:
|
||||
# 时区上海
|
||||
|
|
@ -276,6 +275,22 @@ services:
|
|||
privileged: true
|
||||
network_mode: "host"
|
||||
|
||||
ruoyi-workflow:
|
||||
image: ruoyi/ruoyi-workflow:2.2.0
|
||||
container_name: ruoyi-workflow
|
||||
environment:
|
||||
# 时区上海
|
||||
TZ: Asia/Shanghai
|
||||
ports:
|
||||
- "9205:9205"
|
||||
volumes:
|
||||
# 配置文件
|
||||
- /docker/ruoyi-workflow/logs/:/ruoyi/workflow/logs
|
||||
# skywalking 探针
|
||||
- /docker/skywalking/agent/:/ruoyi/skywalking/agent
|
||||
privileged: true
|
||||
network_mode: "host"
|
||||
|
||||
|
||||
#################################################################################################
|
||||
#################################### 以下为扩展根据需求搭建 #########################################
|
||||
|
|
@ -328,9 +343,9 @@ services:
|
|||
- elasticsearch
|
||||
network_mode: "host"
|
||||
|
||||
mqnamesrv:
|
||||
image: apache/rocketmq:4.9.4
|
||||
container_name: mqnamesrv
|
||||
rmqnamesrv:
|
||||
image: apache/rocketmq:5.2.0
|
||||
container_name: rmqnamesrv
|
||||
ports:
|
||||
- "9876:9876"
|
||||
environment:
|
||||
|
|
@ -340,25 +355,25 @@ services:
|
|||
- /docker/rocketmq/namesrv/logs:/home/rocketmq/logs/rocketmqlogs
|
||||
network_mode: "host"
|
||||
|
||||
mqbroker1:
|
||||
image: apache/rocketmq:4.9.4
|
||||
container_name: mqbroker1
|
||||
rmqbroker1:
|
||||
image: apache/rocketmq:5.2.0
|
||||
container_name: rmqbroker1
|
||||
ports:
|
||||
- "10911:10911"
|
||||
- "10909:10909"
|
||||
- "10912:10912"
|
||||
environment:
|
||||
JAVA_OPT_EXT: -server -Xms512M -Xmx512M -Xmn256m
|
||||
command: sh mqbroker -c /home/rocketmq/rocketmq-4.9.4/conf/broker.conf
|
||||
command: sh mqbroker --enable-proxy -c /home/rocketmq/rocketmq-5.2.0/conf/broker.conf
|
||||
depends_on:
|
||||
- mqnamesrv
|
||||
volumes:
|
||||
- /docker/rocketmq/broker1/conf/broker.conf:/home/rocketmq/rocketmq-4.9.4/conf/broker.conf
|
||||
- /docker/rocketmq/broker1/conf/broker.conf:/home/rocketmq/rocketmq-5.2.0/conf/broker.conf
|
||||
- /docker/rocketmq/broker1/logs:/home/rocketmq/logs/rocketmqlogs
|
||||
- /docker/rocketmq/broker1/store:/home/rocketmq/store
|
||||
network_mode: "host"
|
||||
|
||||
mqconsole:
|
||||
rmqconsole:
|
||||
image: styletang/rocketmq-console-ng
|
||||
container_name: mqconsole
|
||||
ports:
|
||||
|
|
@ -366,11 +381,11 @@ services:
|
|||
environment:
|
||||
JAVA_OPTS: -Dserver.port=19876 -Drocketmq.namesrv.addr=127.0.0.1:9876 -Dcom.rocketmq.sendMessageWithVIPChannel=false
|
||||
depends_on:
|
||||
- mqnamesrv
|
||||
- rmqnamesrv
|
||||
network_mode: "host"
|
||||
|
||||
rabbitmq:
|
||||
image: rabbitmq:3.10.6
|
||||
image: rabbitmq:3.13.3
|
||||
container_name: rabbitmq
|
||||
build:
|
||||
context: ./rabbitmq
|
||||
|
|
@ -402,7 +417,7 @@ services:
|
|||
network_mode: "host"
|
||||
|
||||
kafka:
|
||||
image: 'bitnami/kafka:3.2.0'
|
||||
image: 'bitnami/kafka:3.6.2'
|
||||
container_name: kafka
|
||||
ports:
|
||||
- "9092:9092"
|
||||
|
|
|
|||
|
|
@ -78,11 +78,6 @@ http {
|
|||
proxy_pass http://server/;
|
||||
}
|
||||
|
||||
# 解决 powerjob 代理之后静态文件无法访问的问题 请勿修改乱动
|
||||
location ~ ^/(js|css|jpg|png|svg|woff|ttf|ico|img)/ {
|
||||
proxy_pass http://powerjob-server;
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
location = /50x.html {
|
||||
root html;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
FROM rabbitmq:3.10.6-management
|
||||
FROM rabbitmq:3.13.3-management
|
||||
|
||||
MAINTAINER Lion Li
|
||||
|
||||
ADD ./rabbitmq_delayed_message_exchange-3.10.2.ez /plugins
|
||||
ADD ./rabbitmq_delayed_message_exchange-3.13.0.ez /plugins
|
||||
|
||||
RUN rabbitmq-plugins enable rabbitmq_delayed_message_exchange
|
||||
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
107
pom.xml
107
pom.xml
|
|
@ -13,37 +13,36 @@
|
|||
<description>RuoYi-Cloud-Plus微服务系统</description>
|
||||
|
||||
<properties>
|
||||
<revision>2.1.2</revision>
|
||||
<revision>2.2.0-BETA</revision>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>17</java.version>
|
||||
<spring-boot.version>3.1.7</spring-boot.version>
|
||||
<spring-cloud.version>2022.0.4</spring-cloud.version>
|
||||
<spring-boot-admin.version>3.1.8</spring-boot-admin.version>
|
||||
<spring-boot.mybatis>3.0.3</spring-boot.mybatis>
|
||||
<mybatis.version>3.5.13</mybatis.version>
|
||||
<mybatis-plus.version>3.5.4</mybatis-plus.version>
|
||||
<spring-boot.version>3.2.6</spring-boot.version>
|
||||
<spring-cloud.version>2023.0.2</spring-cloud.version>
|
||||
<spring-boot-admin.version>3.2.3</spring-boot-admin.version>
|
||||
<mybatis.version>3.5.16</mybatis.version>
|
||||
<mybatis-plus.version>3.5.6</mybatis-plus.version>
|
||||
<p6spy.version>3.9.1</p6spy.version>
|
||||
<dynamic-ds.version>4.2.0</dynamic-ds.version>
|
||||
<dynamic-ds.version>4.3.0</dynamic-ds.version>
|
||||
<velocity.version>2.3</velocity.version>
|
||||
<swagger.core.version>2.2.15</swagger.core.version>
|
||||
<springdoc.version>2.2.0</springdoc.version>
|
||||
<swagger.core.version>2.2.21</swagger.core.version>
|
||||
<springdoc.version>2.5.0</springdoc.version>
|
||||
<therapi-javadoc.version>0.15.0</therapi-javadoc.version>
|
||||
<poi.version>5.2.3</poi.version>
|
||||
<easyexcel.version>3.3.3</easyexcel.version>
|
||||
<hutool.version>5.8.22</hutool.version>
|
||||
<redisson.version>3.24.3</redisson.version>
|
||||
<lock4j.version>2.2.5</lock4j.version>
|
||||
<powerjob.version>4.3.6</powerjob.version>
|
||||
<satoken.version>1.37.0</satoken.version>
|
||||
<lombok.version>1.18.30</lombok.version>
|
||||
<easyexcel.version>3.3.4</easyexcel.version>
|
||||
<hutool.version>5.8.27</hutool.version>
|
||||
<redisson.version>3.29.0</redisson.version>
|
||||
<lock4j.version>2.2.7</lock4j.version>
|
||||
<snailjob.version>1.0.0-beta3</snailjob.version>
|
||||
<satoken.version>1.38.0</satoken.version>
|
||||
<lombok.version>1.18.32</lombok.version>
|
||||
<logstash.version>7.4</logstash.version>
|
||||
<easy-es.version>2.0.0-beta4</easy-es.version>
|
||||
<easy-es.version>2.0.0</easy-es.version>
|
||||
<elasticsearch.version>7.14.0</elasticsearch.version>
|
||||
<skywalking-toolkit.version>8.16.0</skywalking-toolkit.version>
|
||||
<bouncycastle.version>1.76</bouncycastle.version>
|
||||
<alibaba-ttl.version>2.14.4</alibaba-ttl.version>
|
||||
<mapstruct-plus.version>1.3.5</mapstruct-plus.version>
|
||||
<mapstruct-plus.version>1.3.6</mapstruct-plus.version>
|
||||
<mapstruct-plus.lombok.version>0.2.0</mapstruct-plus.lombok.version>
|
||||
<justauth.version>1.16.6</justauth.version>
|
||||
<!-- 离线IP地址定位库 -->
|
||||
|
|
@ -52,11 +51,16 @@
|
|||
<fastjson.version>1.2.83</fastjson.version>
|
||||
|
||||
<!-- OSS 配置 -->
|
||||
<aws-java-sdk-s3.version>1.12.600</aws-java-sdk-s3.version>
|
||||
<aws.sdk.version>2.25.15</aws.sdk.version>
|
||||
<aws.crt.version>0.29.13</aws.crt.version>
|
||||
<okhttp.version>4.10.0</okhttp.version>
|
||||
|
||||
<!-- SMS 配置 -->
|
||||
<sms4j.version>2.2.0</sms4j.version>
|
||||
<sms4j.version>3.2.1</sms4j.version>
|
||||
<!-- 工作流配置 -->
|
||||
<flowable.version>7.0.0</flowable.version>
|
||||
<!-- mq配置 -->
|
||||
<rocketmq.version>2.3.0</rocketmq.version>
|
||||
|
||||
<!-- 插件版本 -->
|
||||
<maven-compiler-plugin.verison>3.11.0</maven-compiler-plugin.verison>
|
||||
|
|
@ -73,6 +77,8 @@
|
|||
<nacos.server>127.0.0.1:8848</nacos.server>
|
||||
<nacos.discovery.group>DEFAULT_GROUP</nacos.discovery.group>
|
||||
<nacos.config.group>DEFAULT_GROUP</nacos.config.group>
|
||||
<nacos.username>nacos</nacos.username>
|
||||
<nacos.password>nacos</nacos.password>
|
||||
<logstash.address>127.0.0.1:4560</logstash.address>
|
||||
</properties>
|
||||
<activation>
|
||||
|
|
@ -87,6 +93,8 @@
|
|||
<nacos.server>127.0.0.1:8848</nacos.server>
|
||||
<nacos.discovery.group>DEFAULT_GROUP</nacos.discovery.group>
|
||||
<nacos.config.group>DEFAULT_GROUP</nacos.config.group>
|
||||
<nacos.username>nacos</nacos.username>
|
||||
<nacos.password>nacos</nacos.password>
|
||||
<logstash.address>127.0.0.1:4560</logstash.address>
|
||||
</properties>
|
||||
</profile>
|
||||
|
|
@ -157,6 +165,14 @@
|
|||
<scope>import</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.flowable</groupId>
|
||||
<artifactId>flowable-bom</artifactId>
|
||||
<version>${flowable.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-core</artifactId>
|
||||
|
|
@ -169,13 +185,6 @@
|
|||
<version>${satoken.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Mybatis 依赖配置 -->
|
||||
<dependency>
|
||||
<groupId>org.mybatis.spring.boot</groupId>
|
||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||
<version>${spring-boot.mybatis}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis</artifactId>
|
||||
|
|
@ -184,7 +193,7 @@
|
|||
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
||||
<version>${mybatis-plus.version}</version>
|
||||
</dependency>
|
||||
|
||||
|
|
@ -266,16 +275,16 @@
|
|||
<version>${lock4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- PowerJob -->
|
||||
<!-- SnailJob Client -->
|
||||
<dependency>
|
||||
<groupId>tech.powerjob</groupId>
|
||||
<artifactId>powerjob-worker</artifactId>
|
||||
<version>${powerjob.version}</version>
|
||||
<groupId>com.aizuda</groupId>
|
||||
<artifactId>snail-job-client-starter</artifactId>
|
||||
<version>${snailjob.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>tech.powerjob</groupId>
|
||||
<artifactId>powerjob-official-processors</artifactId>
|
||||
<version>${powerjob.version}</version>
|
||||
<groupId>com.aizuda</groupId>
|
||||
<artifactId>snail-job-client-job-core</artifactId>
|
||||
<version>${snailjob.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 加密包引入 -->
|
||||
|
|
@ -326,10 +335,23 @@
|
|||
<version>${okhttp.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- AWS SDK for Java 2.x -->
|
||||
<dependency>
|
||||
<groupId>com.amazonaws</groupId>
|
||||
<artifactId>aws-java-sdk-s3</artifactId>
|
||||
<version>${aws-java-sdk-s3.version}</version>
|
||||
<groupId>software.amazon.awssdk</groupId>
|
||||
<artifactId>s3</artifactId>
|
||||
<version>${aws.sdk.version}</version>
|
||||
</dependency>
|
||||
<!-- 使用AWS基于 CRT 的 S3 客户端 -->
|
||||
<dependency>
|
||||
<groupId>software.amazon.awssdk.crt</groupId>
|
||||
<artifactId>aws-crt</artifactId>
|
||||
<version>${aws.crt.version}</version>
|
||||
</dependency>
|
||||
<!-- 基于 AWS CRT 的 S3 客户端的性能增强的 S3 传输管理器 -->
|
||||
<dependency>
|
||||
<groupId>software.amazon.awssdk</groupId>
|
||||
<artifactId>s3-transfer-manager</artifactId>
|
||||
<version>${aws.sdk.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--短信sms4j-->
|
||||
|
|
@ -364,6 +386,13 @@
|
|||
<version>${mapstruct-plus.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--消息队列-->
|
||||
<dependency>
|
||||
<groupId>org.apache.rocketmq</groupId>
|
||||
<artifactId>rocketmq-spring-boot-starter</artifactId>
|
||||
<version>${rocketmq.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
<module>ruoyi-api-bom</module>
|
||||
<module>ruoyi-api-system</module>
|
||||
<module>ruoyi-api-resource</module>
|
||||
<module>ruoyi-api-workflow</module>
|
||||
</modules>
|
||||
|
||||
<artifactId>ruoyi-api</artifactId>
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
</description>
|
||||
|
||||
<properties>
|
||||
<revision>2.1.2</revision>
|
||||
<revision>2.2.0-BETA</revision>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
|
|
@ -34,6 +34,13 @@
|
|||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- workflow接口 -->
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-api-workflow</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ package org.dromara.resource.api;
|
|||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.resource.api.domain.RemoteFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 文件服务
|
||||
*
|
||||
|
|
@ -26,4 +28,11 @@ public interface RemoteFileService {
|
|||
*/
|
||||
String selectUrlByIds(String ossIds);
|
||||
|
||||
/**
|
||||
* 通过ossId查询列表
|
||||
*
|
||||
* @param ossIds ossId串逗号分隔
|
||||
* @return 列表
|
||||
*/
|
||||
List<RemoteFile> selectByIds(String ossIds);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import lombok.extern.slf4j.Slf4j;
|
|||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.resource.api.domain.RemoteFile;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 文件服务(降级处理)
|
||||
*
|
||||
|
|
@ -34,4 +36,10 @@ public class RemoteFileServiceMock implements RemoteFileService {
|
|||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RemoteFile> selectByIds(String ossIds) {
|
||||
log.warn("服务调用异常 -> 降级处理");
|
||||
return List.of();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ public interface RemoteMessageService {
|
|||
* @param sessionKey session主键 一般为用户id
|
||||
* @param message 消息文本
|
||||
*/
|
||||
void sendMessage(Long sessionKey, String message);
|
||||
void publishMessage(Long sessionKey, String message);
|
||||
|
||||
void publishAll(String message);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,9 +20,9 @@ public class RemoteMessageServiceStub implements RemoteMessageService {
|
|||
* @param sessionKey session主键 一般为用户id
|
||||
* @param message 消息文本
|
||||
*/
|
||||
public void sendMessage(Long sessionKey, String message) {
|
||||
public void publishMessage(Long sessionKey, String message) {
|
||||
try {
|
||||
remoteMessageService.sendMessage(sessionKey, message);
|
||||
remoteMessageService.publishMessage(sessionKey, message);
|
||||
} catch (Exception e) {
|
||||
log.warn("websocket 功能未开启或服务未找到");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,24 +1,145 @@
|
|||
package org.dromara.resource.api;
|
||||
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.resource.api.domain.RemoteSms;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 短信服务
|
||||
*
|
||||
* @author Lion Li
|
||||
* @author Feng
|
||||
*/
|
||||
public interface RemoteSmsService {
|
||||
|
||||
/**
|
||||
* 发送短信
|
||||
* 同步方法:发送固定消息模板短信
|
||||
*
|
||||
* @param phones 电话号(多个逗号分割)
|
||||
* @param templateId 模板id
|
||||
* @param param 模板对应参数
|
||||
* @param phone 目标手机号
|
||||
* @param message 短信内容
|
||||
* @return 封装了短信发送结果的 RemoteSms 对象
|
||||
*/
|
||||
RemoteSms send(String phones, String templateId, LinkedHashMap<String, String> param) throws ServiceException;
|
||||
RemoteSms sendMessage(String phone, String message);
|
||||
|
||||
/**
|
||||
* 同步方法:发送固定消息模板多模板参数短信
|
||||
*
|
||||
* @param phone 目标手机号
|
||||
* @param messages 短信模板参数,使用 LinkedHashMap 以保持参数顺序
|
||||
* @return 封装了短信发送结果的 RemoteSms 对象
|
||||
*/
|
||||
RemoteSms sendMessage(String phone, LinkedHashMap<String, String> messages);
|
||||
|
||||
/**
|
||||
* 同步方法:使用自定义模板发送短信
|
||||
*
|
||||
* @param phone 目标手机号
|
||||
* @param templateId 短信模板ID
|
||||
* @param messages 短信模板参数,使用 LinkedHashMap 以保持参数顺序
|
||||
* @return 封装了短信发送结果的 RemoteSms 对象
|
||||
*/
|
||||
RemoteSms sendMessage(String phone, String templateId, LinkedHashMap<String, String> messages);
|
||||
|
||||
/**
|
||||
* 同步方法:群发固定模板短信
|
||||
*
|
||||
* @param phones 目标手机号列表(1~1000)
|
||||
* @param message 短信内容
|
||||
* @return 封装了短信发送结果的 RemoteSms 对象
|
||||
*/
|
||||
RemoteSms messageTexting(List<String> phones, String message);
|
||||
|
||||
/**
|
||||
* 同步方法:使用自定义模板群发短信
|
||||
*
|
||||
* @param phones 目标手机号列表(1~1000)(1~1000)
|
||||
* @param templateId 短信模板ID
|
||||
* @param messages 短信模板参数,使用 LinkedHashMap 以保持参数顺序
|
||||
* @return 封装了短信发送结果的 RemoteSms 对象
|
||||
*/
|
||||
RemoteSms messageTexting(List<String> phones, String templateId, LinkedHashMap<String, String> messages);
|
||||
|
||||
/**
|
||||
* 异步方法:发送固定消息模板短信
|
||||
*
|
||||
* @param phone 目标手机号
|
||||
* @param message 短信内容
|
||||
*/
|
||||
void sendMessageAsync(String phone, String message);
|
||||
|
||||
/**
|
||||
* 异步方法:使用自定义模板发送短信
|
||||
*
|
||||
* @param phone 目标手机号
|
||||
* @param templateId 短信模板ID
|
||||
* @param messages 短信模板参数,使用 LinkedHashMap 以保持参数顺序
|
||||
*/
|
||||
void sendMessageAsync(String phone, String templateId, LinkedHashMap<String, String> messages);
|
||||
|
||||
/**
|
||||
* 延迟发送:发送固定消息模板短信
|
||||
*
|
||||
* @param phone 目标手机号
|
||||
* @param message 短信内容
|
||||
* @param delayedTime 延迟发送时间(毫秒)
|
||||
*/
|
||||
void delayMessage(String phone, String message, Long delayedTime);
|
||||
|
||||
/**
|
||||
* 延迟发送:使用自定义模板发送定时短信
|
||||
*
|
||||
* @param phone 目标手机号
|
||||
* @param templateId 短信模板ID
|
||||
* @param messages 短信模板参数,使用 LinkedHashMap 以保持参数顺序
|
||||
* @param delayedTime 延迟发送时间(毫秒)
|
||||
*/
|
||||
void delayMessage(String phone, String templateId, LinkedHashMap<String, String> messages, Long delayedTime);
|
||||
|
||||
/**
|
||||
* 延迟群发:群发延迟短信
|
||||
*
|
||||
* @param phones 目标手机号列表(1~1000)
|
||||
* @param message 短信内容
|
||||
* @param delayedTime 延迟发送时间(毫秒)
|
||||
*/
|
||||
void delayMessageTexting(List<String> phones, String message, Long delayedTime);
|
||||
|
||||
/**
|
||||
* 延迟群发:使用自定义模板发送群体延迟短信
|
||||
*
|
||||
* @param phones 目标手机号列表(1~1000)
|
||||
* @param templateId 短信模板ID
|
||||
* @param messages 短信模板参数,使用 LinkedHashMap 以保持参数顺序
|
||||
* @param delayedTime 延迟发送时间(毫秒)
|
||||
*/
|
||||
void delayMessageTexting(List<String> phones, String templateId, LinkedHashMap<String, String> messages, Long delayedTime);
|
||||
|
||||
/**
|
||||
* 加入黑名单
|
||||
*
|
||||
* @param phone 手机号
|
||||
*/
|
||||
void addBlacklist(String phone);
|
||||
|
||||
/**
|
||||
* 加入黑名单
|
||||
*
|
||||
* @param phones 手机号列表
|
||||
*/
|
||||
void addBlacklist(List<String> phones);
|
||||
|
||||
/**
|
||||
* 移除黑名单
|
||||
*
|
||||
* @param phone 手机号
|
||||
*/
|
||||
void removeBlacklist(String phone);
|
||||
|
||||
/**
|
||||
* 移除黑名单
|
||||
*
|
||||
* @param phones 手机号
|
||||
*/
|
||||
void removeBlacklist(List<String> phones);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,4 +31,14 @@ public class RemoteFile implements Serializable {
|
|||
*/
|
||||
private String url;
|
||||
|
||||
/**
|
||||
* 原名
|
||||
*/
|
||||
private String originalName;
|
||||
|
||||
/**
|
||||
* 文件后缀名
|
||||
*/
|
||||
private String fileSuffix;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,15 +19,15 @@ public class RemoteSms implements Serializable {
|
|||
/**
|
||||
* 是否成功
|
||||
*/
|
||||
private Boolean isSuccess;
|
||||
private Boolean success;
|
||||
|
||||
/**
|
||||
* 响应消息
|
||||
* 配置标识名 如未配置取对应渠道名例如 Alibaba
|
||||
*/
|
||||
private String message;
|
||||
private String configId;
|
||||
|
||||
/**
|
||||
* 实际响应体
|
||||
* 厂商原返回体
|
||||
* <p>
|
||||
* 可自行转换为 SDK 对应的 SendSmsResponse
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -9,11 +9,17 @@ public interface RemoteDataScopeService {
|
|||
|
||||
/**
|
||||
* 获取角色自定义权限语句
|
||||
*
|
||||
* @param roleId 角色ID
|
||||
* @return 返回角色的自定义权限语句,如果没有找到则返回 null
|
||||
*/
|
||||
String getRoleCustom(Long roleId);
|
||||
|
||||
/**
|
||||
* 获取部门和下级权限语句
|
||||
*
|
||||
* @param deptId 部门ID
|
||||
* @return 返回部门及其下级的权限语句,如果没有找到则返回 null
|
||||
*/
|
||||
String getDeptAndChild(Long deptId);
|
||||
|
||||
|
|
|
|||
|
|
@ -18,4 +18,5 @@ public interface RemoteDictService {
|
|||
* @return 字典数据集合信息
|
||||
*/
|
||||
List<RemoteDictDataVo> selectDictDataByType(String dictType);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,4 +23,5 @@ public interface RemoteLogService {
|
|||
* @param sysLogininfor 访问实体
|
||||
*/
|
||||
void saveLogininfor(RemoteLogininforBo sysLogininfor);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,22 +13,39 @@ import java.util.List;
|
|||
public interface RemoteSocialService {
|
||||
|
||||
/**
|
||||
* 根据 authId 查询用户信息
|
||||
* 根据 authId 查询用户授权信息
|
||||
*
|
||||
* @param authId 认证id
|
||||
* @return 授权信息
|
||||
*/
|
||||
List<RemoteSocialVo> selectByAuthId(String authId);
|
||||
|
||||
/**
|
||||
* 查询列表
|
||||
*
|
||||
* @param bo 社会化关系业务对象
|
||||
*/
|
||||
List<RemoteSocialVo> queryList(RemoteSocialBo bo);
|
||||
|
||||
/**
|
||||
* 保存社会化关系
|
||||
*
|
||||
* @param bo 社会化关系业务对象
|
||||
*/
|
||||
void insertByBo(RemoteSocialBo bo);
|
||||
|
||||
/**
|
||||
* 更新社会化关系
|
||||
*
|
||||
* @param bo 社会化关系业务对象
|
||||
*/
|
||||
void updateByBo(RemoteSocialBo bo);
|
||||
|
||||
/**
|
||||
* 删除社会化关系
|
||||
*
|
||||
* @param socialId 社会化关系ID
|
||||
* @return 结果
|
||||
*/
|
||||
Boolean deleteWithValidById(Long socialId);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ import org.dromara.system.api.domain.vo.RemoteTenantVo;
|
|||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 租户服务
|
||||
*
|
||||
* @author zhujie
|
||||
*/
|
||||
public interface RemoteTenantService {
|
||||
|
|
|
|||
|
|
@ -3,9 +3,12 @@ package org.dromara.system.api;
|
|||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.exception.user.UserException;
|
||||
import org.dromara.system.api.domain.bo.RemoteUserBo;
|
||||
import org.dromara.system.api.domain.vo.RemoteUserVo;
|
||||
import org.dromara.system.api.model.LoginUser;
|
||||
import org.dromara.system.api.model.XcxLoginUser;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 用户服务
|
||||
*
|
||||
|
|
@ -81,6 +84,30 @@ public interface RemoteUserService {
|
|||
*/
|
||||
String selectNicknameById(Long userId);
|
||||
|
||||
/**
|
||||
* 通过用户ID查询用户账户
|
||||
*
|
||||
* @param userIds 用户ID 多个用逗号隔开
|
||||
* @return 用户名称
|
||||
*/
|
||||
String selectNicknameByIds(String userIds);
|
||||
|
||||
/**
|
||||
* 通过用户ID查询用户手机号
|
||||
*
|
||||
* @param userId 用户id
|
||||
* @return 用户手机号
|
||||
*/
|
||||
String selectPhonenumberById(Long userId);
|
||||
|
||||
/**
|
||||
* 通过用户ID查询用户邮箱
|
||||
*
|
||||
* @param userId 用户id
|
||||
* @return 用户邮箱
|
||||
*/
|
||||
String selectEmailById(Long userId);
|
||||
|
||||
/**
|
||||
* 更新用户信息
|
||||
*
|
||||
|
|
@ -89,4 +116,19 @@ public interface RemoteUserService {
|
|||
*/
|
||||
void recordLoginInfo(Long userId, String ip);
|
||||
|
||||
/**
|
||||
* 通过用户ID查询用户列表
|
||||
*
|
||||
* @param userIds 用户ids
|
||||
* @return 用户列表
|
||||
*/
|
||||
List<RemoteUserVo> selectListByIds(List<Long> userIds);
|
||||
|
||||
/**
|
||||
* 通过角色ID查询用户ID
|
||||
*
|
||||
* @param roleIds 角色ids
|
||||
* @return 用户ids
|
||||
*/
|
||||
List<Long> selectUserIdsByRoleIds(List<Long> roleIds);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import java.io.Serializable;
|
|||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class SysUserOnline implements Serializable {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import java.util.Map;
|
|||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class RemoteLogininforBo implements Serializable {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import java.util.Map;
|
|||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class RemoteOperLogBo implements Serializable {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ import java.util.Date;
|
|||
*
|
||||
* @author Michelle.Chung
|
||||
*/
|
||||
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class RemoteUserBo implements Serializable {
|
||||
|
|
|
|||
|
|
@ -67,5 +67,4 @@ public class RemoteClientVo implements Serializable {
|
|||
*/
|
||||
private String status;
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ public class RemoteSocialVo implements Serializable {
|
|||
private String tenantId;
|
||||
|
||||
/**
|
||||
* 的唯一ID
|
||||
* 认证唯一ID
|
||||
*/
|
||||
private String authId;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,73 @@
|
|||
package org.dromara.system.api.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
|
||||
/**
|
||||
* 用户
|
||||
*
|
||||
* @author Michelle.Chung
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
public class RemoteUserVo implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 部门ID
|
||||
*/
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 用户账号
|
||||
*/
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 用户昵称
|
||||
*/
|
||||
private String nickName;
|
||||
|
||||
/**
|
||||
* 用户类型(sys_user系统用户)
|
||||
*/
|
||||
private String userType;
|
||||
|
||||
/**
|
||||
* 用户邮箱
|
||||
*/
|
||||
private String email;
|
||||
|
||||
/**
|
||||
* 手机号码
|
||||
*/
|
||||
private String phonenumber;
|
||||
|
||||
/**
|
||||
* 用户性别(0男 1女 2未知)
|
||||
*/
|
||||
private String sex;
|
||||
|
||||
/**
|
||||
* 帐号状态(0正常 1停用)
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 创建时间
|
||||
*/
|
||||
private Date createTime;
|
||||
|
||||
}
|
||||
|
|
@ -35,6 +35,11 @@ public class LoginUser implements Serializable {
|
|||
*/
|
||||
private Long deptId;
|
||||
|
||||
/**
|
||||
* 部门类别编码
|
||||
*/
|
||||
private String deptCategory;
|
||||
|
||||
/**
|
||||
* 部门名
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-api</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>ruoyi-api-workflow</artifactId>
|
||||
|
||||
<description>
|
||||
ruoyi-api-workflow 工作流接口模块
|
||||
</description>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- RuoYi Common Core-->
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
package org.dromara.workflow.api.domain;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 通用 工作流服务
|
||||
*
|
||||
* @Author ZETA
|
||||
* @Date 2024/6/3
|
||||
*/
|
||||
public interface RemoteWorkflowService {
|
||||
|
||||
/**
|
||||
* 运行中的实例 删除程实例,删除历史记录,删除业务与流程关联信息
|
||||
*
|
||||
* @param businessKeys 业务id
|
||||
* @return 结果
|
||||
*/
|
||||
boolean deleteRunAndHisInstance(List<String> businessKeys);
|
||||
|
||||
/**
|
||||
* 获取当前流程状态
|
||||
*
|
||||
* @param taskId 任务id
|
||||
*/
|
||||
String getBusinessStatusByTaskId(String taskId);
|
||||
|
||||
/**
|
||||
* 获取当前流程状态
|
||||
*
|
||||
* @param businessKey 业务id
|
||||
*/
|
||||
String getBusinessStatus(String businessKey);
|
||||
|
||||
/**
|
||||
* 设置流程变量(全局变量)
|
||||
*
|
||||
* @param taskId 任务id
|
||||
* @param variableName 变量名称
|
||||
* @param value 变量值
|
||||
*/
|
||||
void setVariable(String taskId, String variableName, Object value);
|
||||
|
||||
/**
|
||||
* 设置流程变量(全局变量)
|
||||
*
|
||||
* @param taskId 任务id
|
||||
* @param variables 流程变量
|
||||
*/
|
||||
void setVariables(String taskId, Map<String, Object> variables);
|
||||
|
||||
/**
|
||||
* 设置流程变量(本地变量,非全局变量)
|
||||
*
|
||||
* @param taskId 任务id
|
||||
* @param variableName 变量名称
|
||||
* @param value 变量值
|
||||
*/
|
||||
void setVariableLocal(String taskId, String variableName, Object value);
|
||||
|
||||
/**
|
||||
* 设置流程变量(本地变量,非全局变量)
|
||||
*
|
||||
* @param taskId 任务id
|
||||
* @param variables 流程变量
|
||||
*/
|
||||
void setVariablesLocal(String taskId, Map<String, Object> variables);
|
||||
|
||||
/**
|
||||
* 按照业务id查询流程实例id
|
||||
*
|
||||
* @param businessKey 业务id
|
||||
* @return 结果
|
||||
*/
|
||||
String getInstanceIdByBusinessKey(String businessKey);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package org.dromara.workflow.api.domain.event;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 总体流程监听
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
|
||||
@Data
|
||||
public class ProcessEvent implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 流程定义key
|
||||
*/
|
||||
private String key;
|
||||
|
||||
/**
|
||||
* 业务id
|
||||
*/
|
||||
private String businessKey;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private String status;
|
||||
|
||||
/**
|
||||
* 当为true时为申请人节点办理
|
||||
*/
|
||||
private boolean submit;
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package org.dromara.workflow.api.domain.event;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 流程办理监听
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
|
||||
@Data
|
||||
public class ProcessTaskEvent implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 流程定义key与流程节点标识(拼接方式:流程定义key_流程节点)
|
||||
*/
|
||||
private String keyNode;
|
||||
|
||||
/**
|
||||
* 任务id
|
||||
*/
|
||||
private String taskId;
|
||||
|
||||
/**
|
||||
* 业务id
|
||||
*/
|
||||
private String businessKey;
|
||||
|
||||
}
|
||||
|
|
@ -18,6 +18,6 @@ ADD ./target/ruoyi-auth.jar ./app.jar
|
|||
ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -Dserver.port=${SERVER_PORT} \
|
||||
#-Dskywalking.agent.service_name=ruoyi-auth \
|
||||
#-javaagent:/ruoyi/skywalking/agent/skywalking-agent.jar \
|
||||
-jar app.jar \
|
||||
-XX:+HeapDumpOnOutOfMemoryError -Xlog:gc*,:time,tags,level -XX:+UseZGC ${JAVA_OPTS}
|
||||
-XX:+HeapDumpOnOutOfMemoryError -XX:+UseZGC ${JAVA_OPTS} \
|
||||
-jar app.jar
|
||||
|
||||
|
|
|
|||
|
|
@ -16,16 +16,9 @@
|
|||
|
||||
<dependencies>
|
||||
|
||||
<!-- SpringCloud Alibaba Nacos -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- SpringCloud Alibaba Nacos Config -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-nacos</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
|
@ -87,12 +80,6 @@
|
|||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-tenant</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-mybatis</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ public class CaptchaConfig {
|
|||
|
||||
private static final int WIDTH = 160;
|
||||
private static final int HEIGHT = 60;
|
||||
private static final Color BACKGROUND = Color.PINK;
|
||||
private static final Color BACKGROUND = Color.LIGHT_GRAY;
|
||||
private static final Font FONT = new Font("Arial", Font.BOLD, 48);
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ public class CaptchaController {
|
|||
AbstractCaptcha captcha = SpringUtils.getBean(captchaProperties.getCategory().getClazz());
|
||||
captcha.setGenerator(codeGenerator);
|
||||
captcha.createCode();
|
||||
// 如果是数学验证码,使用SpEL表达式处理验证码结果
|
||||
String code = captcha.getCode();
|
||||
if (isMath) {
|
||||
ExpressionParser parser = new SpelExpressionParser();
|
||||
|
|
|
|||
|
|
@ -97,10 +97,7 @@ public class TokenController {
|
|||
|
||||
Long userId = LoginHelper.getUserId();
|
||||
scheduledExecutorService.schedule(() -> {
|
||||
try {
|
||||
remoteMessageService.sendMessage(userId, "欢迎登录RuoYi-Cloud-Plus微服务管理系统");
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
remoteMessageService.publishMessage(userId, "欢迎登录RuoYi-Cloud-Plus微服务管理系统");
|
||||
}, 3, TimeUnit.SECONDS);
|
||||
return R.ok(loginVo);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,10 +10,19 @@ import lombok.Data;
|
|||
@Data
|
||||
public class TenantListVo {
|
||||
|
||||
/**
|
||||
* 租户编号
|
||||
*/
|
||||
private String tenantId;
|
||||
|
||||
/**
|
||||
* 企业名称
|
||||
*/
|
||||
private String companyName;
|
||||
|
||||
/**
|
||||
* 域名
|
||||
*/
|
||||
private String domain;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import org.dromara.common.core.domain.model.LoginBody;
|
|||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class EmailLoginBody extends LoginBody {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@ public class RegisterBody extends LoginBody {
|
|||
@Length(min = PASSWORD_MIN_LENGTH, max = PASSWORD_MAX_LENGTH, message = "{user.password.length.valid}")
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* 用户类型
|
||||
*/
|
||||
private String userType;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import org.dromara.common.core.domain.model.LoginBody;
|
|||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class SmsLoginBody extends LoginBody {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import org.dromara.common.core.domain.model.LoginBody;
|
|||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class SocialLoginBody extends LoginBody {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import org.dromara.common.core.domain.model.LoginBody;
|
|||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class XcxLoginBody extends LoginBody {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package org.dromara.auth.listener;
|
|||
import cn.dev33.satoken.config.SaTokenConfig;
|
||||
import cn.dev33.satoken.listener.SaTokenListener;
|
||||
import cn.dev33.satoken.stp.SaLoginModel;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.http.useragent.UserAgent;
|
||||
import cn.hutool.http.useragent.UserAgentUtil;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
|
@ -18,14 +17,13 @@ import org.dromara.common.core.utils.ip.AddressUtils;
|
|||
import org.dromara.common.log.event.LogininforEvent;
|
||||
import org.dromara.common.redis.utils.RedisUtils;
|
||||
import org.dromara.common.satoken.utils.LoginHelper;
|
||||
import org.dromara.common.tenant.helper.TenantHelper;
|
||||
import org.dromara.resource.api.RemoteMessageService;
|
||||
import org.dromara.system.api.RemoteUserService;
|
||||
import org.dromara.system.api.domain.SysUserOnline;
|
||||
import org.dromara.system.api.model.LoginUser;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
|
||||
/**
|
||||
* 用户行为 侦听器的实现
|
||||
|
|
@ -38,7 +36,6 @@ import java.util.concurrent.ScheduledExecutorService;
|
|||
public class UserActionListener implements SaTokenListener {
|
||||
|
||||
private final SaTokenConfig tokenConfig;
|
||||
private final ScheduledExecutorService scheduledExecutorService;
|
||||
@DubboReference
|
||||
private RemoteUserService remoteUserService;
|
||||
@DubboReference
|
||||
|
|
@ -51,7 +48,6 @@ public class UserActionListener implements SaTokenListener {
|
|||
public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginModel loginModel) {
|
||||
UserAgent userAgent = UserAgentUtil.parse(ServletUtils.getRequest().getHeader("User-Agent"));
|
||||
String ip = ServletUtils.getClientIP();
|
||||
LoginUser user = LoginHelper.getLoginUser();
|
||||
SysUserOnline userOnline = new SysUserOnline();
|
||||
userOnline.setIpaddr(ip);
|
||||
userOnline.setLoginLocation(AddressUtils.getRealAddressByIP(ip));
|
||||
|
|
@ -59,27 +55,28 @@ public class UserActionListener implements SaTokenListener {
|
|||
userOnline.setOs(userAgent.getOs().getName());
|
||||
userOnline.setLoginTime(System.currentTimeMillis());
|
||||
userOnline.setTokenId(tokenValue);
|
||||
userOnline.setUserName(user.getUsername());
|
||||
userOnline.setClientKey(user.getClientKey());
|
||||
userOnline.setDeviceType(user.getDeviceType());
|
||||
if (ObjectUtil.isNotNull(user.getDeptName())) {
|
||||
userOnline.setDeptName(user.getDeptName());
|
||||
}
|
||||
if (tokenConfig.getTimeout() == -1) {
|
||||
RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, userOnline);
|
||||
} else {
|
||||
RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, userOnline, Duration.ofSeconds(tokenConfig.getTimeout()));
|
||||
}
|
||||
String username = (String) loginModel.getExtra(LoginHelper.USER_NAME_KEY);
|
||||
String tenantId = (String) loginModel.getExtra(LoginHelper.TENANT_KEY);
|
||||
userOnline.setUserName(username);
|
||||
userOnline.setClientKey((String) loginModel.getExtra(LoginHelper.CLIENT_KEY));
|
||||
userOnline.setDeviceType(loginModel.getDevice());
|
||||
userOnline.setDeptName((String) loginModel.getExtra(LoginHelper.DEPT_NAME_KEY));
|
||||
TenantHelper.dynamic(tenantId, () -> {
|
||||
if (tokenConfig.getTimeout() == -1) {
|
||||
RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, userOnline);
|
||||
} else {
|
||||
RedisUtils.setCacheObject(CacheConstants.ONLINE_TOKEN_KEY + tokenValue, userOnline, Duration.ofSeconds(tokenConfig.getTimeout()));
|
||||
}
|
||||
});
|
||||
// 记录登录日志
|
||||
LogininforEvent logininforEvent = new LogininforEvent();
|
||||
logininforEvent.setTenantId(user.getTenantId());
|
||||
logininforEvent.setUsername(user.getUsername());
|
||||
logininforEvent.setTenantId(tenantId);
|
||||
logininforEvent.setUsername(username);
|
||||
logininforEvent.setStatus(Constants.LOGIN_SUCCESS);
|
||||
logininforEvent.setMessage(MessageUtils.message("user.login.success"));
|
||||
logininforEvent.setRequest(ServletUtils.getRequest());
|
||||
SpringUtils.context().publishEvent(logininforEvent);
|
||||
// 更新登录信息
|
||||
remoteUserService.recordLoginInfo(user.getUserId(), ServletUtils.getClientIP());
|
||||
remoteUserService.recordLoginInfo((Long) loginModel.getExtra(LoginHelper.USER_KEY), ip);
|
||||
log.info("user doLogin, useId:{}, token:{}", loginId, tokenValue);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import org.springframework.context.annotation.Configuration;
|
|||
@RefreshScope
|
||||
@ConfigurationProperties(prefix = "security.captcha")
|
||||
public class CaptchaProperties {
|
||||
|
||||
/**
|
||||
* 验证码类型
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -16,6 +16,11 @@ public interface IAuthStrategy {
|
|||
|
||||
/**
|
||||
* 登录
|
||||
*
|
||||
* @param body 登录对象
|
||||
* @param client 授权管理视图对象
|
||||
* @param grantType 授权类型
|
||||
* @return 登录验证信息
|
||||
*/
|
||||
static LoginVo login(String body, RemoteClientVo client, String grantType) {
|
||||
// 授权类型和客户端id
|
||||
|
|
@ -29,6 +34,10 @@ public interface IAuthStrategy {
|
|||
|
||||
/**
|
||||
* 登录
|
||||
*
|
||||
* @param body 登录对象
|
||||
* @param client 授权管理视图对象
|
||||
* @return 登录验证信息
|
||||
*/
|
||||
LoginVo login(String body, RemoteClientVo client);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import cn.dev33.satoken.stp.StpUtil;
|
|||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.lock.annotation.Lock4j;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.zhyd.oauth.model.AuthUser;
|
||||
|
|
@ -19,11 +20,11 @@ import org.dromara.common.core.constant.TenantConstants;
|
|||
import org.dromara.common.core.enums.LoginType;
|
||||
import org.dromara.common.core.enums.TenantStatus;
|
||||
import org.dromara.common.core.enums.UserType;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.exception.user.CaptchaException;
|
||||
import org.dromara.common.core.exception.user.CaptchaExpireException;
|
||||
import org.dromara.common.core.exception.user.UserException;
|
||||
import org.dromara.common.core.utils.MessageUtils;
|
||||
import org.dromara.common.core.utils.ServletUtils;
|
||||
import org.dromara.common.core.utils.SpringUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.common.log.event.LogininforEvent;
|
||||
|
|
@ -74,18 +75,27 @@ public class SysLoginService {
|
|||
*
|
||||
* @param authUserData 授权响应实体
|
||||
*/
|
||||
@Lock4j
|
||||
public void socialRegister(AuthUser authUserData) {
|
||||
String authId = authUserData.getSource() + authUserData.getUuid();
|
||||
// 第三方用户信息
|
||||
RemoteSocialBo bo = BeanUtil.toBean(authUserData, RemoteSocialBo.class);
|
||||
BeanUtil.copyProperties(authUserData.getToken(), bo);
|
||||
bo.setUserId(LoginHelper.getUserId());
|
||||
Long userId = LoginHelper.getUserId();
|
||||
bo.setUserId(userId);
|
||||
bo.setAuthId(authId);
|
||||
bo.setOpenId(authUserData.getUuid());
|
||||
bo.setUserName(authUserData.getUsername());
|
||||
bo.setNickName(authUserData.getNickname());
|
||||
List<RemoteSocialVo> checkList = remoteSocialService.selectByAuthId(authId);
|
||||
if (CollUtil.isNotEmpty(checkList)) {
|
||||
throw new ServiceException("此三方账号已经被绑定!");
|
||||
}
|
||||
// 查询是否已经绑定用户
|
||||
List<RemoteSocialVo> list = remoteSocialService.selectByAuthId(authId);
|
||||
RemoteSocialBo params = new RemoteSocialBo();
|
||||
params.setUserId(userId);
|
||||
params.setSource(bo.getSource());
|
||||
List<RemoteSocialVo> list = remoteSocialService.queryList(params);
|
||||
if (CollUtil.isEmpty(list)) {
|
||||
// 没有绑定用户, 新增用户信息
|
||||
remoteSocialService.insertByBo(bo);
|
||||
|
|
@ -93,6 +103,8 @@ public class SysLoginService {
|
|||
// 更新用户信息
|
||||
bo.setId(list.get(0).getId());
|
||||
remoteSocialService.updateByBo(bo);
|
||||
// 如果要绑定的平台账号已经被绑定过了 是否抛异常自行决断
|
||||
// throw new ServiceException("此平台账号已经被绑定!");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -158,7 +170,7 @@ public class SysLoginService {
|
|||
* @param uuid 唯一标识
|
||||
*/
|
||||
public void validateCaptcha(String tenantId, String username, String code, String uuid) {
|
||||
String verifyKey = GlobalConstants.CAPTCHA_CODE_KEY + StringUtils.defaultString(uuid, "");
|
||||
String verifyKey = GlobalConstants.CAPTCHA_CODE_KEY + StringUtils.blankToDefault(uuid, "");
|
||||
String captcha = RedisUtils.getCacheObject(verifyKey);
|
||||
RedisUtils.deleteObject(verifyKey);
|
||||
if (captcha == null) {
|
||||
|
|
@ -186,7 +198,6 @@ public class SysLoginService {
|
|||
logininforEvent.setUsername(username);
|
||||
logininforEvent.setStatus(status);
|
||||
logininforEvent.setMessage(message);
|
||||
logininforEvent.setRequest(ServletUtils.getRequest());
|
||||
SpringUtils.context().publishEvent(logininforEvent);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ public class PasswordAuthStrategy implements IAuthStrategy {
|
|||
* @param uuid 唯一标识
|
||||
*/
|
||||
private void validateCaptcha(String tenantId, String username, String code, String uuid) {
|
||||
String verifyKey = GlobalConstants.CAPTCHA_CODE_KEY + StringUtils.defaultString(uuid, "");
|
||||
String verifyKey = GlobalConstants.CAPTCHA_CODE_KEY + StringUtils.blankToDefault(uuid, "");
|
||||
String captcha = RedisUtils.getCacheObject(verifyKey);
|
||||
RedisUtils.deleteObject(verifyKey);
|
||||
if (captcha == null) {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import org.dromara.common.json.utils.JsonUtils;
|
|||
import org.dromara.common.satoken.utils.LoginHelper;
|
||||
import org.dromara.common.social.config.properties.SocialProperties;
|
||||
import org.dromara.common.social.utils.SocialUtils;
|
||||
import org.dromara.common.tenant.helper.TenantHelper;
|
||||
import org.dromara.system.api.RemoteSocialService;
|
||||
import org.dromara.system.api.RemoteUserService;
|
||||
import org.dromara.system.api.domain.vo.RemoteClientVo;
|
||||
|
|
@ -80,11 +81,16 @@ public class SocialAuthStrategy implements IAuthStrategy {
|
|||
if (CollUtil.isEmpty(list)) {
|
||||
throw new ServiceException("你还没有绑定第三方账号,绑定后才可以登录!");
|
||||
}
|
||||
Optional<RemoteSocialVo> opt = list.stream().filter(x -> x.getTenantId().equals(loginBody.getTenantId())).findAny();
|
||||
if (opt.isEmpty()) {
|
||||
throw new ServiceException("对不起,你没有权限登录当前租户!");
|
||||
RemoteSocialVo socialVo;
|
||||
if (TenantHelper.isEnable()) {
|
||||
Optional<RemoteSocialVo> opt = list.stream().filter(x -> x.getTenantId().equals(loginBody.getTenantId())).findAny();
|
||||
if (opt.isEmpty()) {
|
||||
throw new ServiceException("对不起,你没有权限登录当前租户!");
|
||||
}
|
||||
socialVo = opt.get();
|
||||
} else {
|
||||
socialVo = list.get(0);
|
||||
}
|
||||
RemoteSocialVo socialVo = opt.get();
|
||||
|
||||
LoginUser loginUser = remoteUserService.getUserInfo(socialVo.getUserId(), socialVo.getTenantId());
|
||||
loginUser.setClientKey(client.getClientKey());
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ spring:
|
|||
nacos:
|
||||
# nacos 服务地址
|
||||
server-addr: @nacos.server@
|
||||
username: @nacos.username@
|
||||
password: @nacos.password@
|
||||
discovery:
|
||||
# 注册组
|
||||
group: @nacos.discovery.group@
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
<module>ruoyi-common-tenant</module>
|
||||
<module>ruoyi-common-websocket</module>
|
||||
<module>ruoyi-common-social</module>
|
||||
<module>ruoyi-common-nacos</module>
|
||||
</modules>
|
||||
|
||||
<artifactId>ruoyi-common</artifactId>
|
||||
|
|
|
|||
|
|
@ -14,12 +14,12 @@
|
|||
</description>
|
||||
|
||||
<properties>
|
||||
<revision>2.1.2</revision>
|
||||
<spring-cloud-alibaba.version>2022.0.0.0</spring-cloud-alibaba.version>
|
||||
<sentinel.version>1.8.6</sentinel.version>
|
||||
<revision>2.2.0-BETA</revision>
|
||||
<spring-cloud-alibaba.version>2023.0.1.0</spring-cloud-alibaba.version>
|
||||
<sentinel.version>1.8.8</sentinel.version>
|
||||
<seata.version>1.7.1</seata.version>
|
||||
<nacos.client.version>2.2.1</nacos.client.version>
|
||||
<dubbo.version>3.2.7</dubbo.version>
|
||||
<nacos.client.version>2.3.2</nacos.client.version>
|
||||
<dubbo.version>3.2.11</dubbo.version>
|
||||
<spring.context.support.version>1.0.11</spring.context.support.version>
|
||||
</properties>
|
||||
<dependencyManagement>
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
</description>
|
||||
|
||||
<properties>
|
||||
<revision>2.1.2</revision>
|
||||
<revision>2.2.0-BETA</revision>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
|
|
@ -218,6 +218,12 @@
|
|||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.dromara</groupId>
|
||||
<artifactId>ruoyi-common-nacos</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -99,6 +99,11 @@
|
|||
<artifactId>ip2region</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>transmittable-thread-local</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package org.dromara.common.core.config;
|
|||
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
|
||||
/**
|
||||
* 程序注解配置
|
||||
|
|
@ -11,6 +12,7 @@ import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
|||
@AutoConfiguration
|
||||
// 表示通过aop框架暴露该代理对象,AopContext能够访问
|
||||
@EnableAspectJAutoProxy(exposeProxy = true)
|
||||
@EnableAsync(proxyTargetClass = true)
|
||||
public class ApplicationConfig {
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,70 +1,34 @@
|
|||
package org.dromara.common.core.config;
|
||||
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import jakarta.annotation.PreDestroy;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.utils.SpringUtils;
|
||||
import org.dromara.common.core.utils.Threads;
|
||||
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.task.VirtualThreadTaskExecutor;
|
||||
import org.springframework.scheduling.annotation.AsyncConfigurer;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* 异步配置
|
||||
* <p>
|
||||
* 如果未使用虚拟线程则生效
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Slf4j
|
||||
@EnableAsync(proxyTargetClass = true)
|
||||
@AutoConfiguration
|
||||
public class AsyncConfig implements AsyncConfigurer {
|
||||
|
||||
private final int corePoolSize = Runtime.getRuntime().availableProcessors() + 1;
|
||||
private ScheduledExecutorService scheduledExecutorService;
|
||||
|
||||
/**
|
||||
* 执行周期性或定时任务
|
||||
*/
|
||||
@Bean(name = "scheduledExecutorService")
|
||||
public ScheduledExecutorService scheduledExecutorService() {
|
||||
ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(corePoolSize,
|
||||
new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(),
|
||||
new ThreadPoolExecutor.CallerRunsPolicy()) {
|
||||
@Override
|
||||
protected void afterExecute(Runnable r, Throwable t) {
|
||||
super.afterExecute(r, t);
|
||||
printException(r, t);
|
||||
}
|
||||
};
|
||||
this.scheduledExecutorService = scheduledThreadPoolExecutor;
|
||||
return scheduledThreadPoolExecutor;
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁事件
|
||||
*/
|
||||
@PreDestroy
|
||||
public void destroy() {
|
||||
try {
|
||||
log.info("====关闭后台任务任务线程池====");
|
||||
Threads.shutdownAndAwaitTermination(scheduledExecutorService);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义 @Async 注解使用系统线程池
|
||||
*/
|
||||
@Override
|
||||
public Executor getAsyncExecutor() {
|
||||
if(SpringUtils.isVirtual()) {
|
||||
return new VirtualThreadTaskExecutor("async-");
|
||||
}
|
||||
return SpringUtils.getBean("scheduledExecutorService");
|
||||
}
|
||||
|
||||
|
|
@ -85,27 +49,4 @@ public class AsyncConfig implements AsyncConfigurer {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印线程异常信息
|
||||
*/
|
||||
public void printException(Runnable r, Throwable t) {
|
||||
if (t == null && r instanceof Future<?>) {
|
||||
try {
|
||||
Future<?> future = (Future<?>) r;
|
||||
if (future.isDone()) {
|
||||
future.get();
|
||||
}
|
||||
} catch (CancellationException ce) {
|
||||
t = ce;
|
||||
} catch (ExecutionException ee) {
|
||||
t = ee.getCause();
|
||||
} catch (InterruptedException ie) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
if (t != null) {
|
||||
log.error(t.getMessage(), t);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
package org.dromara.common.core.config;
|
||||
|
||||
import jakarta.annotation.PreDestroy;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
|
||||
import org.dromara.common.core.utils.Threads;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
/**
|
||||
* 线程池配置
|
||||
*
|
||||
* @author Lion Li
|
||||
**/
|
||||
@Slf4j
|
||||
@AutoConfiguration
|
||||
public class ThreadPoolConfig {
|
||||
|
||||
/**
|
||||
* 核心线程数 = cpu 核心数 + 1
|
||||
*/
|
||||
private final int core = Runtime.getRuntime().availableProcessors() + 1;
|
||||
|
||||
private ScheduledExecutorService scheduledExecutorService;
|
||||
|
||||
/**
|
||||
* 执行周期性或定时任务
|
||||
*/
|
||||
@Bean(name = "scheduledExecutorService")
|
||||
protected ScheduledExecutorService scheduledExecutorService() {
|
||||
ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(core,
|
||||
new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(),
|
||||
new ThreadPoolExecutor.CallerRunsPolicy()) {
|
||||
@Override
|
||||
protected void afterExecute(Runnable r, Throwable t) {
|
||||
super.afterExecute(r, t);
|
||||
Threads.printException(r, t);
|
||||
}
|
||||
};
|
||||
this.scheduledExecutorService = scheduledThreadPoolExecutor;
|
||||
return scheduledThreadPoolExecutor;
|
||||
}
|
||||
|
||||
/**
|
||||
* 销毁事件
|
||||
*/
|
||||
@PreDestroy
|
||||
public void destroy() {
|
||||
try {
|
||||
log.info("====关闭后台任务任务线程池====");
|
||||
Threads.shutdownAndAwaitTermination(scheduledExecutorService);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -35,6 +35,11 @@ public interface CacheNames {
|
|||
*/
|
||||
String SYS_TENANT = GlobalConstants.GLOBAL_REDIS_KEY + "sys_tenant#30d";
|
||||
|
||||
/**
|
||||
* 客户端
|
||||
*/
|
||||
String SYS_CLIENT = GlobalConstants.GLOBAL_REDIS_KEY + "sys_client#30d";
|
||||
|
||||
/**
|
||||
* 用户账户
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
package org.dromara.common.core.constant;
|
||||
|
||||
import cn.hutool.core.lang.RegexPool;
|
||||
|
||||
/**
|
||||
* 常用正则表达式字符串
|
||||
* <p>
|
||||
* 常用正则表达式集合,更多正则见: https://any86.github.io/any-rule/
|
||||
*
|
||||
* @author Feng
|
||||
*/
|
||||
public interface RegexConstants extends RegexPool {
|
||||
|
||||
/**
|
||||
* 字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)
|
||||
*/
|
||||
String DICTIONARY_TYPE = "^[a-z][a-z0-9_]*$";
|
||||
|
||||
/**
|
||||
* 权限标识必须符合 tool:build:list 格式,或者空字符串
|
||||
*/
|
||||
String PERMISSION_STRING = "^(|^[a-zA-Z0-9_]+:[a-zA-Z0-9_]+:[a-zA-Z0-9_]+)$";
|
||||
|
||||
/**
|
||||
* 身份证号码(后6位)
|
||||
*/
|
||||
String ID_CARD_LAST_6 = "^(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx]$";
|
||||
|
||||
/**
|
||||
* QQ号码
|
||||
*/
|
||||
String QQ_NUMBER = "^[1-9][0-9]\\d{4,9}$";
|
||||
|
||||
/**
|
||||
* 邮政编码
|
||||
*/
|
||||
String POSTAL_CODE = "^[1-9]\\d{5}$";
|
||||
|
||||
/**
|
||||
* 注册账号
|
||||
*/
|
||||
String ACCOUNT = "^[a-zA-Z][a-zA-Z0-9_]{4,15}$";
|
||||
|
||||
/**
|
||||
* 密码:包含至少8个字符,包括大写字母、小写字母、数字和特殊字符
|
||||
*/
|
||||
String PASSWORD = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$";
|
||||
|
||||
/**
|
||||
* 通用状态(0表示正常,1表示停用)
|
||||
*/
|
||||
String STATUS = "^[01]$";
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
package org.dromara.common.core.enums;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.dromara.common.core.exception.ServiceException;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 业务状态枚举
|
||||
*
|
||||
* @author may
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum BusinessStatusEnum {
|
||||
/**
|
||||
* 已撤销
|
||||
*/
|
||||
CANCEL("cancel", "已撤销"),
|
||||
/**
|
||||
* 草稿
|
||||
*/
|
||||
DRAFT("draft", "草稿"),
|
||||
/**
|
||||
* 待审核
|
||||
*/
|
||||
WAITING("waiting", "待审核"),
|
||||
/**
|
||||
* 已完成
|
||||
*/
|
||||
FINISH("finish", "已完成"),
|
||||
/**
|
||||
* 已作废
|
||||
*/
|
||||
INVALID("invalid", "已作废"),
|
||||
/**
|
||||
* 已退回
|
||||
*/
|
||||
BACK("back", "已退回"),
|
||||
/**
|
||||
* 已终止
|
||||
*/
|
||||
TERMINATION("termination", "已终止");
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private final String status;
|
||||
|
||||
/**
|
||||
* 描述
|
||||
*/
|
||||
private final String desc;
|
||||
|
||||
/**
|
||||
* 获取业务状态
|
||||
*
|
||||
* @param status 状态
|
||||
*/
|
||||
public static String findByStatus(String status) {
|
||||
if (StringUtils.isBlank(status)) {
|
||||
return StrUtil.EMPTY;
|
||||
}
|
||||
return Arrays.stream(BusinessStatusEnum.values())
|
||||
.filter(statusEnum -> statusEnum.getStatus().equals(status))
|
||||
.findFirst()
|
||||
.map(BusinessStatusEnum::getDesc)
|
||||
.orElse(StrUtil.EMPTY);
|
||||
}
|
||||
|
||||
/**
|
||||
* 启动流程校验
|
||||
*
|
||||
* @param status 状态
|
||||
*/
|
||||
public static void checkStartStatus(String status) {
|
||||
if (WAITING.getStatus().equals(status)) {
|
||||
throw new ServiceException("该单据已提交过申请,正在审批中!");
|
||||
} else if (FINISH.getStatus().equals(status)) {
|
||||
throw new ServiceException("该单据已完成申请!");
|
||||
} else if (INVALID.getStatus().equals(status)) {
|
||||
throw new ServiceException("该单据已作废!");
|
||||
} else if (TERMINATION.getStatus().equals(status)) {
|
||||
throw new ServiceException("该单据已终止!");
|
||||
} else if (StringUtils.isBlank(status)) {
|
||||
throw new ServiceException("流程状态为空!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 撤销流程校验
|
||||
*
|
||||
* @param status 状态
|
||||
*/
|
||||
public static void checkCancelStatus(String status) {
|
||||
if (CANCEL.getStatus().equals(status)) {
|
||||
throw new ServiceException("该单据已撤销!");
|
||||
} else if (FINISH.getStatus().equals(status)) {
|
||||
throw new ServiceException("该单据已完成申请!");
|
||||
} else if (INVALID.getStatus().equals(status)) {
|
||||
throw new ServiceException("该单据已作废!");
|
||||
} else if (TERMINATION.getStatus().equals(status)) {
|
||||
throw new ServiceException("该单据已终止!");
|
||||
} else if (BACK.getStatus().equals(status)) {
|
||||
throw new ServiceException("该单据已退回!");
|
||||
} else if (StringUtils.isBlank(status)) {
|
||||
throw new ServiceException("流程状态为空!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 驳回流程校验
|
||||
*
|
||||
* @param status 状态
|
||||
*/
|
||||
public static void checkBackStatus(String status) {
|
||||
if (BACK.getStatus().equals(status)) {
|
||||
throw new ServiceException("该单据已退回!");
|
||||
} else if (FINISH.getStatus().equals(status)) {
|
||||
throw new ServiceException("该单据已完成申请!");
|
||||
} else if (INVALID.getStatus().equals(status)) {
|
||||
throw new ServiceException("该单据已作废!");
|
||||
} else if (TERMINATION.getStatus().equals(status)) {
|
||||
throw new ServiceException("该单据已终止!");
|
||||
} else if (CANCEL.getStatus().equals(status)) {
|
||||
throw new ServiceException("该单据已撤销!");
|
||||
} else if (StringUtils.isBlank(status)) {
|
||||
throw new ServiceException("流程状态为空!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 作废,终止流程校验
|
||||
*
|
||||
* @param status 状态
|
||||
*/
|
||||
public static void checkInvalidStatus(String status) {
|
||||
if (FINISH.getStatus().equals(status)) {
|
||||
throw new ServiceException("该单据已完成申请!");
|
||||
} else if (INVALID.getStatus().equals(status)) {
|
||||
throw new ServiceException("该单据已作废!");
|
||||
} else if (TERMINATION.getStatus().equals(status)) {
|
||||
throw new ServiceException("该单据已终止!");
|
||||
} else if (StringUtils.isBlank(status)) {
|
||||
throw new ServiceException("流程状态为空!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package org.dromara.common.core.factory;
|
||||
|
||||
import cn.hutool.core.lang.PatternPool;
|
||||
import org.dromara.common.core.constant.RegexConstants;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 正则表达式模式池工厂
|
||||
* <p>初始化的时候将正则表达式加入缓存池当中</p>
|
||||
* <p>提高正则表达式的性能,避免重复编译相同的正则表达式</p>
|
||||
*
|
||||
* @author 21001
|
||||
*/
|
||||
public class RegexPatternPoolFactory extends PatternPool {
|
||||
|
||||
/**
|
||||
* 字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)
|
||||
*/
|
||||
public static final Pattern DICTIONARY_TYPE = get(RegexConstants.DICTIONARY_TYPE);
|
||||
|
||||
/**
|
||||
* 身份证号码(后6位)
|
||||
*/
|
||||
public static final Pattern ID_CARD_LAST_6 = get(RegexConstants.ID_CARD_LAST_6);
|
||||
|
||||
/**
|
||||
* QQ号码
|
||||
*/
|
||||
public static final Pattern QQ_NUMBER = get(RegexConstants.QQ_NUMBER);
|
||||
|
||||
/**
|
||||
* 邮政编码
|
||||
*/
|
||||
public static final Pattern POSTAL_CODE = get(RegexConstants.POSTAL_CODE);
|
||||
|
||||
/**
|
||||
* 注册账号
|
||||
*/
|
||||
public static final Pattern ACCOUNT = get(RegexConstants.ACCOUNT);
|
||||
|
||||
/**
|
||||
* 密码:包含至少8个字符,包括大写字母、小写字母、数字和特殊字符
|
||||
*/
|
||||
public static final Pattern PASSWORD = get(RegexConstants.PASSWORD);
|
||||
|
||||
/**
|
||||
* 通用状态(0表示正常,1表示停用)
|
||||
*/
|
||||
public static final Pattern STATUS = get(RegexConstants.STATUS);
|
||||
|
||||
}
|
||||
|
|
@ -1,148 +0,0 @@
|
|||
package org.dromara.common.core.utils;
|
||||
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class ReUtil {
|
||||
public final static Pattern GROUP_VAR = Pattern.compile("\\$(\\d+)");
|
||||
|
||||
/**
|
||||
* 正则中需要被转义的关键字
|
||||
*/
|
||||
public final static Set<Character> RE_KEYS = new HashSet<>(
|
||||
Arrays.asList('$', '(', ')', '*', '+', '.', '[', ']', '?', '\\', '^', '{', '}', '|'));
|
||||
;
|
||||
|
||||
/**
|
||||
* 正则替换指定值<br>
|
||||
* 通过正则查找到字符串,然后把匹配到的字符串加入到replacementTemplate中,$1表示分组1的字符串
|
||||
*
|
||||
* <p>
|
||||
* 例如:原字符串是:中文1234,我想把1234换成(1234),则可以:
|
||||
*
|
||||
* <pre>
|
||||
* ReUtil.replaceAll("中文1234", "(\\d+)", "($1)"))
|
||||
*
|
||||
* 结果:中文(1234)
|
||||
* </pre>
|
||||
*
|
||||
* @param content 文本
|
||||
* @param regex 正则
|
||||
* @param replacementTemplate 替换的文本模板,可以使用$1类似的变量提取正则匹配出的内容
|
||||
* @return 处理后的文本
|
||||
*/
|
||||
public static String replaceAll(CharSequence content, String regex, String replacementTemplate) {
|
||||
final Pattern pattern = Pattern.compile(regex, Pattern.DOTALL);
|
||||
return replaceAll(content, pattern, replacementTemplate);
|
||||
}
|
||||
|
||||
/**
|
||||
* 正则替换指定值<br>
|
||||
* 通过正则查找到字符串,然后把匹配到的字符串加入到replacementTemplate中,$1表示分组1的字符串
|
||||
*
|
||||
* @param content 文本
|
||||
* @param pattern {@link Pattern}
|
||||
* @param replacementTemplate 替换的文本模板,可以使用$1类似的变量提取正则匹配出的内容
|
||||
* @return 处理后的文本
|
||||
* @since 3.0.4
|
||||
*/
|
||||
public static String replaceAll(CharSequence content, Pattern pattern, String replacementTemplate) {
|
||||
if (StringUtils.isEmpty(content)) {
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
final Matcher matcher = pattern.matcher(content);
|
||||
boolean result = matcher.find();
|
||||
if (result) {
|
||||
final Set<String> varNums = findAll(GROUP_VAR, replacementTemplate, 1, new HashSet<>());
|
||||
final StringBuffer sb = new StringBuffer();
|
||||
do {
|
||||
String replacement = replacementTemplate;
|
||||
for (String var : varNums) {
|
||||
int group = Integer.parseInt(var);
|
||||
replacement = replacement.replace("$" + var, matcher.group(group));
|
||||
}
|
||||
matcher.appendReplacement(sb, escape(replacement));
|
||||
result = matcher.find();
|
||||
}
|
||||
while (result);
|
||||
matcher.appendTail(sb);
|
||||
return sb.toString();
|
||||
}
|
||||
return Convert.toStr(content);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取得内容中匹配的所有结果
|
||||
*
|
||||
* @param <T> 集合类型
|
||||
* @param pattern 编译后的正则模式
|
||||
* @param content 被查找的内容
|
||||
* @param group 正则的分组
|
||||
* @param collection 返回的集合类型
|
||||
* @return 结果集
|
||||
*/
|
||||
public static <T extends Collection<String>> T findAll(Pattern pattern, CharSequence content, int group,
|
||||
T collection) {
|
||||
if (null == pattern || null == content) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (null == collection) {
|
||||
throw new NullPointerException("Null collection param provided!");
|
||||
}
|
||||
|
||||
final Matcher matcher = pattern.matcher(content);
|
||||
while (matcher.find()) {
|
||||
collection.add(matcher.group(group));
|
||||
}
|
||||
return collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* 转义字符,将正则的关键字转义
|
||||
*
|
||||
* @param c 字符
|
||||
* @return 转义后的文本
|
||||
*/
|
||||
public static String escape(char c) {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
if (RE_KEYS.contains(c)) {
|
||||
builder.append('\\');
|
||||
}
|
||||
builder.append(c);
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 转义字符串,将正则的关键字转义
|
||||
*
|
||||
* @param content 文本
|
||||
* @return 转义后的文本
|
||||
*/
|
||||
public static String escape(CharSequence content) {
|
||||
if (StringUtils.isBlank(content)) {
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
int len = content.length();
|
||||
char current;
|
||||
for (int i = 0; i < len; i++) {
|
||||
current = content.charAt(i);
|
||||
if (RE_KEYS.contains(current)) {
|
||||
builder.append('\\');
|
||||
}
|
||||
builder.append(current);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -3,13 +3,17 @@ package org.dromara.common.core.utils;
|
|||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import org.springframework.aop.framework.AopContext;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.boot.autoconfigure.thread.Threading;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* spring工具类
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Component
|
||||
public final class SpringUtils extends SpringUtil {
|
||||
|
||||
/**
|
||||
|
|
@ -57,4 +61,8 @@ public final class SpringUtils extends SpringUtil {
|
|||
return getApplicationContext();
|
||||
}
|
||||
|
||||
public static boolean isVirtual() {
|
||||
return Threading.VIRTUAL.isActive(getBean(Environment.class));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
|||
|
||||
public static final String SEPARATOR = ",";
|
||||
|
||||
public static final String SLASH = "/";
|
||||
|
||||
/**
|
||||
* 获取参数不为空值
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
package org.dromara.common.core.utils.regex;
|
||||
|
||||
|
||||
import cn.hutool.core.util.ReUtil;
|
||||
import org.dromara.common.core.constant.RegexConstants;
|
||||
|
||||
/**
|
||||
* 正则相关工具类
|
||||
*
|
||||
* @author Feng
|
||||
*/
|
||||
public final class RegexUtils extends ReUtil {
|
||||
|
||||
/**
|
||||
* 从输入字符串中提取匹配的部分,如果没有匹配则返回默认值
|
||||
*
|
||||
* @param input 要提取的输入字符串
|
||||
* @param regex 用于匹配的正则表达式,可以使用 {@link RegexConstants} 中定义的常量
|
||||
* @param defaultInput 如果没有匹配时返回的默认值
|
||||
* @return 如果找到匹配的部分,则返回匹配的部分,否则返回默认值
|
||||
*/
|
||||
public static String extractFromString(String input, String regex, String defaultInput) {
|
||||
try {
|
||||
return ReUtil.get(regex, input, 1);
|
||||
} catch (Exception e) {
|
||||
return defaultInput;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
package org.dromara.common.core.utils.regex;
|
||||
|
||||
import cn.hutool.core.exceptions.ValidateException;
|
||||
import cn.hutool.core.lang.Validator;
|
||||
import org.dromara.common.core.factory.RegexPatternPoolFactory;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 正则字段校验器
|
||||
* 主要验证字段非空、是否为满足指定格式等
|
||||
*
|
||||
* @author Feng
|
||||
*/
|
||||
public class RegexValidator extends Validator {
|
||||
|
||||
/**
|
||||
* 字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)
|
||||
*/
|
||||
public static final Pattern DICTIONARY_TYPE = RegexPatternPoolFactory.DICTIONARY_TYPE;
|
||||
|
||||
/**
|
||||
* 身份证号码(后6位)
|
||||
*/
|
||||
public static final Pattern ID_CARD_LAST_6 = RegexPatternPoolFactory.ID_CARD_LAST_6;
|
||||
|
||||
/**
|
||||
* QQ号码
|
||||
*/
|
||||
public static final Pattern QQ_NUMBER = RegexPatternPoolFactory.QQ_NUMBER;
|
||||
|
||||
/**
|
||||
* 邮政编码
|
||||
*/
|
||||
public static final Pattern POSTAL_CODE = RegexPatternPoolFactory.POSTAL_CODE;
|
||||
|
||||
/**
|
||||
* 注册账号
|
||||
*/
|
||||
public static final Pattern ACCOUNT = RegexPatternPoolFactory.ACCOUNT;
|
||||
|
||||
/**
|
||||
* 密码:包含至少8个字符,包括大写字母、小写字母、数字和特殊字符
|
||||
*/
|
||||
public static final Pattern PASSWORD = RegexPatternPoolFactory.PASSWORD;
|
||||
|
||||
/**
|
||||
* 通用状态(0表示正常,1表示停用)
|
||||
*/
|
||||
public static final Pattern STATUS = RegexPatternPoolFactory.STATUS;
|
||||
|
||||
|
||||
/**
|
||||
* 检查输入的账号是否匹配预定义的规则
|
||||
*
|
||||
* @param value 要验证的账号
|
||||
* @return 如果账号符合规则,返回 true;否则,返回 false。
|
||||
*/
|
||||
public static boolean isAccount(CharSequence value) {
|
||||
return isMatchRegex(ACCOUNT, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证输入的账号是否符合规则,如果不符合,则抛出 ValidateException 异常
|
||||
*
|
||||
* @param value 要验证的账号
|
||||
* @param errorMsg 验证失败时抛出的异常消息
|
||||
* @param <T> CharSequence 的子类型
|
||||
* @return 如果验证通过,返回输入的账号
|
||||
* @throws ValidateException 如果验证失败
|
||||
*/
|
||||
public static <T extends CharSequence> T validateAccount(T value, String errorMsg) throws ValidateException {
|
||||
if (!isAccount(value)) {
|
||||
throw new ValidateException(errorMsg);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查输入的状态是否匹配预定义的规则
|
||||
*
|
||||
* @param value 要验证的状态
|
||||
* @return 如果状态符合规则,返回 true;否则,返回 false。
|
||||
*/
|
||||
public static boolean isStatus(CharSequence value) {
|
||||
return isMatchRegex(STATUS, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证输入的状态是否符合规则,如果不符合,则抛出 ValidateException 异常
|
||||
*
|
||||
* @param value 要验证的状态
|
||||
* @param errorMsg 验证失败时抛出的异常消息
|
||||
* @param <T> CharSequence 的子类型
|
||||
* @return 如果验证通过,返回输入的状态
|
||||
* @throws ValidateException 如果验证失败
|
||||
*/
|
||||
public static <T extends CharSequence> T validateStatus(T value, String errorMsg) throws ValidateException {
|
||||
if (!isStatus(value)) {
|
||||
throw new ValidateException(errorMsg);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
org.dromara.common.core.utils.SpringUtils
|
||||
org.dromara.common.core.config.ApplicationConfig
|
||||
org.dromara.common.core.config.ValidatorConfig
|
||||
org.dromara.common.core.config.ThreadPoolConfig
|
||||
org.dromara.common.core.config.AsyncConfig
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -33,10 +33,6 @@
|
|||
<artifactId>dubbo-spring-boot-starter</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
package org.dromara.common.dict.service.impl;
|
||||
|
||||
import cn.dev33.satoken.context.SaHolder;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import org.apache.dubbo.config.annotation.DubboReference;
|
||||
import org.dromara.common.core.constant.CacheConstants;
|
||||
import org.dromara.common.core.service.DictService;
|
||||
import org.dromara.common.core.utils.StreamUtils;
|
||||
import org.dromara.common.core.utils.StringUtils;
|
||||
import org.dromara.system.api.RemoteDictService;
|
||||
import org.apache.dubbo.config.annotation.DubboReference;
|
||||
import org.dromara.system.api.domain.vo.RemoteDictDataVo;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
|
@ -24,6 +24,9 @@ import java.util.stream.Collectors;
|
|||
@Service
|
||||
public class DictServiceImpl implements DictService {
|
||||
|
||||
@Autowired
|
||||
private Cache<Object, Object> ceffeine;
|
||||
|
||||
@DubboReference
|
||||
private RemoteDictService remoteDictService;
|
||||
|
||||
|
|
@ -35,16 +38,13 @@ public class DictServiceImpl implements DictService {
|
|||
* @param separator 分隔符
|
||||
* @return 字典标签
|
||||
*/
|
||||
@SuppressWarnings("unchecked cast")
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public String getDictLabel(String dictType, String dictValue, String separator) {
|
||||
// 优先从本地缓存获取
|
||||
List<RemoteDictDataVo> datas = (List<RemoteDictDataVo>) SaHolder.getStorage().get(CacheConstants.SYS_DICT_KEY + dictType);
|
||||
if (ObjectUtil.isNull(datas)) {
|
||||
datas = remoteDictService.selectDictDataByType(dictType);
|
||||
SaHolder.getStorage().set(CacheConstants.SYS_DICT_KEY + dictType, datas);
|
||||
}
|
||||
|
||||
List<RemoteDictDataVo> datas = (List<RemoteDictDataVo>) ceffeine.get(CacheConstants.SYS_DICT_KEY + "remote:" + dictType, k -> {
|
||||
return remoteDictService.selectDictDataByType(dictType);
|
||||
});
|
||||
Map<String, String> map = StreamUtils.toMap(datas, RemoteDictDataVo::getDictValue, RemoteDictDataVo::getDictLabel);
|
||||
if (StringUtils.containsAny(dictValue, separator)) {
|
||||
return Arrays.stream(dictValue.split(separator))
|
||||
|
|
@ -63,16 +63,13 @@ public class DictServiceImpl implements DictService {
|
|||
* @param separator 分隔符
|
||||
* @return 字典值
|
||||
*/
|
||||
@SuppressWarnings("unchecked cast")
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public String getDictValue(String dictType, String dictLabel, String separator) {
|
||||
// 优先从本地缓存获取
|
||||
List<RemoteDictDataVo> datas = (List<RemoteDictDataVo>) SaHolder.getStorage().get(CacheConstants.SYS_DICT_KEY + dictType);
|
||||
if (ObjectUtil.isNull(datas)) {
|
||||
datas = remoteDictService.selectDictDataByType(dictType);
|
||||
SaHolder.getStorage().set(CacheConstants.SYS_DICT_KEY + dictType, datas);
|
||||
}
|
||||
|
||||
List<RemoteDictDataVo> datas = (List<RemoteDictDataVo>) ceffeine.get(CacheConstants.SYS_DICT_KEY + "remote:" + dictType, k -> {
|
||||
return remoteDictService.selectDictDataByType(dictType);
|
||||
});
|
||||
Map<String, String> map = StreamUtils.toMap(datas, RemoteDictDataVo::getDictLabel, RemoteDictDataVo::getDictValue);
|
||||
if (StringUtils.containsAny(dictLabel, separator)) {
|
||||
return Arrays.stream(dictLabel.split(separator))
|
||||
|
|
|
|||
|
|
@ -41,11 +41,6 @@
|
|||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-spring-boot3-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Sa-Token 整合 Dubbo -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
|
|
@ -59,5 +54,10 @@
|
|||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-commons</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
package org.dromara.common.dubbo.config;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.cloud.commons.util.InetUtils;
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
|
||||
/**
|
||||
* dubbo自定义IP注入(避免IP不正确问题)
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor, Ordered {
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return Ordered.HIGHEST_PRECEDENCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
|
||||
InetUtils inetUtils = beanFactory.getBean(InetUtils.class);
|
||||
String ip = "127.0.0.1";
|
||||
InetAddress address = inetUtils.findFirstNonLoopbackAddress();
|
||||
if (address != null) {
|
||||
if (address instanceof Inet6Address) {
|
||||
String ipv6AddressString = address.getHostAddress();
|
||||
if (ipv6AddressString.contains("%")) {
|
||||
ipv6AddressString = ipv6AddressString.substring(0, ipv6AddressString.indexOf("%"));
|
||||
}
|
||||
ip = ipv6AddressString;
|
||||
} else {
|
||||
ip = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress();
|
||||
}
|
||||
}
|
||||
System.setProperty("DUBBO_IP_TO_REGISTRY", ip);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,8 +2,10 @@ package org.dromara.common.dubbo.config;
|
|||
|
||||
import org.dromara.common.core.factory.YmlPropertySourceFactory;
|
||||
import org.dromara.common.dubbo.properties.DubboCustomProperties;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
|
||||
/**
|
||||
|
|
@ -14,4 +16,8 @@ import org.springframework.context.annotation.PropertySource;
|
|||
@PropertySource(value = "classpath:common-dubbo.yml", factory = YmlPropertySourceFactory.class)
|
||||
public class DubboConfiguration {
|
||||
|
||||
@Bean
|
||||
public BeanFactoryPostProcessor customBeanFactoryPostProcessor() {
|
||||
return new CustomBeanFactoryPostProcessor();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ dubbo:
|
|||
registry:
|
||||
address: nacos://${spring.cloud.nacos.server-addr}
|
||||
group: DUBBO_GROUP
|
||||
username: ${spring.cloud.nacos.username}
|
||||
password: ${spring.cloud.nacos.password}
|
||||
parameters:
|
||||
namespace: ${spring.profiles.active}
|
||||
# 消费者相关配置
|
||||
|
|
|
|||
|
|
@ -22,11 +22,6 @@
|
|||
<artifactId>ruoyi-common-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.mybatis.spring.boot</groupId>
|
||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15to18</artifactId>
|
||||
|
|
@ -42,6 +37,18 @@
|
|||
<artifactId>spring-webmvc</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
||||
<optional>true</optional>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.mybatis</groupId>
|
||||
<artifactId>mybatis-spring</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue