Compare commits
No commits in common. "master" and "v2026.01(jdk17/21)" have entirely different histories.
master
...
v2026.01(j
|
Before Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 163 KiB |
|
Before Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 74 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 216 KiB |
|
Before Width: | Height: | Size: 54 KiB |
61
README.md
|
|
@ -1,6 +1,6 @@
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="https://img.shields.io/badge/Spring%20Cloud-2021-blue.svg" alt="Coverage Status">
|
<img src="https://img.shields.io/badge/Spring%20Cloud-2024-blue.svg" alt="Coverage Status">
|
||||||
<img src="https://img.shields.io/badge/Spring%20Boot-2.7.18-blue.svg" alt="Downloads">
|
<img src="https://img.shields.io/badge/Spring%20Boot-3.4.5-blue.svg" alt="Downloads">
|
||||||
<img src="https://img.shields.io/badge/Vue-3.2-blue.svg" alt="Downloads">
|
<img src="https://img.shields.io/badge/Vue-3.2-blue.svg" alt="Downloads">
|
||||||
<img src="https://img.shields.io/github/license/YunaiV/yudao-cloud" alt="Downloads" />
|
<img src="https://img.shields.io/github/license/YunaiV/yudao-cloud" alt="Downloads" />
|
||||||
</p>
|
</p>
|
||||||
|
|
@ -31,8 +31,8 @@
|
||||||
| 【完整版】[yudao-cloud](https://gitee.com/zhijiantianya/yudao-cloud) | [`master`](https://gitee.com/zhijiantianya/yudao-cloud/tree/master/) 分支 | [`master-jdk17`](https://gitee.com/zhijiantianya/yudao-cloud/tree/master-jdk17/) 分支 |
|
| 【完整版】[yudao-cloud](https://gitee.com/zhijiantianya/yudao-cloud) | [`master`](https://gitee.com/zhijiantianya/yudao-cloud/tree/master/) 分支 | [`master-jdk17`](https://gitee.com/zhijiantianya/yudao-cloud/tree/master-jdk17/) 分支 |
|
||||||
| 【精简版】[yudao-cloud-mini](https://gitee.com/yudaocode/yudao-cloud-mini) | [`master`](https://gitee.com/yudaocode/yudao-cloud-mini/tree/master/) 分支 | [`master-jdk17`](https://gitee.com/yudaocode/yudao-cloud-mini/tree/master-jdk17/) 分支 |
|
| 【精简版】[yudao-cloud-mini](https://gitee.com/yudaocode/yudao-cloud-mini) | [`master`](https://gitee.com/yudaocode/yudao-cloud-mini/tree/master/) 分支 | [`master-jdk17`](https://gitee.com/yudaocode/yudao-cloud-mini/tree/master-jdk17/) 分支 |
|
||||||
|
|
||||||
* 【完整版】:包括系统功能、基础设施、会员中心、数据报表、工作流程、商城系统、微信公众号、CRM、ERP、WMS、MES、AI 大模型、IoT 物联网 等功能
|
* 【完整版】:包括系统功能、基础设施、会员中心、数据报表、工作流程、商城系统、微信公众号、CRM、ERP 等功能
|
||||||
* 【精简版】:只包括系统功能、基础设施功能,不包括会员中心、数据报表、工作流程、商城系统、微信公众号、CRM、ERP、WMS、MES、AI 大模型、IoT 物联网 等功能
|
* 【精简版】:只包括系统功能、基础设施功能,不包括会员中心、数据报表、工作流程、商城系统、微信公众号、CRM、ERP 等功能
|
||||||
|
|
||||||
可参考 [《迁移文档》](https://cloud.iocoder.cn/migrate-module/) ,只需要 5-10 分钟,即可将【完整版】按需迁移到【精简版】
|
可参考 [《迁移文档》](https://cloud.iocoder.cn/migrate-module/) ,只需要 5-10 分钟,即可将【完整版】按需迁移到【精简版】
|
||||||
|
|
||||||
|
|
@ -115,7 +115,7 @@
|
||||||
|
|
||||||
* 通用模块(必选):系统功能、基础设施
|
* 通用模块(必选):系统功能、基础设施
|
||||||
* 通用模块(可选):工作流程、支付系统、数据报表、会员中心
|
* 通用模块(可选):工作流程、支付系统、数据报表、会员中心
|
||||||
* 业务系统(按需):Mall 电子商城、OA 办公自动化、ERP 企业资源计划系统、WMS 仓库管理系统、CRM 客户关系管理、CMS 内容管理系统、MES 执行制造系统、AI 大模型平台、IoT 物联网系统、IM 即时通讯系统、Mobile 手机移动端、Report 数据大屏
|
* 业务系统(按需):ERP 系统、CRM 系统、商城系统、微信公众号、AI 大模型
|
||||||
|
|
||||||
> 友情提示:本项目基于 RuoYi-Vue 修改,**重构优化**后端的代码,**美化**前端的界面。
|
> 友情提示:本项目基于 RuoYi-Vue 修改,**重构优化**后端的代码,**美化**前端的界面。
|
||||||
>
|
>
|
||||||
|
|
@ -273,28 +273,12 @@
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
### WMS 系统
|
|
||||||
|
|
||||||
演示地址:<https://cloud.iocoder.cn/wms-preview/>
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### CRM 系统
|
### CRM 系统
|
||||||
|
|
||||||
演示地址:<https://cloud.iocoder.cn/crm-preview/>
|
演示地址:<https://cloud.iocoder.cn/crm-preview/>
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
### MES 系统
|
|
||||||
|
|
||||||
演示地址:<https://cloud.iocoder.cn/mes-preview/>
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
### AI 大模型
|
### AI 大模型
|
||||||
|
|
||||||
演示地址:<https://cloud.iocoder.cn/ai-preview/>
|
演示地址:<https://cloud.iocoder.cn/ai-preview/>
|
||||||
|
|
@ -303,14 +287,6 @@
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
### IoT 物联网
|
|
||||||
|
|
||||||
演示地址:<https://cloud.iocoder.cn/iot/build>
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## 🐨 技术栈
|
## 🐨 技术栈
|
||||||
|
|
||||||
### 微服务
|
### 微服务
|
||||||
|
|
@ -328,10 +304,7 @@
|
||||||
| `yudao-module-mall` | 商城系统的 Module 模块 |
|
| `yudao-module-mall` | 商城系统的 Module 模块 |
|
||||||
| `yudao-module-erp` | ERP 系统的 Module 模块 |
|
| `yudao-module-erp` | ERP 系统的 Module 模块 |
|
||||||
| `yudao-module-crm` | CRM 系统的 Module 模块 |
|
| `yudao-module-crm` | CRM 系统的 Module 模块 |
|
||||||
| `yudao-module-mes` | MES 系统的 Module 模块 |
|
|
||||||
| `yudao-module-wms` | WMS 系统的 Module 模块 |
|
|
||||||
| `yudao-module-ai` | AI 大模型的 Module 模块 |
|
| `yudao-module-ai` | AI 大模型的 Module 模块 |
|
||||||
| `yudao-module-iot` | IoT 物联网的 Module 模块 |
|
|
||||||
| `yudao-module-mp` | 微信公众号的 Module 模块 |
|
| `yudao-module-mp` | 微信公众号的 Module 模块 |
|
||||||
| `yudao-module-report` | 大屏报表 Module 模块 |
|
| `yudao-module-report` | 大屏报表 Module 模块 |
|
||||||
|
|
||||||
|
|
@ -339,12 +312,12 @@
|
||||||
|
|
||||||
| 框架 | 说明 | 版本 | 学习指南 |
|
| 框架 | 说明 | 版本 | 学习指南 |
|
||||||
|---------------------------------------------------------------------------------------------|------------------|------------|---------------------------------------------------------------------|
|
|---------------------------------------------------------------------------------------------|------------------|------------|---------------------------------------------------------------------|
|
||||||
| [Spring Cloud Alibaba](https://github.com/alibaba/spring-cloud-alibaba) | 微服务框架 | 2021.0.4.0 | [文档](https://github.com/YunaiV/SpringBoot-Labs) |
|
| [Spring Cloud Alibaba](https://github.com/alibaba/spring-cloud-alibaba) | 微服务框架 | 2023.0.1 | [文档](https://github.com/YunaiV/SpringBoot-Labs) |
|
||||||
| [Nacos](https://github.com/alibaba/nacos) | 配置中心 & 注册中心 | 2.3.2 | [文档](https://www.iocoder.cn/categories/Nacos/?yudao) |
|
| [Nacos](https://github.com/alibaba/nacos) | 配置中心 & 注册中心 | 2.3.2 | [文档](https://www.iocoder.cn/categories/Nacos/?yudao) |
|
||||||
| [RocketMQ](https://github.com/apache/rocketmq) | 消息队列 | 5.2.0 | [文档](https://www.iocoder.cn/categories/RocketMQ/?yudao) |
|
| [RocketMQ](https://github.com/apache/rocketmq) | 消息队列 | 5.2.0 | [文档](https://www.iocoder.cn/categories/RocketMQ/?yudao) |
|
||||||
| [Sentinel](https://github.com/alibaba/sentinel) | 服务保障 | 1.8.6 | [文档](https://www.iocoder.cn/categories/Sentinel/?yudao) |
|
| [Sentinel](https://github.com/alibaba/sentinel) | 服务保障 | 1.8.6 | [文档](https://www.iocoder.cn/categories/Sentinel/?yudao) |
|
||||||
| [XXL Job](https://github.com/xuxueli/xxl-job) | 定时任务 | 2.3.1 | [文档](https://www.iocoder.cn/XXL-JOB/good-collection/?yudao) |
|
| [XXL Job](https://github.com/xuxueli/xxl-job) | 定时任务 | 2.4.0 | [文档](https://www.iocoder.cn/XXL-JOB/good-collection/?yudao) |
|
||||||
| [Spring Cloud Gateway](https://github.com/spring-cloud/spring-cloud-gateway) | 服务网关 | 3.4.1 | [文档](https://www.iocoder.cn/categories/Spring-Cloud-Gateway/?yudao) |
|
| [Spring Cloud Gateway](https://github.com/spring-cloud/spring-cloud-gateway) | 服务网关 | 4.1.0 | [文档](https://www.iocoder.cn/categories/Spring-Cloud-Gateway/?yudao) |
|
||||||
| [Seata](https://github.com/seata/seata) | 分布式事务 | 1.6.1 | [文档](https://www.iocoder.cn/categories/Seata/?yudao) |
|
| [Seata](https://github.com/seata/seata) | 分布式事务 | 1.6.1 | [文档](https://www.iocoder.cn/categories/Seata/?yudao) |
|
||||||
| [MySQL](https://www.mysql.com/cn/) | 数据库服务器 | 5.7 / 8.0+ | |
|
| [MySQL](https://www.mysql.com/cn/) | 数据库服务器 | 5.7 / 8.0+ | |
|
||||||
| [Druid](https://github.com/alibaba/druid) | JDBC 连接池、监控组件 | 1.2.23 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
|
| [Druid](https://github.com/alibaba/druid) | JDBC 连接池、监控组件 | 1.2.23 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
|
||||||
|
|
@ -352,18 +325,18 @@
|
||||||
| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 4.3.1 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
|
| [Dynamic Datasource](https://dynamic-datasource.com/) | 动态数据源 | 4.3.1 | [文档](http://www.iocoder.cn/Spring-Boot/datasource-pool/?yudao) |
|
||||||
| [Redis](https://redis.io/) | key-value 数据库 | 5.0 / 6.0 | |
|
| [Redis](https://redis.io/) | key-value 数据库 | 5.0 / 6.0 | |
|
||||||
| [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 3.32.0 | [文档](http://www.iocoder.cn/Spring-Boot/Redis/?yudao) |
|
| [Redisson](https://github.com/redisson/redisson) | Redis 客户端 | 3.32.0 | [文档](http://www.iocoder.cn/Spring-Boot/Redis/?yudao) |
|
||||||
| [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架 | 5.3.24 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) |
|
| [Spring MVC](https://github.com/spring-projects/spring-framework/tree/master/spring-webmvc) | MVC 框架 | 6.1.10 | [文档](http://www.iocoder.cn/SpringMVC/MVC/?yudao) |
|
||||||
| [Spring Security](https://github.com/spring-projects/spring-security) | Spring 安全框架 | 5.7.5 | [文档](http://www.iocoder.cn/Spring-Boot/Spring-Security/?yudao) |
|
| [Spring Security](https://github.com/spring-projects/spring-security) | Spring 安全框架 | 6.3.1 | [文档](http://www.iocoder.cn/Spring-Boot/Spring-Security/?yudao) |
|
||||||
| [Hibernate Validator](https://github.com/hibernate/hibernate-validator) | 参数校验组件 | 6.2.5 | [文档](http://www.iocoder.cn/Spring-Boot/Validation/?yudao) |
|
| [Hibernate Validator](https://github.com/hibernate/hibernate-validator) | 参数校验组件 | 8.0.1 | [文档](http://www.iocoder.cn/Spring-Boot/Validation/?yudao) |
|
||||||
| [Flowable](https://github.com/flowable/flowable-engine) | 工作流引擎 | 6.8.0 | [文档](https://doc.iocoder.cn/bpm/) |
|
| [Flowable](https://github.com/flowable/flowable-engine) | 工作流引擎 | 7.0.0 | [文档](https://doc.iocoder.cn/bpm/) |
|
||||||
| [Knife4j](https://gitee.com/xiaoym/knife4j) | Swagger 增强 UI 实现 | 4.5.0 | [文档](http://www.iocoder.cn/Spring-Boot/Swagger/?yudao) |
|
| [Knife4j](https://gitee.com/xiaoym/knife4j) | Swagger 增强 UI 实现 | 4.5.0 | [文档](http://www.iocoder.cn/Spring-Boot/Swagger/?yudao) |
|
||||||
| [SkyWalking](https://skywalking.apache.org/) | 分布式应用追踪系统 | 8.12.0 | [文档](http://www.iocoder.cn/Spring-Boot/SkyWalking/?yudao) |
|
| [SkyWalking](https://skywalking.apache.org/) | 分布式应用追踪系统 | 9.0.0 | [文档](http://www.iocoder.cn/Spring-Boot/SkyWalking/?yudao) |
|
||||||
| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 2.7.10 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) |
|
| [Spring Boot Admin](https://github.com/codecentric/spring-boot-admin) | Spring Boot 监控平台 | 3.6.1 | [文档](http://www.iocoder.cn/Spring-Boot/Admin/?yudao) |
|
||||||
| [Jackson](https://github.com/FasterXML/jackson) | JSON 工具库 | 2.13.3 | |
|
| [Jackson](https://github.com/FasterXML/jackson) | JSON 工具库 | 2.17.1 | |
|
||||||
| [MapStruct](https://mapstruct.org/) | Java Bean 转换 | 1.6.3 | [文档](http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao) |
|
| [MapStruct](https://mapstruct.org/) | Java Bean 转换 | 1.6.3 | [文档](http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao) |
|
||||||
| [Lombok](https://projectlombok.org/) | 消除冗长的 Java 代码 | 1.18.34 | [文档](http://www.iocoder.cn/Spring-Boot/Lombok/?yudao) |
|
| [Lombok](https://projectlombok.org/) | 消除冗长的 Java 代码 | 1.18.34 | [文档](http://www.iocoder.cn/Spring-Boot/Lombok/?yudao) |
|
||||||
| [JUnit](https://junit.org/junit5/) | Java 单元测试框架 | 5.8.2 | - |
|
| [JUnit](https://junit.org/junit5/) | Java 单元测试框架 | 5.10.1 | - |
|
||||||
| [Mockito](https://github.com/mockito/mockito) | Java Mock 框架 | 4.8.0 | - |
|
| [Mockito](https://github.com/mockito/mockito) | Java Mock 框架 | 5.7.0 | - |
|
||||||
|
|
||||||
## 🐷 演示图
|
## 🐷 演示图
|
||||||
|
|
||||||
|
|
|
||||||
35
pom.xml
|
|
@ -22,13 +22,10 @@
|
||||||
<module>yudao-module-report</module>
|
<module>yudao-module-report</module>
|
||||||
<module>yudao-module-mp</module>
|
<module>yudao-module-mp</module>
|
||||||
<module>yudao-module-mall</module>
|
<module>yudao-module-mall</module>
|
||||||
<module>yudao-module-erp</module>
|
|
||||||
<module>yudao-module-crm</module>
|
<module>yudao-module-crm</module>
|
||||||
|
<module>yudao-module-erp</module>
|
||||||
|
<module>yudao-module-ai</module>
|
||||||
<module>yudao-module-iot</module>
|
<module>yudao-module-iot</module>
|
||||||
<module>yudao-module-mes</module>
|
|
||||||
<module>yudao-module-wms</module>
|
|
||||||
<!-- 友情提示:基于 Spring AI 实现 LLM 大模型的接入,需要使用 JDK17 版本,详细可见 https://doc.iocoder.cn/ai/build/ -->
|
|
||||||
<!-- <module>yudao-module-ai</module>-->
|
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<name>${project.artifactId}</name>
|
<name>${project.artifactId}</name>
|
||||||
|
|
@ -36,9 +33,9 @@
|
||||||
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<revision>2026.04-jdk8-SNAPSHOT</revision>
|
<revision>2026.01-SNAPSHOT</revision>
|
||||||
<!-- Maven 相关 -->
|
<!-- Maven 相关 -->
|
||||||
<java.version>1.8</java.version>
|
<java.version>17</java.version>
|
||||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||||
<maven-surefire-plugin.version>3.5.3</maven-surefire-plugin.version>
|
<maven-surefire-plugin.version>3.5.3</maven-surefire-plugin.version>
|
||||||
|
|
@ -46,7 +43,7 @@
|
||||||
<flatten-maven-plugin.version>1.7.2</flatten-maven-plugin.version>
|
<flatten-maven-plugin.version>1.7.2</flatten-maven-plugin.version>
|
||||||
<!-- maven-surefire-plugin 暂时无法通过 bom 的依赖读取(兼容老版本 IDEA 2024 及以前版本) -->
|
<!-- maven-surefire-plugin 暂时无法通过 bom 的依赖读取(兼容老版本 IDEA 2024 及以前版本) -->
|
||||||
<lombok.version>1.18.42</lombok.version>
|
<lombok.version>1.18.42</lombok.version>
|
||||||
<spring.boot.version>2.7.18</spring.boot.version>
|
<spring.boot.version>3.5.9</spring.boot.version>
|
||||||
<mapstruct.version>1.6.3</mapstruct.version>
|
<mapstruct.version>1.6.3</mapstruct.version>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
@ -104,6 +101,11 @@
|
||||||
<version>${mapstruct.version}</version>
|
<version>${mapstruct.version}</version>
|
||||||
</path>
|
</path>
|
||||||
</annotationProcessorPaths>
|
</annotationProcessorPaths>
|
||||||
|
<!-- 编译参数写在 arg 内,解决 Spring Boot 3.2 的 Parameter Name Discovery 问题 -->
|
||||||
|
<debug>false</debug>
|
||||||
|
<compilerArgs>
|
||||||
|
<arg>-parameters</arg>
|
||||||
|
</compilerArgs>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
|
|
@ -151,6 +153,23 @@
|
||||||
<name>aliyun</name>
|
<name>aliyun</name>
|
||||||
<url>https://maven.aliyun.com/repository/public</url>
|
<url>https://maven.aliyun.com/repository/public</url>
|
||||||
</repository>
|
</repository>
|
||||||
|
|
||||||
|
<repository>
|
||||||
|
<id>spring-milestones</id>
|
||||||
|
<name>Spring Milestones</name>
|
||||||
|
<url>https://repo.spring.io/milestone</url>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
<repository>
|
||||||
|
<id>spring-snapshots</id>
|
||||||
|
<name>Spring Snapshots</name>
|
||||||
|
<url>https://repo.spring.io/snapshot</url>
|
||||||
|
<releases>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</releases>
|
||||||
|
</repository>
|
||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
||||||
|
|
@ -62,10 +62,6 @@ def load_and_clean(sql_file: str) -> str:
|
||||||
content = open(sql_file, encoding="utf-8").read()
|
content = open(sql_file, encoding="utf-8").read()
|
||||||
for replace_pair in REPLACE_PAIR_LIST:
|
for replace_pair in REPLACE_PAIR_LIST:
|
||||||
content = content.replace(*replace_pair)
|
content = content.replace(*replace_pair)
|
||||||
# 移除所有 CHARACTER SET / COLLATE 变体 (utf8mb3、utf8 等)
|
|
||||||
content = re.sub(r" CHARACTER SET \w+ COLLATE \w+", "", content)
|
|
||||||
content = re.sub(r" CHARACTER SET \w+", "", content)
|
|
||||||
content = re.sub(r" COLLATE \w+", "", content)
|
|
||||||
# 移除索引字段的前缀长度定义,例如: `name`(32) -> `name`
|
# 移除索引字段的前缀长度定义,例如: `name`(32) -> `name`
|
||||||
# 移除索引定义上的 USING BTREE COMMENT 部分
|
# 移除索引定义上的 USING BTREE COMMENT 部分
|
||||||
# 相关 issue:https://t.zsxq.com/96IFc 、https://t.zsxq.com/rC3A3
|
# 相关 issue:https://t.zsxq.com/96IFc 、https://t.zsxq.com/rC3A3
|
||||||
|
|
@ -81,11 +77,7 @@ class Convertor(ABC):
|
||||||
self.src = src
|
self.src = src
|
||||||
self.db_type = db_type
|
self.db_type = db_type
|
||||||
self.content = load_and_clean(self.src)
|
self.content = load_and_clean(self.src)
|
||||||
# original_content 保留原始 COMMENT 信息,用于注释提取
|
self.table_script_list = re.findall(r"CREATE TABLE [^;]*;", self.content)
|
||||||
self.original_content = open(src, encoding="utf-8").read()
|
|
||||||
# 剥离列级 COMMENT 以避免 COMMENT 值内的分号截断 CREATE TABLE 正则
|
|
||||||
content_no_comment = re.sub(r" COMMENT '(?:[^'\\]|\\.)*'", "", self.content)
|
|
||||||
self.table_script_list = re.findall(r"CREATE TABLE [^;]*;", content_no_comment)
|
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def translate_type(self, type: str, size: Optional[Union[int, Tuple[int]]]) -> str:
|
def translate_type(self, type: str, size: Optional[Union[int, Tuple[int]]]) -> str:
|
||||||
|
|
@ -190,8 +182,7 @@ class Convertor(ABC):
|
||||||
head = head.strip().replace("`", "").lower()
|
head = head.strip().replace("`", "").lower()
|
||||||
tail = tail.strip().replace(r"\"", '"')
|
tail = tail.strip().replace(r"\"", '"')
|
||||||
# tail = tail.replace("b'0'", "'0'").replace("b'1'", "'1'")
|
# tail = tail.replace("b'0'", "'0'").replace("b'1'", "'1'")
|
||||||
col_part = f" {head}" if head else ""
|
yield f"INSERT INTO {table_name.lower()} {head} VALUES {tail}"
|
||||||
yield f"INSERT INTO {table_name.lower()}{col_part} VALUES {tail}"
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def index(ddl: Dict) -> Generator:
|
def index(ddl: Dict) -> Generator:
|
||||||
|
|
@ -236,8 +227,7 @@ class Convertor(ABC):
|
||||||
yield field, comment_string
|
yield field, comment_string
|
||||||
|
|
||||||
def table_comment(self, table_sql: str) -> str:
|
def table_comment(self, table_sql: str) -> str:
|
||||||
# 兼容 COMMENT='xxx' / COMMENT = 'xxx' 等等号两侧空格变体;允许 COMMENT 内含转义单引号
|
match = re.search(r"COMMENT \='([^']+)';", table_sql)
|
||||||
match = re.search(r"COMMENT\s*=\s*'((?:[^'\\]|\\.)*)'", table_sql)
|
|
||||||
return match.group(1) if match else None
|
return match.group(1) if match else None
|
||||||
|
|
||||||
def print(self):
|
def print(self):
|
||||||
|
|
@ -261,9 +251,7 @@ class Convertor(ABC):
|
||||||
|
|
||||||
error_scripts = []
|
error_scripts = []
|
||||||
for table_sql in self.table_script_list:
|
for table_sql in self.table_script_list:
|
||||||
# 剥离 COMMENT 子句避免 DDLParser 无法处理中文等特殊字符
|
ddl = DDLParser(table_sql.replace("`", "")).run()
|
||||||
table_sql_for_parse = re.sub(r"\s+COMMENT\s+'[^']*'", "", table_sql)
|
|
||||||
ddl = DDLParser(table_sql_for_parse.replace("`", "")).run()
|
|
||||||
|
|
||||||
# 如果parse失败, 需要跟进
|
# 如果parse失败, 需要跟进
|
||||||
if len(ddl) == 0:
|
if len(ddl) == 0:
|
||||||
|
|
@ -278,23 +266,17 @@ class Convertor(ABC):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# 解析注释
|
# 解析注释
|
||||||
# 从原始 SQL 提取注释(支持中文等 DDLParser 不能处理的内容)
|
|
||||||
# 按表名定位完整建表段(以「换行 + )」起始的 ENGINE 行作为终止),避免被列 COMMENT 内的分号截断
|
|
||||||
orig_match = re.search(
|
|
||||||
rf"CREATE TABLE\s+`{re.escape(table_name)}`[\s\S]*?\n\)[^;]*;",
|
|
||||||
self.original_content,
|
|
||||||
flags=re.IGNORECASE,
|
|
||||||
)
|
|
||||||
orig_table_sql = orig_match.group() if orig_match else table_sql
|
|
||||||
comments_dict = dict(Convertor.filed_comments(orig_table_sql))
|
|
||||||
for column in table_ddl["columns"]:
|
for column in table_ddl["columns"]:
|
||||||
column["comment"] = comments_dict.get(column["name"], "")
|
column["comment"] = bytes(column["comment"], "utf-8").decode(
|
||||||
table_ddl["comment"] = self.table_comment(orig_table_sql) or ""
|
r"unicode_escape"
|
||||||
|
)[1:-1]
|
||||||
|
table_ddl["comment"] = bytes(table_ddl["comment"], "utf-8").decode(
|
||||||
|
r"unicode_escape"
|
||||||
|
)[1:-1]
|
||||||
|
|
||||||
# 为每个表生成个6个基本部分
|
# 为每个表生成个6个基本部分
|
||||||
create = self.gen_create(table_ddl)
|
create = self.gen_create(table_ddl)
|
||||||
has_id = any(col["name"].lower() == "id" for col in table_ddl["columns"])
|
pk = self.gen_pk(table_name)
|
||||||
pk = self.gen_pk(table_name) if has_id else ""
|
|
||||||
uk = self.gen_uk(table_ddl)
|
uk = self.gen_uk(table_ddl)
|
||||||
index = self.gen_index(table_ddl)
|
index = self.gen_index(table_ddl)
|
||||||
comment = self.gen_comment(table_ddl)
|
comment = self.gen_comment(table_ddl)
|
||||||
|
|
@ -338,31 +320,25 @@ class PostgreSQLConvertor(Convertor):
|
||||||
|
|
||||||
if type == "varchar":
|
if type == "varchar":
|
||||||
return f"varchar({size})"
|
return f"varchar({size})"
|
||||||
if type in ("int", "int unsigned", "int unsigned zerofill"):
|
if type in ("int", "int unsigned"):
|
||||||
return "int4"
|
return "int4"
|
||||||
if type in ("bigint", "bigint unsigned"):
|
if type in ("bigint", "bigint unsigned"):
|
||||||
return "int8"
|
return "int8"
|
||||||
if type in ("tinyint", "smallint", "tinyint unsigned"):
|
if type == "datetime":
|
||||||
return "int2"
|
|
||||||
if type in ("datetime", "timestamp null"):
|
|
||||||
return "timestamp"
|
return "timestamp"
|
||||||
if type == "date":
|
|
||||||
return "date"
|
|
||||||
if type == "json":
|
|
||||||
return "jsonb"
|
|
||||||
if type == "double":
|
|
||||||
return "double precision"
|
|
||||||
if type == "timestamp":
|
if type == "timestamp":
|
||||||
return f"timestamp({size})" if size else "timestamp"
|
return f"timestamp({size})"
|
||||||
if type == "bit":
|
if type == "bit":
|
||||||
return "bool"
|
return "bool"
|
||||||
|
if type in ("tinyint", "smallint"):
|
||||||
|
return "int2"
|
||||||
if type in ("text", "longtext"):
|
if type in ("text", "longtext"):
|
||||||
return "text"
|
return "text"
|
||||||
if type in ("blob", "mediumblob", "longblob"):
|
if type in ("blob", "mediumblob"):
|
||||||
return "bytea"
|
return "bytea"
|
||||||
if type == "decimal":
|
if type == "decimal":
|
||||||
return (
|
return (
|
||||||
f"numeric({','.join(str(s) for s in size)})" if size and len(size) else "numeric"
|
f"numeric({','.join(str(s) for s in size)})" if len(size) else "numeric"
|
||||||
)
|
)
|
||||||
|
|
||||||
def gen_create(self, ddl: Dict) -> str:
|
def gen_create(self, ddl: Dict) -> str:
|
||||||
|
|
@ -375,10 +351,6 @@ class PostgreSQLConvertor(Convertor):
|
||||||
|
|
||||||
type = col["type"].lower()
|
type = col["type"].lower()
|
||||||
full_type = self.translate_type(type, col["size"])
|
full_type = self.translate_type(type, col["size"])
|
||||||
if full_type is None:
|
|
||||||
raise NotImplementedError(
|
|
||||||
f"未支持的类型: '{col['type']}' (列: {name}, 表: {ddl['table_name']})"
|
|
||||||
)
|
|
||||||
nullable = "NULL" if col["nullable"] else "NOT NULL"
|
nullable = "NULL" if col["nullable"] else "NOT NULL"
|
||||||
default = f"DEFAULT {col['default']}" if col["default"] is not None else ""
|
default = f"DEFAULT {col['default']}" if col["default"] is not None else ""
|
||||||
return f"{name} {full_type} {nullable} {default}"
|
return f"{name} {full_type} {nullable} {default}"
|
||||||
|
|
@ -435,8 +407,6 @@ CREATE TABLE {table_name} (
|
||||||
"""生成 insert 语句,以及根据最后的 insert id+1 生成 Sequence"""
|
"""生成 insert 语句,以及根据最后的 insert id+1 生成 Sequence"""
|
||||||
|
|
||||||
inserts = list(Convertor.inserts(table_name, self.content))
|
inserts = list(Convertor.inserts(table_name, self.content))
|
||||||
# 转换 MySQL 字符串转义为 PostgreSQL 格式:\\ -> \,\' -> ''
|
|
||||||
inserts = [re.sub(r"\\\\|\\'", lambda m: "\\" if m.group() == "\\\\" else "''", s) for s in inserts]
|
|
||||||
## 生成 insert 脚本
|
## 生成 insert 脚本
|
||||||
script = ""
|
script = ""
|
||||||
last_id = 0
|
last_id = 0
|
||||||
|
|
|
||||||
|
|
@ -14,30 +14,27 @@
|
||||||
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
<url>https://github.com/YunaiV/ruoyi-vue-pro</url>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<revision>2026.04-jdk8-SNAPSHOT</revision>
|
<revision>2026.01-SNAPSHOT</revision>
|
||||||
<flatten-maven-plugin.version>1.6.0</flatten-maven-plugin.version>
|
<flatten-maven-plugin.version>1.7.2</flatten-maven-plugin.version>
|
||||||
<!-- 统一依赖管理 -->
|
<!-- 统一依赖管理 -->
|
||||||
<spring.framework.version>5.3.39</spring.framework.version>
|
<spring.boot.version>3.5.9</spring.boot.version>
|
||||||
<spring.security.version>5.8.16</spring.security.version>
|
<spring.cloud.version>2025.0.0</spring.cloud.version>
|
||||||
<spring.boot.version>2.7.18</spring.boot.version>
|
<spring.cloud.alibaba.version>2023.0.3.3</spring.cloud.alibaba.version>
|
||||||
<spring.cloud.version>2021.0.9</spring.cloud.version> <!-- Spring Boot 2.X 最多使用 2021.0.9 版本 -->
|
|
||||||
<spring.cloud.alibaba.version>2021.0.6.2</spring.cloud.alibaba.version> <!-- Spring Boot 2.X 最多使用 2021.0.6.2 版本 -->
|
|
||||||
<!-- Web 相关 -->
|
<!-- Web 相关 -->
|
||||||
<servlet.versoin>2.5</servlet.versoin>
|
<springdoc.version>2.8.14</springdoc.version>
|
||||||
<springdoc.version>1.8.0</springdoc.version>
|
|
||||||
<knife4j.version>4.5.0</knife4j.version>
|
<knife4j.version>4.5.0</knife4j.version>
|
||||||
<!-- DB 相关 -->
|
<!-- DB 相关 -->
|
||||||
<druid.version>1.2.28</druid.version>
|
<druid.version>1.2.27</druid.version>
|
||||||
<mybatis.version>3.5.19</mybatis.version>
|
<mybatis.version>3.5.19</mybatis.version>
|
||||||
<mybatis-plus.version>3.5.16</mybatis-plus.version>
|
<mybatis-plus.version>3.5.15</mybatis-plus.version>
|
||||||
<mybatis-plus-join.version>1.5.7</mybatis-plus-join.version>
|
<mybatis-plus-join.version>1.5.5</mybatis-plus-join.version>
|
||||||
<dynamic-datasource.version>4.5.0</dynamic-datasource.version>
|
<dynamic-datasource.version>4.5.0</dynamic-datasource.version>
|
||||||
<easy-trans.version>3.0.6</easy-trans.version>
|
<easy-trans.version>3.0.6</easy-trans.version>
|
||||||
<redisson.version>4.3.1</redisson.version>
|
<redisson.version>3.52.0</redisson.version>
|
||||||
<dm8.jdbc.version>8.1.3.140</dm8.jdbc.version>
|
<dm8.jdbc.version>8.1.3.140</dm8.jdbc.version>
|
||||||
<kingbase.jdbc.version>9.0.1.jre7</kingbase.jdbc.version>
|
<kingbase.jdbc.version>8.6.0</kingbase.jdbc.version>
|
||||||
<opengauss.jdbc.version>7.0.0-RC3-og</opengauss.jdbc.version>
|
<opengauss.jdbc.version>5.1.0</opengauss.jdbc.version>
|
||||||
<taos.version>3.8.3</taos.version>
|
<taos.version>3.7.9</taos.version>
|
||||||
<!-- 消息队列 -->
|
<!-- 消息队列 -->
|
||||||
<rocketmq-spring.version>2.3.5</rocketmq-spring.version>
|
<rocketmq-spring.version>2.3.5</rocketmq-spring.version>
|
||||||
<!-- RPC 相关 -->
|
<!-- RPC 相关 -->
|
||||||
|
|
@ -47,51 +44,47 @@
|
||||||
<!-- 服务保障相关 -->
|
<!-- 服务保障相关 -->
|
||||||
<lock4j.version>2.2.7</lock4j.version>
|
<lock4j.version>2.2.7</lock4j.version>
|
||||||
<!-- 监控相关 -->
|
<!-- 监控相关 -->
|
||||||
<skywalking.version>8.12.0</skywalking.version>
|
<skywalking.version>9.5.0</skywalking.version>
|
||||||
<spring-boot-admin.version>2.7.15</spring-boot-admin.version>
|
<spring-boot-admin.version>3.5.6</spring-boot-admin.version>
|
||||||
<opentracing.version>0.33.0</opentracing.version>
|
<opentracing.version>0.33.0</opentracing.version>
|
||||||
<!-- Test 测试相关 -->
|
<!-- Test 测试相关 -->
|
||||||
<podam.version>7.2.11.RELEASE</podam.version> <!-- Spring Boot 2.X 最多使用 7.2.11 版本 -->
|
<podam.version>8.0.2.RELEASE</podam.version>
|
||||||
<jedis-mock.version>1.1.12</jedis-mock.version>
|
<jedis-mock.version>1.1.12</jedis-mock.version>
|
||||||
<mockito-inline.version>4.11.0</mockito-inline.version>
|
<mockito-inline.version>5.2.0</mockito-inline.version>
|
||||||
<!-- Bpm 工作流相关 -->
|
<!-- Bpm 工作流相关 -->
|
||||||
<flowable.version>6.8.1</flowable.version>
|
<flowable.version>7.2.0</flowable.version>
|
||||||
<!-- 工具类相关 -->
|
<!-- 工具类相关 -->
|
||||||
<anji-plus-captcha.version>1.4.0</anji-plus-captcha.version>
|
<anji-plus-captcha.version>1.4.0</anji-plus-captcha.version>
|
||||||
<jsoup.version>1.22.2</jsoup.version>
|
<jsoup.version>1.21.2</jsoup.version>
|
||||||
<lombok.version>1.18.46</lombok.version>
|
<lombok.version>1.18.42</lombok.version>
|
||||||
<mapstruct.version>1.6.3</mapstruct.version>
|
<mapstruct.version>1.6.3</mapstruct.version>
|
||||||
<hutool-5.version>5.8.44</hutool-5.version>
|
<hutool-5.version>5.8.42</hutool-5.version>
|
||||||
|
<hutool-6.version>6.0.0-M22</hutool-6.version>
|
||||||
<fastexcel.version>1.3.0</fastexcel.version>
|
<fastexcel.version>1.3.0</fastexcel.version>
|
||||||
<velocity.version>2.4</velocity.version> <!-- JDK8 不能从 2.4 升级到 2.4.1,会报包不存在!!!! -->
|
<velocity.version>2.4.1</velocity.version>
|
||||||
<fastjson.version>1.2.83</fastjson.version>
|
<fastjson.version>1.2.83</fastjson.version>
|
||||||
<guava.version>33.6.0-jre</guava.version>
|
<guava.version>33.5.0-jre</guava.version>
|
||||||
<transmittable-thread-local.version>2.14.5</transmittable-thread-local.version>
|
<transmittable-thread-local.version>2.14.5</transmittable-thread-local.version>
|
||||||
<commons-net.version>3.13.0</commons-net.version>
|
<commons-net.version>3.12.0</commons-net.version>
|
||||||
<commons-lang3.version>3.20.0</commons-lang3.version>
|
<commons-lang3.version>3.20.0</commons-lang3.version>
|
||||||
<jsch.version>2.28.2</jsch.version>
|
<jsch.version>2.27.7</jsch.version>
|
||||||
<tika-core.version>2.9.3</tika-core.version> <!-- JDK8 不能从 2.9.3 升级到 3.X,会报 JDK8 不支持 -->
|
<tika-core.version>3.2.3</tika-core.version>
|
||||||
<ip2region.version>2.7.0</ip2region.version>
|
<ip2region.version>2.7.0</ip2region.version>
|
||||||
<bizlog-sdk.version>3.0.6</bizlog-sdk.version>
|
<bizlog-sdk.version>3.0.6</bizlog-sdk.version>
|
||||||
<reflections.version>0.10.2</reflections.version>
|
<reflections.version>0.10.2</reflections.version>
|
||||||
<netty.version>4.2.12.Final</netty.version>
|
<netty.version>4.2.9.Final</netty.version>
|
||||||
<mqtt.version>1.2.5</mqtt.version>
|
<mqtt.version>1.2.5</mqtt.version>
|
||||||
<vertx.version>4.5.26</vertx.version>
|
<vertx.version>4.5.22</vertx.version>
|
||||||
<okhttp.version>4.12.0</okhttp.version>
|
<okhttp.version>4.12.0</okhttp.version>
|
||||||
<californium.version>3.14.0</californium.version>
|
<californium.version>3.12.0</californium.version>
|
||||||
<j2mod.version>3.3.0</j2mod.version>
|
|
||||||
<httpclient5.version>5.5.2</httpclient5.version> <!-- WxJava 4.8.x 需要 HttpClient5 5.4+,Spring Boot 2.7 默认 5.1.4 不兼容 -->
|
|
||||||
<httpcore5.version>5.3.6</httpcore5.version> <!-- 配套 httpclient5 5.5.2,Spring Boot 2.7 默认 5.1.5 不兼容 -->
|
|
||||||
<!-- 三方云服务相关 -->
|
<!-- 三方云服务相关 -->
|
||||||
<awssdk.version>2.44.0</awssdk.version>
|
<awssdk.version>2.40.15</awssdk.version>
|
||||||
<justauth.version>1.16.7</justauth.version>
|
<justauth.version>1.16.7</justauth.version>
|
||||||
<justauth-starter.version>1.4.0</justauth-starter.version>
|
<justauth-starter.version>1.4.0</justauth-starter.version>
|
||||||
<jimureport.version>2.3.2</jimureport.version>
|
<jimureport.version>2.1.3</jimureport.version>
|
||||||
<jimubi.version>2.3.2</jimubi.version>
|
<jimubi.version>2.3.0</jimubi.version>
|
||||||
<weixin-java.version>4.8.2-20260501.180637</weixin-java.version>
|
<weixin-java.version>4.7.9-20251224.161447</weixin-java.version>
|
||||||
<alipay-sdk-java.version>4.40.771.ALL</alipay-sdk-java.version>
|
<alipay-sdk-java.version>4.40.607.ALL</alipay-sdk-java.version>
|
||||||
<!-- 专属于 JDK8 安全漏洞升级 -->
|
|
||||||
<logback.version>1.2.13</logback.version> <!-- 无法使用 1.3.X 版本,启动会报错 -->
|
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
|
|
@ -104,20 +97,6 @@
|
||||||
<type>pom</type>
|
<type>pom</type>
|
||||||
<scope>import</scope>
|
<scope>import</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework</groupId>
|
|
||||||
<artifactId>spring-framework-bom</artifactId> <!-- JDK8 版本独有:保证 Spring Framework 尽量高 -->
|
|
||||||
<version>${spring.framework.version}</version>
|
|
||||||
<type>pom</type>
|
|
||||||
<scope>import</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.springframework.security</groupId>
|
|
||||||
<artifactId>spring-security-bom</artifactId> <!-- JDK8 版本独有:保证 Spring Security 尽量高 -->
|
|
||||||
<version>${spring.security.version}</version>
|
|
||||||
<type>pom</type>
|
|
||||||
<scope>import</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
<artifactId>spring-boot-dependencies</artifactId>
|
<artifactId>spring-boot-dependencies</artifactId>
|
||||||
|
|
@ -202,14 +181,20 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springdoc</groupId> <!-- 接口文档 UI:默认 -->
|
<groupId>com.github.xiaoymin</groupId>
|
||||||
<artifactId>springdoc-openapi-ui</artifactId>
|
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
|
||||||
<version>${springdoc.version}</version>
|
<version>${knife4j.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.springdoc</groupId>
|
||||||
|
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.xiaoymin</groupId> <!-- 接口文档 UI:knife4j -->
|
<groupId>org.springdoc</groupId>
|
||||||
<artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
|
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||||
<version>${knife4j.version}</version>
|
<version>${springdoc.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.xiaoymin</groupId> <!-- 接口文档 UI:knife4j【网关专属】 -->
|
<groupId>com.github.xiaoymin</groupId> <!-- 接口文档 UI:knife4j【网关专属】 -->
|
||||||
|
|
@ -223,15 +208,10 @@
|
||||||
<artifactId>yudao-spring-boot-starter-mybatis</artifactId>
|
<artifactId>yudao-spring-boot-starter-mybatis</artifactId>
|
||||||
<version>${revision}</version>
|
<version>${revision}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.springdoc</groupId>
|
|
||||||
<artifactId>springdoc-openapi-webflux-ui</artifactId>
|
|
||||||
<version>${springdoc.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba</groupId>
|
<groupId>com.alibaba</groupId>
|
||||||
<artifactId>druid-spring-boot-starter</artifactId>
|
<artifactId>druid-spring-boot-3-starter</artifactId>
|
||||||
<version>${druid.version}</version>
|
<version>${druid.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
@ -242,12 +222,12 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.baomidou</groupId>
|
<groupId>com.baomidou</groupId>
|
||||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
||||||
<version>${mybatis-plus.version}</version>
|
<version>${mybatis-plus.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.baomidou</groupId>
|
<groupId>com.baomidou</groupId>
|
||||||
<artifactId>mybatis-plus-jsqlparser-4.9</artifactId>
|
<artifactId>mybatis-plus-jsqlparser</artifactId>
|
||||||
<version>${mybatis-plus.version}</version>
|
<version>${mybatis-plus.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
@ -257,7 +237,7 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.baomidou</groupId>
|
<groupId>com.baomidou</groupId>
|
||||||
<artifactId>dynamic-datasource-spring-boot-starter</artifactId> <!-- 多数据源 -->
|
<artifactId>dynamic-datasource-spring-boot3-starter</artifactId> <!-- 多数据源 -->
|
||||||
<version>${dynamic-datasource.version}</version>
|
<version>${dynamic-datasource.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
@ -266,12 +246,6 @@
|
||||||
<version>${mybatis-plus-join.version}</version>
|
<version>${mybatis-plus-join.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>cn.iocoder.cloud</groupId>
|
|
||||||
<artifactId>yudao-spring-boot-starter-redis</artifactId>
|
|
||||||
<version>${revision}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.fhs-opensource</groupId> <!-- VO 数据翻译 -->
|
<groupId>com.fhs-opensource</groupId> <!-- VO 数据翻译 -->
|
||||||
<artifactId>easy-trans-spring-boot-starter</artifactId>
|
<artifactId>easy-trans-spring-boot-starter</artifactId>
|
||||||
|
|
@ -299,24 +273,14 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.redisson</groupId>
|
<groupId>cn.iocoder.cloud</groupId>
|
||||||
<artifactId>redisson-spring-boot-starter</artifactId>
|
<artifactId>yudao-spring-boot-starter-redis</artifactId>
|
||||||
<version>${redisson.version}</version>
|
<version>${revision}</version>
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-actuator</artifactId>
|
|
||||||
</exclusion>
|
|
||||||
<exclusion>
|
|
||||||
<groupId>org.redisson</groupId>
|
|
||||||
<!-- 使用 redisson-spring-data-27 替代,解决 Tuple NoClassDefFoundError 报错 -->
|
|
||||||
<artifactId>redisson-spring-data-40</artifactId> <!-- Redisson 4.x 默认依赖 spring-data-40,排除后使用 spring-data-27 适配 Spring Boot 2.7 -->
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.redisson</groupId>
|
<groupId>org.redisson</groupId>
|
||||||
<artifactId>redisson-spring-data-27</artifactId>
|
<artifactId>redisson-spring-boot-starter</artifactId>
|
||||||
<version>${redisson.version}</version>
|
<version>${redisson.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
@ -353,6 +317,19 @@
|
||||||
|
|
||||||
<!-- Registry 注册中心相关 -->
|
<!-- Registry 注册中心相关 -->
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.cloud</groupId>
|
||||||
|
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
|
||||||
|
<version>${spring.cloud.alibaba.version}</version>
|
||||||
|
<exclusions>
|
||||||
|
<!-- 目的:解决 Nacos 启动的 NAMING_LOG_FILE 告警 -->
|
||||||
|
<exclusion>
|
||||||
|
<artifactId>logback-adapter</artifactId>
|
||||||
|
<groupId>com.alibaba.nacos</groupId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- Config 配置中心相关 -->
|
<!-- Config 配置中心相关 -->
|
||||||
|
|
||||||
<!-- Job 定时任务相关 -->
|
<!-- Job 定时任务相关 -->
|
||||||
|
|
@ -552,6 +529,11 @@
|
||||||
<artifactId>hutool-all</artifactId>
|
<artifactId>hutool-all</artifactId>
|
||||||
<version>${hutool-5.version}</version>
|
<version>${hutool-5.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.dromara.hutool</groupId>
|
||||||
|
<artifactId>hutool-extra</artifactId>
|
||||||
|
<version>${hutool-6.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.idev.excel</groupId>
|
<groupId>cn.idev.excel</groupId>
|
||||||
|
|
@ -674,30 +656,6 @@
|
||||||
<version>${californium.version}</version>
|
<version>${californium.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- Modbus 相关 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.ghgande</groupId>
|
|
||||||
<artifactId>j2mod</artifactId>
|
|
||||||
<version>${j2mod.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- WxJava 4.8.x 需要 HttpClient5 5.4+,覆盖 Spring Boot 2.7 默认的 5.1.4 -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.httpcomponents.client5</groupId>
|
|
||||||
<artifactId>httpclient5</artifactId>
|
|
||||||
<version>${httpclient5.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.httpcomponents.core5</groupId>
|
|
||||||
<artifactId>httpcore5</artifactId>
|
|
||||||
<version>${httpcore5.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.httpcomponents.core5</groupId>
|
|
||||||
<artifactId>httpcore5-h2</artifactId>
|
|
||||||
<version>${httpcore5.version}</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- 三方云服务相关 -->
|
<!-- 三方云服务相关 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>software.amazon.awssdk</groupId>
|
<groupId>software.amazon.awssdk</groupId>
|
||||||
|
|
@ -754,12 +712,12 @@
|
||||||
<!-- 积木报表-->
|
<!-- 积木报表-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jeecgframework.jimureport</groupId>
|
<groupId>org.jeecgframework.jimureport</groupId>
|
||||||
<artifactId>jimureport-spring-boot-starter</artifactId>
|
<artifactId>jimureport-spring-boot3-starter-fastjson2</artifactId>
|
||||||
<version>${jimureport.version}</version>
|
<version>${jimureport.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jeecgframework.jimureport</groupId>
|
<groupId>org.jeecgframework.jimureport</groupId>
|
||||||
<artifactId>jimubi-spring-boot-starter</artifactId>
|
<artifactId>jimubi-spring-boot3-starter</artifactId>
|
||||||
<version>${jimubi.version}</version>
|
<version>${jimubi.version}</version>
|
||||||
<exclusions>
|
<exclusions>
|
||||||
<exclusion>
|
<exclusion>
|
||||||
|
|
|
||||||
|
|
@ -60,8 +60,8 @@
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springdoc</groupId>
|
<groupId>org.springdoc</groupId>
|
||||||
<artifactId>springdoc-openapi-ui</artifactId>
|
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope> <!-- 设置为 provided,主要是 PageParam 使用到 -->
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- RPC 远程调用相关 -->
|
<!-- RPC 远程调用相关 -->
|
||||||
|
|
@ -140,11 +140,6 @@
|
||||||
<artifactId>transmittable-thread-local</artifactId>
|
<artifactId>transmittable-thread-local</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jsoup</groupId>
|
|
||||||
<artifactId>jsoup</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.fhs-opensource</groupId> <!-- VO 数据翻译 -->
|
<groupId>com.fhs-opensource</groupId> <!-- VO 数据翻译 -->
|
||||||
<artifactId>easy-trans-anno</artifactId> <!-- 默认引入的原因,方便 xxx-module-api 包使用 -->
|
<artifactId>easy-trans-anno</artifactId> <!-- 默认引入的原因,方便 xxx-module-api 包使用 -->
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,12 @@ import cn.iocoder.yudao.framework.common.enums.RpcConstants;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
import org.springframework.cloud.openfeign.FeignClient;
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
|
||||||
|
|
||||||
@FeignClient(name = RpcConstants.INFRA_NAME) // TODO 芋艿:fallbackFactory =
|
@FeignClient(name = RpcConstants.INFRA_NAME) // TODO 芋艿:fallbackFactory =
|
||||||
@Tag(name = "RPC 服务 - API 访问日志")
|
@Tag(name = "RPC 服务 - API 访问日志")
|
||||||
public interface ApiAccessLogCommonApi {
|
public interface ApiAccessLogCommonApi {
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,12 @@ import cn.iocoder.yudao.framework.common.enums.RpcConstants;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
import org.springframework.cloud.openfeign.FeignClient;
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
|
||||||
|
|
||||||
@FeignClient(name = RpcConstants.INFRA_NAME) // TODO 芋艿:fallbackFactory =
|
@FeignClient(name = RpcConstants.INFRA_NAME) // TODO 芋艿:fallbackFactory =
|
||||||
@Tag(name = "RPC 服务 - API 异常日志")
|
@Tag(name = "RPC 服务 - API 异常日志")
|
||||||
public interface ApiErrorLogCommonApi {
|
public interface ApiErrorLogCommonApi {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
package cn.iocoder.yudao.framework.common.biz.infra.logger.dto;
|
package cn.iocoder.yudao.framework.common.biz.infra.logger.dto;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
package cn.iocoder.yudao.framework.common.biz.infra.logger.dto;
|
package cn.iocoder.yudao.framework.common.biz.infra.logger.dto;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
@Schema(description = "RPC 服务 - API 错误日志创建 Request DTO")
|
@Schema(description = "RPC 服务 - API 错误日志创建 Request DTO")
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,12 @@ import cn.iocoder.yudao.framework.common.enums.RpcConstants;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
import org.springframework.cloud.openfeign.FeignClient;
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestBody;
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
|
||||||
|
|
||||||
@FeignClient(name = RpcConstants.SYSTEM_NAME, primary = false) // TODO 芋艿:fallbackFactory =
|
@FeignClient(name = RpcConstants.SYSTEM_NAME, primary = false) // TODO 芋艿:fallbackFactory =
|
||||||
@Tag(name = "RPC 服务 - 操作日志")
|
@Tag(name = "RPC 服务 - 操作日志")
|
||||||
public interface OperateLogCommonApi {
|
public interface OperateLogCommonApi {
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
package cn.iocoder.yudao.framework.common.biz.system.logger.dto;
|
package cn.iocoder.yudao.framework.common.biz.system.logger.dto;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import javax.validation.constraints.NotEmpty;
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
|
|
||||||
@Schema(name = "RPC 服务 - 系统操作日志 Create Request DTO")
|
@Schema(name = "RPC 服务 - 系统操作日志 Create Request DTO")
|
||||||
@Data
|
@Data
|
||||||
public class OperateLogCreateReqDTO {
|
public class OperateLogCreateReqDTO {
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ import io.swagger.v3.oas.annotations.Operation;
|
||||||
import org.springframework.cloud.openfeign.FeignClient;
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
|
|
||||||
@FeignClient(name = RpcConstants.SYSTEM_NAME) // TODO 芋艿:fallbackFactory =
|
@FeignClient(name = RpcConstants.SYSTEM_NAME) // TODO 芋艿:fallbackFactory =
|
||||||
@Tag(name = "RPC 服务 - OAuth2.0 令牌")
|
@Tag(name = "RPC 服务 - OAuth2.0 令牌")
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.common.validation.InEnum;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,9 @@ package cn.iocoder.yudao.framework.common.pojo;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import javax.validation.constraints.Min;
|
import jakarta.validation.constraints.Min;
|
||||||
import javax.validation.constraints.Max;
|
import jakarta.validation.constraints.Max;
|
||||||
import javax.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
@Schema(description="分页参数")
|
@Schema(description="分页参数")
|
||||||
|
|
|
||||||
|
|
@ -349,27 +349,4 @@ public class CollectionUtils {
|
||||||
return (LinkedHashSet<T>) toCollection(LinkedHashSet.class, elementType, value);
|
return (LinkedHashSet<T>) toCollection(LinkedHashSet.class, elementType, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean dfs(Long node, Map<Long, Set<Long>> graph) {
|
|
||||||
return dfs(node, graph, new HashSet<>(), new HashSet<>());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean dfs(Long node, Map<Long, Set<Long>> graph, Set<Long> visited, Set<Long> inStack) {
|
|
||||||
if (inStack.contains(node)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (visited.contains(node)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
visited.add(node);
|
|
||||||
inStack.add(node);
|
|
||||||
Set<Long> neighbors = graph.getOrDefault(node, Collections.emptySet());
|
|
||||||
for (Long neighbor : neighbors) {
|
|
||||||
if (dfs(neighbor, graph, visited, inStack)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
inStack.remove(node);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -302,21 +302,6 @@ public class LocalDateTimeUtils {
|
||||||
return timeRanges;
|
return timeRanges;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取从开始日期起的日期列表
|
|
||||||
*
|
|
||||||
* @param startDate 开始日期
|
|
||||||
* @param days 天数
|
|
||||||
* @return 日期列表,包含开始日期
|
|
||||||
*/
|
|
||||||
public static List<LocalDate> getDateList(LocalDate startDate, int days) {
|
|
||||||
List<LocalDate> dateList = new ArrayList<>(days);
|
|
||||||
for (int i = 0; i < days; i++) {
|
|
||||||
dateList.add(startDate.plusDays(i));
|
|
||||||
}
|
|
||||||
return dateList;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 格式化时间范围
|
* 格式化时间范围
|
||||||
*
|
*
|
||||||
|
|
@ -350,27 +335,6 @@ public class LocalDateTimeUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取指定日期所在季度的第一天
|
|
||||||
*
|
|
||||||
* @param date 日期
|
|
||||||
* @return 所在季度的第一天
|
|
||||||
*/
|
|
||||||
public static LocalDate getQuarterStart(LocalDate date) {
|
|
||||||
Month firstMonthOfQuarter = date.getMonth().firstMonthOfQuarter();
|
|
||||||
return LocalDate.of(date.getYear(), firstMonthOfQuarter, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取指定日期所在周的第一天(周一)
|
|
||||||
*
|
|
||||||
* @param date 日期
|
|
||||||
* @return 所在周的周一
|
|
||||||
*/
|
|
||||||
public static LocalDate getWeekStart(LocalDate date) {
|
|
||||||
return date.with(DayOfWeek.MONDAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将给定的 {@link LocalDateTime} 转换为自 Unix 纪元时间(1970-01-01T00:00:00Z)以来的秒数。
|
* 将给定的 {@link LocalDateTime} 转换为自 Unix 纪元时间(1970-01-01T00:00:00Z)以来的秒数。
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,17 @@
|
||||||
package cn.iocoder.yudao.framework.common.util.http;
|
package cn.iocoder.yudao.framework.common.util.http;
|
||||||
|
|
||||||
import cn.hutool.core.codec.Base64;
|
import cn.hutool.core.codec.Base64;
|
||||||
|
import cn.hutool.core.map.TableMap;
|
||||||
import cn.hutool.core.net.url.UrlBuilder;
|
import cn.hutool.core.net.url.UrlBuilder;
|
||||||
|
import cn.hutool.core.util.ReflectUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.http.HttpRequest;
|
import cn.hutool.http.HttpRequest;
|
||||||
import cn.hutool.http.HttpResponse;
|
import cn.hutool.http.HttpResponse;
|
||||||
import lombok.SneakyThrows;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
import org.springframework.web.util.UriComponents;
|
import org.springframework.web.util.UriComponents;
|
||||||
import org.springframework.web.util.UriComponentsBuilder;
|
import org.springframework.web.util.UriComponentsBuilder;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
|
|
@ -31,43 +32,28 @@ public class HttpUtils {
|
||||||
* @param value 参数
|
* @param value 参数
|
||||||
* @return 编码后的参数
|
* @return 编码后的参数
|
||||||
*/
|
*/
|
||||||
@SneakyThrows
|
|
||||||
public static String encodeUtf8(String value) {
|
public static String encodeUtf8(String value) {
|
||||||
return URLEncoder.encode(value, StandardCharsets.UTF_8.name());
|
return URLEncoder.encode(value, StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解码 URL 参数(query parameter)
|
* 解码 URL 参数
|
||||||
* 注意:此方法会将 + 解码为空格,适用于 query parameter,不适用于 URL path
|
|
||||||
*
|
*
|
||||||
* @see #decodeUrlPath(String)
|
|
||||||
* @param value 参数
|
* @param value 参数
|
||||||
* @return 解码后的参数
|
* @return 解码后的参数
|
||||||
*/
|
*/
|
||||||
@SneakyThrows
|
|
||||||
public static String decodeUtf8(String value) {
|
public static String decodeUtf8(String value) {
|
||||||
return URLDecoder.decode(value, StandardCharsets.UTF_8.name());
|
return URLDecoder.decode(value, StandardCharsets.UTF_8);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 解码 URL 路径
|
|
||||||
* 与 {@link #decodeUtf8(String)} 不同,此方法不会将 + 解码为空格,保持 + 为字面字符
|
|
||||||
* 适用于 URL path 部分的解码
|
|
||||||
*
|
|
||||||
* @param path URL 路径
|
|
||||||
* @return 解码后的路径
|
|
||||||
*/
|
|
||||||
@SneakyThrows
|
|
||||||
public static String decodeUrlPath(String path) {
|
|
||||||
// 先将 + 替换为 %2B,避免被 URLDecoder 解码为空格
|
|
||||||
String encoded = path.replace("+", "%2B");
|
|
||||||
return URLDecoder.decode(encoded, StandardCharsets.UTF_8.name());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public static String replaceUrlQuery(String url, String key, String value) {
|
public static String replaceUrlQuery(String url, String key, String value) {
|
||||||
UrlBuilder builder = UrlBuilder.of(url, Charset.defaultCharset());
|
UrlBuilder builder = UrlBuilder.of(url, Charset.defaultCharset());
|
||||||
// 先移除;再添加
|
// 先移除
|
||||||
builder.getQuery().remove(key);
|
TableMap<CharSequence, CharSequence> query = (TableMap<CharSequence, CharSequence>)
|
||||||
|
ReflectUtil.getFieldValue(builder.getQuery(), "query");
|
||||||
|
query.remove(key);
|
||||||
|
// 后添加
|
||||||
builder.addQuery(key, value);
|
builder.addQuery(key, value);
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -173,24 +173,6 @@ public class JsonUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 解析 JSON 字符串成指定类型的对象,如果解析失败,则返回 null
|
|
||||||
*
|
|
||||||
* @param text 字符串
|
|
||||||
* @param clazz 类型
|
|
||||||
* @return 指定类型的对象
|
|
||||||
*/
|
|
||||||
public static <T> T parseObjectQuietly(String text, Class<T> clazz) {
|
|
||||||
if (StrUtil.isEmpty(text)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return objectMapper.readValue(text, clazz);
|
|
||||||
} catch (IOException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> List<T> parseArray(String text, Class<T> clazz) {
|
public static <T> List<T> parseArray(String text, Class<T> clazz) {
|
||||||
if (StrUtil.isEmpty(text)) {
|
if (StrUtil.isEmpty(text)) {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
|
|
|
||||||
|
|
@ -60,11 +60,6 @@ public class ObjectUtils {
|
||||||
return Arrays.asList(array).contains(obj);
|
return Arrays.asList(array).contains(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SafeVarargs
|
|
||||||
public static <T> boolean notEqualsAny(T obj, T... array) {
|
|
||||||
return !Arrays.asList(array).contains(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isNotAllEmpty(Object... objs) {
|
public static boolean isNotAllEmpty(Object... objs) {
|
||||||
return !ObjectUtil.isAllEmpty(objs);
|
return !ObjectUtil.isAllEmpty(objs);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,16 @@
|
||||||
package cn.iocoder.yudao.framework.common.util.servlet;
|
package cn.iocoder.yudao.framework.common.util.servlet;
|
||||||
|
|
||||||
import cn.hutool.core.io.IoUtil;
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.extra.servlet.ServletUtil;
|
import cn.hutool.extra.servlet.JakartaServletUtil;
|
||||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||||
|
import jakarta.servlet.ServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.web.context.request.RequestAttributes;
|
import org.springframework.web.context.request.RequestAttributes;
|
||||||
import org.springframework.web.context.request.RequestContextHolder;
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
|
|
||||||
import javax.servlet.ServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URLEncoder;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -32,22 +29,7 @@ public class ServletUtils {
|
||||||
@SuppressWarnings("deprecation") // 必须使用 APPLICATION_JSON_UTF8_VALUE,否则会乱码
|
@SuppressWarnings("deprecation") // 必须使用 APPLICATION_JSON_UTF8_VALUE,否则会乱码
|
||||||
public static void writeJSON(HttpServletResponse response, Object object) {
|
public static void writeJSON(HttpServletResponse response, Object object) {
|
||||||
String content = JsonUtils.toJsonString(object);
|
String content = JsonUtils.toJsonString(object);
|
||||||
ServletUtil.write(response, content, MediaType.APPLICATION_JSON_UTF8_VALUE);
|
JakartaServletUtil.write(response, content, MediaType.APPLICATION_JSON_UTF8_VALUE);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 返回附件
|
|
||||||
*
|
|
||||||
* @param response 响应
|
|
||||||
* @param filename 文件名
|
|
||||||
* @param content 附件内容
|
|
||||||
*/
|
|
||||||
public static void writeAttachment(HttpServletResponse response, String filename, byte[] content) throws IOException {
|
|
||||||
// 设置 header 和 contentType
|
|
||||||
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
|
|
||||||
response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
|
|
||||||
// 输出附件
|
|
||||||
IoUtil.write(response.getOutputStream(), false, content);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -85,7 +67,7 @@ public class ServletUtils {
|
||||||
if (request == null) {
|
if (request == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return ServletUtil.getClientIP(request);
|
return JakartaServletUtil.getClientIP(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isJsonRequest(ServletRequest request) {
|
public static boolean isJsonRequest(ServletRequest request) {
|
||||||
|
|
@ -95,7 +77,7 @@ public class ServletUtils {
|
||||||
public static String getBody(HttpServletRequest request) {
|
public static String getBody(HttpServletRequest request) {
|
||||||
// 只有在 json 请求在读取,因为只有 CacheRequestBodyFilter 才会进行缓存,支持重复读取
|
// 只有在 json 请求在读取,因为只有 CacheRequestBodyFilter 才会进行缓存,支持重复读取
|
||||||
if (isJsonRequest(request)) {
|
if (isJsonRequest(request)) {
|
||||||
return ServletUtil.getBody(request);
|
return JakartaServletUtil.getBody(request);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -103,21 +85,21 @@ public class ServletUtils {
|
||||||
public static byte[] getBodyBytes(HttpServletRequest request) {
|
public static byte[] getBodyBytes(HttpServletRequest request) {
|
||||||
// 只有在 json 请求在读取,因为只有 CacheRequestBodyFilter 才会进行缓存,支持重复读取
|
// 只有在 json 请求在读取,因为只有 CacheRequestBodyFilter 才会进行缓存,支持重复读取
|
||||||
if (isJsonRequest(request)) {
|
if (isJsonRequest(request)) {
|
||||||
return ServletUtil.getBodyBytes(request);
|
return JakartaServletUtil.getBodyBytes(request);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getClientIP(HttpServletRequest request) {
|
public static String getClientIP(HttpServletRequest request) {
|
||||||
return ServletUtil.getClientIP(request);
|
return JakartaServletUtil.getClientIP(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map<String, String> getParamMap(HttpServletRequest request) {
|
public static Map<String, String> getParamMap(HttpServletRequest request) {
|
||||||
return ServletUtil.getParamMap(request);
|
return JakartaServletUtil.getParamMap(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map<String, String> getHeaderMap(HttpServletRequest request) {
|
public static Map<String, String> getHeaderMap(HttpServletRequest request) {
|
||||||
return ServletUtil.getHeaderMap(request);
|
return JakartaServletUtil.getHeaderMap(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,10 @@ import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import javax.validation.ConstraintViolation;
|
import jakarta.validation.ConstraintViolation;
|
||||||
import javax.validation.ConstraintViolationException;
|
import jakarta.validation.ConstraintViolationException;
|
||||||
import javax.validation.Validation;
|
import jakarta.validation.Validation;
|
||||||
import javax.validation.Validator;
|
import jakarta.validation.Validator;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
package cn.iocoder.yudao.framework.common.validation;
|
package cn.iocoder.yudao.framework.common.validation;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
||||||
|
import jakarta.validation.Constraint;
|
||||||
|
import jakarta.validation.Payload;
|
||||||
|
|
||||||
import javax.validation.Constraint;
|
|
||||||
import javax.validation.Payload;
|
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
@Target({
|
@Target({
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@ package cn.iocoder.yudao.framework.common.validation;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
||||||
|
import jakarta.validation.ConstraintValidator;
|
||||||
|
import jakarta.validation.ConstraintValidatorContext;
|
||||||
|
|
||||||
import javax.validation.ConstraintValidator;
|
|
||||||
import javax.validation.ConstraintValidatorContext;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
package cn.iocoder.yudao.framework.common.validation;
|
package cn.iocoder.yudao.framework.common.validation;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
import cn.iocoder.yudao.framework.common.core.ArrayValuable;
|
||||||
|
import jakarta.validation.ConstraintValidator;
|
||||||
|
import jakarta.validation.ConstraintValidatorContext;
|
||||||
|
|
||||||
import javax.validation.ConstraintValidator;
|
|
||||||
import javax.validation.ConstraintValidatorContext;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package cn.iocoder.yudao.framework.common.validation;
|
package cn.iocoder.yudao.framework.common.validation;
|
||||||
|
|
||||||
import javax.validation.Constraint;
|
import jakarta.validation.Constraint;
|
||||||
import javax.validation.Payload;
|
import jakarta.validation.Payload;
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
@Target({
|
@Target({
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ package cn.iocoder.yudao.framework.common.validation;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
|
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
|
||||||
|
|
||||||
import javax.validation.ConstraintValidator;
|
import jakarta.validation.ConstraintValidator;
|
||||||
import javax.validation.ConstraintValidatorContext;
|
import jakarta.validation.ConstraintValidatorContext;
|
||||||
|
|
||||||
public class MobileValidator implements ConstraintValidator<Mobile, String> {
|
public class MobileValidator implements ConstraintValidator<Mobile, String> {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package cn.iocoder.yudao.framework.common.validation;
|
package cn.iocoder.yudao.framework.common.validation;
|
||||||
|
|
||||||
import javax.validation.Constraint;
|
import jakarta.validation.Constraint;
|
||||||
import javax.validation.Payload;
|
import jakarta.validation.Payload;
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
@Target({
|
@Target({
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ package cn.iocoder.yudao.framework.common.validation;
|
||||||
import cn.hutool.core.text.CharSequenceUtil;
|
import cn.hutool.core.text.CharSequenceUtil;
|
||||||
import cn.hutool.core.util.PhoneUtil;
|
import cn.hutool.core.util.PhoneUtil;
|
||||||
|
|
||||||
import javax.validation.ConstraintValidator;
|
import jakarta.validation.ConstraintValidator;
|
||||||
import javax.validation.ConstraintValidatorContext;
|
import jakarta.validation.ConstraintValidatorContext;
|
||||||
|
|
||||||
public class TelephoneValidator implements ConstraintValidator<Telephone, String> {
|
public class TelephoneValidator implements ConstraintValidator<Telephone, String> {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
package cn.iocoder.yudao.framework.common.util.http;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link HttpUtils} 的单元测试
|
|
||||||
*/
|
|
||||||
public class HttpUtilsTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testReplaceUrlQuery_replace() {
|
|
||||||
// 准备参数
|
|
||||||
String url = "https://www.iocoder.cn/path?a=1&b=2";
|
|
||||||
// 调用
|
|
||||||
String result = HttpUtils.replaceUrlQuery(url, "a", "3");
|
|
||||||
// 断言:被替换的 key 会移到末尾,原顺序的其它参数保留
|
|
||||||
assertEquals("https://www.iocoder.cn/path?b=2&a=3", result);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testReplaceUrlQuery_add() {
|
|
||||||
// 准备参数
|
|
||||||
String url = "https://www.iocoder.cn/path?a=1";
|
|
||||||
// 调用
|
|
||||||
String result = HttpUtils.replaceUrlQuery(url, "b", "2");
|
|
||||||
// 断言
|
|
||||||
assertEquals("https://www.iocoder.cn/path?a=1&b=2", result);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testReplaceUrlQuery_noQuery() {
|
|
||||||
// 准备参数:原 URL 没有 query
|
|
||||||
String url = "https://www.iocoder.cn/path";
|
|
||||||
// 调用
|
|
||||||
String result = HttpUtils.replaceUrlQuery(url, "a", "1");
|
|
||||||
// 断言
|
|
||||||
assertEquals("https://www.iocoder.cn/path?a=1", result);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testReplaceUrlQuery_emptyValue() {
|
|
||||||
// 准备参数:value 为空字符串
|
|
||||||
String url = "https://www.iocoder.cn/path?a=1";
|
|
||||||
// 调用
|
|
||||||
String result = HttpUtils.replaceUrlQuery(url, "a", "");
|
|
||||||
// 断言:保留 key,value 为空
|
|
||||||
assertEquals("https://www.iocoder.cn/path?a=", result);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -2,12 +2,12 @@ package cn.iocoder.yudao.framework.datapermission.core.rpc;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.datapermission.core.aop.DataPermissionContextHolder;
|
import cn.iocoder.yudao.framework.datapermission.core.aop.DataPermissionContextHolder;
|
||||||
import cn.iocoder.yudao.framework.datapermission.core.util.DataPermissionUtils;
|
import cn.iocoder.yudao.framework.datapermission.core.util.DataPermissionUtils;
|
||||||
|
import jakarta.servlet.FilterChain;
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
import javax.servlet.FilterChain;
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||||
import cn.iocoder.yudao.framework.ip.core.Area;
|
import cn.iocoder.yudao.framework.ip.core.Area;
|
||||||
import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum;
|
import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.experimental.UtilityClass;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -26,46 +25,44 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.
|
||||||
* @author 芋道源码
|
* @author 芋道源码
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@UtilityClass
|
|
||||||
public class AreaUtils {
|
public class AreaUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化 SEARCHER
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("InstantiationOfUtilityClass")
|
||||||
|
private final static AreaUtils INSTANCE = new AreaUtils();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Area 内存缓存,提升访问速度
|
* Area 内存缓存,提升访问速度
|
||||||
*/
|
*/
|
||||||
private static Map<Integer, Area> areas;
|
private static Map<Integer, Area> areas;
|
||||||
|
|
||||||
static {
|
private AreaUtils() {
|
||||||
init();
|
long now = System.currentTimeMillis();
|
||||||
}
|
areas = new HashMap<>();
|
||||||
|
areas.put(Area.ID_GLOBAL, new Area(Area.ID_GLOBAL, "全球", 0,
|
||||||
/**
|
null, new ArrayList<>()));
|
||||||
* 初始化
|
// 从 csv 中加载数据
|
||||||
*/
|
List<CsvRow> rows = CsvUtil.getReader().read(ResourceUtil.getUtf8Reader("area.csv")).getRows();
|
||||||
private static void init() {
|
rows.remove(0); // 删除 header
|
||||||
try {
|
for (CsvRow row : rows) {
|
||||||
long now = System.currentTimeMillis();
|
// 创建 Area 对象
|
||||||
areas = new HashMap<>();
|
Area area = new Area(Integer.valueOf(row.get(0)), row.get(1), Integer.valueOf(row.get(2)),
|
||||||
areas.put(Area.ID_GLOBAL, new Area(Area.ID_GLOBAL, "全球", 0, null, new ArrayList<>()));
|
null, new ArrayList<>());
|
||||||
// 从 csv 中加载数据
|
// 添加到 areas 中
|
||||||
List<CsvRow> rows = CsvUtil.getReader().read(ResourceUtil.getUtf8Reader("area.csv")).getRows();
|
areas.put(area.getId(), area);
|
||||||
rows.remove(0); // 删除 header
|
|
||||||
for (CsvRow row : rows) {
|
|
||||||
Area area = new Area(Integer.valueOf(row.get(0)), row.get(1), Integer.valueOf(row.get(2)), null, new ArrayList<>());
|
|
||||||
areas.put(area.getId(), area);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建父子关系:因为 Area 中没有 parentId 字段,所以需要重复读取
|
|
||||||
for (CsvRow row : rows) {
|
|
||||||
Area area = areas.get(Integer.valueOf(row.get(0))); // 自己
|
|
||||||
Area parent = areas.get(Integer.valueOf(row.get(3))); // 父
|
|
||||||
Assert.isTrue(area != parent, "{}:父子节点相同", area.getName());
|
|
||||||
area.setParent(parent);
|
|
||||||
parent.getChildren().add(area);
|
|
||||||
}
|
|
||||||
log.info("启动加载 AreaUtils 成功,耗时 ({}) 毫秒", System.currentTimeMillis() - now);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException("AreaUtils 初始化失败", e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 构建父子关系:因为 Area 中没有 parentId 字段,所以需要重复读取
|
||||||
|
for (CsvRow row : rows) {
|
||||||
|
Area area = areas.get(Integer.valueOf(row.get(0))); // 自己
|
||||||
|
Area parent = areas.get(Integer.valueOf(row.get(3))); // 父
|
||||||
|
Assert.isTrue(area != parent, "{}:父子节点相同", area.getName());
|
||||||
|
area.setParent(parent);
|
||||||
|
parent.getChildren().add(area);
|
||||||
|
}
|
||||||
|
log.info("启动加载 AreaUtils 成功,耗时 ({}) 毫秒", System.currentTimeMillis() - now);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,11 @@ package cn.iocoder.yudao.framework.ip.core.utils;
|
||||||
import cn.hutool.core.io.resource.ResourceUtil;
|
import cn.hutool.core.io.resource.ResourceUtil;
|
||||||
import cn.iocoder.yudao.framework.ip.core.Area;
|
import cn.iocoder.yudao.framework.ip.core.Area;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import lombok.experimental.UtilityClass;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.lionsoul.ip2region.xdb.Searcher;
|
import org.lionsoul.ip2region.xdb.Searcher;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IP 工具类
|
* IP 工具类
|
||||||
*
|
*
|
||||||
|
|
@ -15,29 +16,30 @@ import org.lionsoul.ip2region.xdb.Searcher;
|
||||||
* @author wanglhup
|
* @author wanglhup
|
||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@UtilityClass
|
|
||||||
public class IPUtils {
|
public class IPUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化 SEARCHER
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("InstantiationOfUtilityClass")
|
||||||
|
private final static IPUtils INSTANCE = new IPUtils();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* IP 查询器,启动加载到内存中
|
* IP 查询器,启动加载到内存中
|
||||||
*/
|
*/
|
||||||
private static Searcher SEARCHER;
|
private static Searcher SEARCHER;
|
||||||
|
|
||||||
static {
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化
|
* 私有化构造
|
||||||
*/
|
*/
|
||||||
private static void init() {
|
private IPUtils() {
|
||||||
try {
|
try {
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
byte[] bytes = ResourceUtil.readBytes("ip2region.xdb");
|
byte[] bytes = ResourceUtil.readBytes("ip2region.xdb");
|
||||||
SEARCHER = Searcher.newWithBuffer(bytes);
|
SEARCHER = Searcher.newWithBuffer(bytes);
|
||||||
log.info("启动加载 IPUtils 成功,耗时 ({}) 毫秒", System.currentTimeMillis() - now);
|
log.info("启动加载 IPUtils 成功,耗时 ({}) 毫秒", System.currentTimeMillis() - now);
|
||||||
} catch (Exception e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException("IPUtils 初始化失败", e);
|
log.error("启动加载 IPUtils 失败", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,7 @@ import cn.iocoder.yudao.framework.ip.core.Area;
|
||||||
import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum;
|
import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link AreaUtils} 的单元测试
|
* {@link AreaUtils} 的单元测试
|
||||||
|
|
@ -36,46 +31,6 @@ public class AreaUtilsTest {
|
||||||
assertEquals(AreaUtils.format(110105), "北京市 北京市 朝阳区");
|
assertEquals(AreaUtils.format(110105), "北京市 北京市 朝阳区");
|
||||||
assertEquals(AreaUtils.format(1), "中国");
|
assertEquals(AreaUtils.format(1), "中国");
|
||||||
assertEquals(AreaUtils.format(2), "蒙古");
|
assertEquals(AreaUtils.format(2), "蒙古");
|
||||||
// 中国台湾省:省/市/区三级
|
|
||||||
assertEquals(AreaUtils.format(710101), "台湾省 台北市 中正区");
|
|
||||||
// 自定义分隔符
|
|
||||||
assertEquals(AreaUtils.format(110105, "/"), "北京市/北京市/朝阳区");
|
|
||||||
// 不存在的编号
|
|
||||||
assertNull(AreaUtils.format(-1));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testParseArea() {
|
|
||||||
// 调用:通过路径解析得到地区
|
|
||||||
Area area = AreaUtils.parseArea("北京市/北京市/朝阳区");
|
|
||||||
// 断言
|
|
||||||
assertNotNull(area);
|
|
||||||
assertEquals(area.getId(), 110105);
|
|
||||||
// 路径不存在时返回 null
|
|
||||||
assertNull(AreaUtils.parseArea("不存在/路径"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetParentIdByType() {
|
|
||||||
// 调用:朝阳区向上找省
|
|
||||||
Integer provinceId = AreaUtils.getParentIdByType(110105, AreaTypeEnum.PROVINCE);
|
|
||||||
// 断言
|
|
||||||
assertEquals(provinceId, 110000);
|
|
||||||
// 自身就是目标类型
|
|
||||||
assertEquals(AreaUtils.getParentIdByType(110000, AreaTypeEnum.PROVINCE), 110000);
|
|
||||||
// 不存在的编号返回 null
|
|
||||||
assertNull(AreaUtils.getParentIdByType(-1, AreaTypeEnum.PROVINCE));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testGetByType() {
|
|
||||||
// 调用:获取所有省份
|
|
||||||
List<Area> provinces = AreaUtils.getByType(AreaTypeEnum.PROVINCE, area -> area);
|
|
||||||
// 断言:包含北京、台湾、香港、澳门
|
|
||||||
assertTrue(provinces.stream().anyMatch(area -> "北京市".equals(area.getName())));
|
|
||||||
assertTrue(provinces.stream().anyMatch(area -> "台湾省".equals(area.getName())));
|
|
||||||
assertTrue(provinces.stream().anyMatch(area -> "香港特别行政区".equals(area.getName())));
|
|
||||||
assertTrue(provinces.stream().anyMatch(area -> "澳门特别行政区".equals(area.getName())));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import cn.iocoder.yudao.framework.web.config.WebProperties;
|
||||||
import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
|
import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
|
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
|
@ -45,7 +46,6 @@ import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
|
||||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||||
import org.springframework.web.util.pattern.PathPattern;
|
import org.springframework.web.util.pattern.PathPattern;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,13 @@ import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService;
|
||||||
import cn.iocoder.yudao.framework.web.config.WebProperties;
|
import cn.iocoder.yudao.framework.web.config.WebProperties;
|
||||||
import cn.iocoder.yudao.framework.web.core.filter.ApiRequestFilter;
|
import cn.iocoder.yudao.framework.web.core.filter.ApiRequestFilter;
|
||||||
import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
|
import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
|
||||||
|
import jakarta.servlet.FilterChain;
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.util.AntPathMatcher;
|
import org.springframework.util.AntPathMatcher;
|
||||||
|
|
||||||
import javax.servlet.FilterChain;
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,10 @@ import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
||||||
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
import javax.servlet.FilterChain;
|
import jakarta.servlet.FilterChain;
|
||||||
import javax.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -8,13 +8,12 @@ import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
||||||
import cn.iocoder.yudao.framework.tenant.config.TenantProperties;
|
import cn.iocoder.yudao.framework.tenant.config.TenantProperties;
|
||||||
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
||||||
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.servlet.HandlerInterceptor;
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2021 the original author or authors.
|
* Copyright 2002-2023 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -16,6 +16,11 @@
|
||||||
|
|
||||||
package org.springframework.messaging.handler.invocation;
|
package org.springframework.messaging.handler.invocation;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
||||||
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
|
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
|
||||||
import org.springframework.core.DefaultParameterNameDiscoverer;
|
import org.springframework.core.DefaultParameterNameDiscoverer;
|
||||||
|
|
@ -27,11 +32,6 @@ import org.springframework.messaging.Message;
|
||||||
import org.springframework.messaging.handler.HandlerMethod;
|
import org.springframework.messaging.handler.HandlerMethod;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
|
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -50,10 +50,12 @@ public class InvocableHandlerMethod extends HandlerMethod {
|
||||||
|
|
||||||
private static final Object[] EMPTY_ARGS = new Object[0];
|
private static final Object[] EMPTY_ARGS = new Object[0];
|
||||||
|
|
||||||
|
|
||||||
private HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite();
|
private HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite();
|
||||||
|
|
||||||
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
|
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance from a {@code HandlerMethod}.
|
* Create an instance from a {@code HandlerMethod}.
|
||||||
*/
|
*/
|
||||||
|
|
@ -81,6 +83,7 @@ public class InvocableHandlerMethod extends HandlerMethod {
|
||||||
super(bean, methodName, parameterTypes);
|
super(bean, methodName, parameterTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set {@link HandlerMethodArgumentResolver HandlerMethodArgumentResolvers} to use for resolving method argument values.
|
* Set {@link HandlerMethodArgumentResolver HandlerMethodArgumentResolvers} to use for resolving method argument values.
|
||||||
*/
|
*/
|
||||||
|
|
@ -91,12 +94,13 @@ public class InvocableHandlerMethod extends HandlerMethod {
|
||||||
/**
|
/**
|
||||||
* Set the ParameterNameDiscoverer for resolving parameter names when needed
|
* Set the ParameterNameDiscoverer for resolving parameter names when needed
|
||||||
* (e.g. default request attribute name).
|
* (e.g. default request attribute name).
|
||||||
* <p>Default is a {@link DefaultParameterNameDiscoverer}.
|
* <p>Default is a {@link org.springframework.core.DefaultParameterNameDiscoverer}.
|
||||||
*/
|
*/
|
||||||
public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) {
|
public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) {
|
||||||
this.parameterNameDiscoverer = parameterNameDiscoverer;
|
this.parameterNameDiscoverer = parameterNameDiscoverer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoke the method after resolving its argument values in the context of the given message.
|
* Invoke the method after resolving its argument values in the context of the given message.
|
||||||
* <p>Argument values are commonly resolved through
|
* <p>Argument values are commonly resolved through
|
||||||
|
|
@ -200,20 +204,21 @@ public class InvocableHandlerMethod extends HandlerMethod {
|
||||||
}
|
}
|
||||||
catch (IllegalArgumentException ex) {
|
catch (IllegalArgumentException ex) {
|
||||||
assertTargetBean(getBridgedMethod(), getBean(), args);
|
assertTargetBean(getBridgedMethod(), getBean(), args);
|
||||||
String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument");
|
String text = (ex.getMessage() == null || ex.getCause() instanceof NullPointerException) ?
|
||||||
|
"Illegal argument": ex.getMessage();
|
||||||
throw new IllegalStateException(formatInvokeError(text, args), ex);
|
throw new IllegalStateException(formatInvokeError(text, args), ex);
|
||||||
}
|
}
|
||||||
catch (InvocationTargetException ex) {
|
catch (InvocationTargetException ex) {
|
||||||
// Unwrap for HandlerExceptionResolvers ...
|
// Unwrap for HandlerExceptionResolvers ...
|
||||||
Throwable targetException = ex.getTargetException();
|
Throwable targetException = ex.getTargetException();
|
||||||
if (targetException instanceof RuntimeException) {
|
if (targetException instanceof RuntimeException runtimeException) {
|
||||||
throw (RuntimeException) targetException;
|
throw runtimeException;
|
||||||
}
|
}
|
||||||
else if (targetException instanceof Error) {
|
else if (targetException instanceof Error error) {
|
||||||
throw (Error) targetException;
|
throw error;
|
||||||
}
|
}
|
||||||
else if (targetException instanceof Exception) {
|
else if (targetException instanceof Exception exception) {
|
||||||
throw (Exception) targetException;
|
throw exception;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new IllegalStateException(formatInvokeError("Invocation failure", args), targetException);
|
throw new IllegalStateException(formatInvokeError("Invocation failure", args), targetException);
|
||||||
|
|
@ -225,7 +230,8 @@ public class InvocableHandlerMethod extends HandlerMethod {
|
||||||
return new AsyncResultMethodParameter(returnValue);
|
return new AsyncResultMethodParameter(returnValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class AsyncResultMethodParameter extends HandlerMethodParameter {
|
|
||||||
|
private class AsyncResultMethodParameter extends AnnotatedMethodParameter {
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private final Object returnValue;
|
private final Object returnValue;
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import lombok.SneakyThrows;
|
||||||
import org.springframework.cloud.client.ServiceInstance;
|
import org.springframework.cloud.client.ServiceInstance;
|
||||||
import org.springframework.core.env.Environment;
|
import org.springframework.core.env.Environment;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,14 +5,14 @@ import cn.iocoder.yudao.framework.env.core.context.EnvContextHolder;
|
||||||
import cn.iocoder.yudao.framework.env.core.util.EnvUtils;
|
import cn.iocoder.yudao.framework.env.core.util.EnvUtils;
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
import javax.servlet.FilterChain;
|
import jakarta.servlet.FilterChain;
|
||||||
import javax.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 环境的 {@link javax.servlet.Filter} 实现类
|
* 环境的 {@link jakarta.servlet.Filter} 实现类
|
||||||
* 当有 tag 请求头时,设置到 {@link EnvContextHolder} 的标签上下文
|
* 当有 tag 请求头时,设置到 {@link EnvContextHolder} 的标签上下文
|
||||||
*
|
*
|
||||||
* @author 芋道源码
|
* @author 芋道源码
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
package cn.iocoder.yudao.framework.dict.validation;
|
package cn.iocoder.yudao.framework.dict.validation;
|
||||||
|
|
||||||
import javax.validation.Constraint;
|
import jakarta.validation.Constraint;
|
||||||
import javax.validation.Payload;
|
import jakarta.validation.Payload;
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
@Target({
|
@Target({
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@ package cn.iocoder.yudao.framework.dict.validation;
|
||||||
|
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
|
import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
|
||||||
|
import jakarta.validation.ConstraintValidator;
|
||||||
|
import jakarta.validation.ConstraintValidatorContext;
|
||||||
|
|
||||||
import javax.validation.ConstraintValidator;
|
|
||||||
import javax.validation.ConstraintValidatorContext;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,9 +2,9 @@ package cn.iocoder.yudao.framework.dict.validation;
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
|
import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
|
||||||
|
import jakarta.validation.ConstraintValidator;
|
||||||
|
import jakarta.validation.ConstraintValidatorContext;
|
||||||
|
|
||||||
import javax.validation.ConstraintValidator;
|
|
||||||
import javax.validation.ConstraintValidatorContext;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class InDictValidator implements ConstraintValidator<InDict, Object> {
|
public class InDictValidator implements ConstraintValidator<InDict, Object> {
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@ import cn.idev.excel.converters.longconverter.LongStringConverter;
|
||||||
import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
|
import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
|
||||||
import cn.iocoder.yudao.framework.excel.core.handler.ColumnWidthMatchStyleStrategy;
|
import cn.iocoder.yudao.framework.excel.core.handler.ColumnWidthMatchStyleStrategy;
|
||||||
import cn.iocoder.yudao.framework.excel.core.handler.SelectSheetWriteHandler;
|
import cn.iocoder.yudao.framework.excel.core.handler.SelectSheetWriteHandler;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package cn.iocoder.yudao.framework.dict.core.util;
|
package cn.iocoder.yudao.framework.dict.core.util;
|
||||||
|
|
||||||
import cn.hutool.core.collection.ListUtil;
|
|
||||||
import cn.iocoder.yudao.framework.common.biz.system.dict.DictDataCommonApi;
|
import cn.iocoder.yudao.framework.common.biz.system.dict.DictDataCommonApi;
|
||||||
import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
|
import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
|
||||||
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
|
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
|
||||||
|
|
@ -34,7 +33,7 @@ public class DictFrameworkUtilsTest extends BaseMockitoUnitTest {
|
||||||
@Test
|
@Test
|
||||||
public void testParseDictDataLabel() {
|
public void testParseDictDataLabel() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
List<DictDataRespDTO> dictDatas = ListUtil.of(
|
List<DictDataRespDTO> dictDatas = List.of(
|
||||||
randomPojo(DictDataRespDTO.class, o -> o.setDictType("animal").setValue("cat").setLabel("猫")),
|
randomPojo(DictDataRespDTO.class, o -> o.setDictType("animal").setValue("cat").setLabel("猫")),
|
||||||
randomPojo(DictDataRespDTO.class, o -> o.setDictType("animal").setValue("dog").setLabel("狗"))
|
randomPojo(DictDataRespDTO.class, o -> o.setDictType("animal").setValue("dog").setLabel("狗"))
|
||||||
);
|
);
|
||||||
|
|
@ -48,7 +47,7 @@ public class DictFrameworkUtilsTest extends BaseMockitoUnitTest {
|
||||||
@Test
|
@Test
|
||||||
public void testParseDictDataValue() {
|
public void testParseDictDataValue() {
|
||||||
// mock 数据
|
// mock 数据
|
||||||
List<DictDataRespDTO> dictDatas = ListUtil.of(
|
List<DictDataRespDTO> dictDatas = List.of(
|
||||||
randomPojo(DictDataRespDTO.class, o -> o.setDictType("animal").setValue("cat").setLabel("猫")),
|
randomPojo(DictDataRespDTO.class, o -> o.setDictType("animal").setValue("cat").setLabel("猫")),
|
||||||
randomPojo(DictDataRespDTO.class, o -> o.setDictType("animal").setValue("dog").setLabel("狗"))
|
randomPojo(DictDataRespDTO.class, o -> o.setDictType("animal").setValue("dog").setLabel("狗"))
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,9 @@ import lombok.Data;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import javax.validation.constraints.NotEmpty;
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
import javax.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* XXL-Job 配置类
|
* XXL-Job 配置类
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ import org.springframework.context.annotation.Bean;
|
||||||
@ConditionalOnClass(name = {
|
@ConditionalOnClass(name = {
|
||||||
"org.apache.skywalking.apm.toolkit.opentracing.SkywalkingTracer", // 来自 apm-toolkit-opentracing.jar
|
"org.apache.skywalking.apm.toolkit.opentracing.SkywalkingTracer", // 来自 apm-toolkit-opentracing.jar
|
||||||
// "io.opentracing.Tracer", // 来自 opentracing-api.jar
|
// "io.opentracing.Tracer", // 来自 opentracing-api.jar
|
||||||
"javax.servlet.Filter"
|
"jakarta.servlet.Filter"
|
||||||
})
|
})
|
||||||
@EnableConfigurationProperties(TracerProperties.class)
|
@EnableConfigurationProperties(TracerProperties.class)
|
||||||
@ConditionalOnProperty(prefix = "yudao.tracer", value = "enable", matchIfMissing = true)
|
@ConditionalOnProperty(prefix = "yudao.tracer", value = "enable", matchIfMissing = true)
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,10 @@ package cn.iocoder.yudao.framework.tracer.core.filter;
|
||||||
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
|
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
import javax.servlet.FilterChain;
|
import jakarta.servlet.FilterChain;
|
||||||
import javax.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -66,19 +66,25 @@
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.alibaba</groupId>
|
<groupId>com.alibaba</groupId>
|
||||||
<artifactId>druid-spring-boot-starter</artifactId>
|
<artifactId>druid-spring-boot-3-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.baomidou</groupId>
|
<groupId>com.baomidou</groupId>
|
||||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.baomidou</groupId>
|
<groupId>com.baomidou</groupId>
|
||||||
<artifactId>mybatis-plus-jsqlparser-4.9</artifactId>
|
<artifactId>mybatis-plus-jsqlparser</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.baomidou</groupId>
|
<groupId>com.baomidou</groupId>
|
||||||
<artifactId>dynamic-datasource-spring-boot-starter</artifactId> <!-- 多数据源 -->
|
<artifactId>dynamic-datasource-spring-boot3-starter</artifactId> <!-- 多数据源 -->
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-undertow</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package cn.iocoder.yudao.framework.datasource.config;
|
package cn.iocoder.yudao.framework.datasource.config;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.datasource.core.filter.DruidAdRemoveFilter;
|
import cn.iocoder.yudao.framework.datasource.core.filter.DruidAdRemoveFilter;
|
||||||
import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
|
import com.alibaba.druid.spring.boot3.autoconfigure.properties.DruidStatProperties;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,10 @@ package cn.iocoder.yudao.framework.datasource.core.filter;
|
||||||
import com.alibaba.druid.util.Utils;
|
import com.alibaba.druid.util.Utils;
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
import javax.servlet.FilterChain;
|
import jakarta.servlet.FilterChain;
|
||||||
import javax.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -119,31 +119,6 @@ public interface BaseMapperX<T> extends MPJBaseMapper<T> {
|
||||||
return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2).eq(field3, value3));
|
return selectOne(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2).eq(field3, value3));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得满足条件的一条记录,并使用 FOR UPDATE 锁定。
|
|
||||||
*
|
|
||||||
* 注意:需要在事务中调用,否则锁会立即释放。
|
|
||||||
*
|
|
||||||
* @param queryWrapper 查询条件
|
|
||||||
* @return 实体
|
|
||||||
*/
|
|
||||||
default T selectOneForUpdate(LambdaQueryWrapper<T> queryWrapper) {
|
|
||||||
return selectOne(queryWrapper.last("FOR UPDATE"));
|
|
||||||
}
|
|
||||||
|
|
||||||
default T selectOneForUpdate(SFunction<T, ?> field, Object value) {
|
|
||||||
return selectOneForUpdate(new LambdaQueryWrapper<T>().eq(field, value));
|
|
||||||
}
|
|
||||||
|
|
||||||
default T selectOneForUpdate(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2) {
|
|
||||||
return selectOneForUpdate(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2));
|
|
||||||
}
|
|
||||||
|
|
||||||
default T selectOneForUpdate(SFunction<T, ?> field1, Object value1, SFunction<T, ?> field2, Object value2,
|
|
||||||
SFunction<T, ?> field3, Object value3) {
|
|
||||||
return selectOneForUpdate(new LambdaQueryWrapper<T>().eq(field1, value1).eq(field2, value2).eq(field3, value3));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取满足条件的第 1 条记录
|
* 获取满足条件的第 1 条记录
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -54,14 +54,14 @@ public class MyBatisUtils {
|
||||||
if (CollUtil.isEmpty(sortingFields)) {
|
if (CollUtil.isEmpty(sortingFields)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (wrapper instanceof QueryWrapper) {
|
if (wrapper instanceof QueryWrapper<T>) {
|
||||||
QueryWrapper<T> query = (QueryWrapper<T>) wrapper;
|
QueryWrapper<T> query = (QueryWrapper<T>) wrapper;
|
||||||
for (SortingField sortingField : sortingFields) {
|
for (SortingField sortingField : sortingFields) {
|
||||||
query.orderBy(true,
|
query.orderBy(true,
|
||||||
SortingField.ORDER_ASC.equals(sortingField.getOrder()),
|
SortingField.ORDER_ASC.equals(sortingField.getOrder()),
|
||||||
StrUtil.toUnderlineCase(sortingField.getField()));
|
StrUtil.toUnderlineCase(sortingField.getField()));
|
||||||
}
|
}
|
||||||
} else if (wrapper instanceof LambdaQueryWrapper) {
|
} else if (wrapper instanceof LambdaQueryWrapper<T>) {
|
||||||
// LambdaQueryWrapper 不直接支持字符串字段排序,使用 last 方法拼接 ORDER BY
|
// LambdaQueryWrapper 不直接支持字符串字段排序,使用 last 方法拼接 ORDER BY
|
||||||
LambdaQueryWrapper<T> lambdaQuery = (LambdaQueryWrapper<T>) wrapper;
|
LambdaQueryWrapper<T> lambdaQuery = (LambdaQueryWrapper<T>) wrapper;
|
||||||
StringBuilder orderBy = new StringBuilder();
|
StringBuilder orderBy = new StringBuilder();
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.idempotent.core.annotation.Idempotent;
|
||||||
import cn.iocoder.yudao.framework.idempotent.core.keyresolver.IdempotentKeyResolver;
|
import cn.iocoder.yudao.framework.idempotent.core.keyresolver.IdempotentKeyResolver;
|
||||||
import org.aspectj.lang.JoinPoint;
|
import org.aspectj.lang.JoinPoint;
|
||||||
import org.aspectj.lang.reflect.MethodSignature;
|
import org.aspectj.lang.reflect.MethodSignature;
|
||||||
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
|
import org.springframework.core.DefaultParameterNameDiscoverer;
|
||||||
import org.springframework.core.ParameterNameDiscoverer;
|
import org.springframework.core.ParameterNameDiscoverer;
|
||||||
import org.springframework.expression.Expression;
|
import org.springframework.expression.Expression;
|
||||||
import org.springframework.expression.ExpressionParser;
|
import org.springframework.expression.ExpressionParser;
|
||||||
|
|
@ -21,7 +21,8 @@ import java.lang.reflect.Method;
|
||||||
*/
|
*/
|
||||||
public class ExpressionIdempotentKeyResolver implements IdempotentKeyResolver {
|
public class ExpressionIdempotentKeyResolver implements IdempotentKeyResolver {
|
||||||
|
|
||||||
private final ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
|
private final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
|
||||||
|
|
||||||
private final ExpressionParser expressionParser = new SpelExpressionParser();
|
private final ExpressionParser expressionParser = new SpelExpressionParser();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -11,13 +11,13 @@ import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstant
|
||||||
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
||||||
import cn.iocoder.yudao.framework.signature.core.annotation.ApiSignature;
|
import cn.iocoder.yudao.framework.signature.core.annotation.ApiSignature;
|
||||||
import cn.iocoder.yudao.framework.signature.core.redis.ApiSignatureRedisDAO;
|
import cn.iocoder.yudao.framework.signature.core.redis.ApiSignatureRedisDAO;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.aspectj.lang.JoinPoint;
|
import org.aspectj.lang.JoinPoint;
|
||||||
import org.aspectj.lang.annotation.Aspect;
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
import org.aspectj.lang.annotation.Before;
|
import org.aspectj.lang.annotation.Before;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.SortedMap;
|
import java.util.SortedMap;
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,13 @@ import cn.hutool.crypto.digest.DigestUtil;
|
||||||
import cn.iocoder.yudao.framework.signature.core.annotation.ApiSignature;
|
import cn.iocoder.yudao.framework.signature.core.annotation.ApiSignature;
|
||||||
import cn.iocoder.yudao.framework.signature.core.aop.ApiSignatureAspect;
|
import cn.iocoder.yudao.framework.signature.core.aop.ApiSignatureAspect;
|
||||||
import cn.iocoder.yudao.framework.signature.core.redis.ApiSignatureRedisDAO;
|
import cn.iocoder.yudao.framework.signature.core.redis.ApiSignatureRedisDAO;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.jupiter.api.extension.ExtendWith;
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
import org.mockito.InjectMocks;
|
import org.mockito.InjectMocks;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.junit.jupiter.MockitoExtension;
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
|
|
|
||||||
|
|
@ -26,10 +26,6 @@
|
||||||
<groupId>org.redisson</groupId>
|
<groupId>org.redisson</groupId>
|
||||||
<artifactId>redisson-spring-boot-starter</artifactId>
|
<artifactId>redisson-spring-boot-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.redisson</groupId>
|
|
||||||
<artifactId>redisson-spring-data-27</artifactId>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package cn.iocoder.yudao.framework.redis.config;
|
||||||
import cn.hutool.core.util.ReflectUtil;
|
import cn.hutool.core.util.ReflectUtil;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||||
import org.redisson.spring.starter.RedissonAutoConfiguration;
|
import org.redisson.spring.starter.RedissonAutoConfigurationV2;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||||
|
|
@ -13,7 +13,7 @@ import org.springframework.data.redis.serializer.RedisSerializer;
|
||||||
/**
|
/**
|
||||||
* Redis 配置类
|
* Redis 配置类
|
||||||
*/
|
*/
|
||||||
@AutoConfiguration(before = RedissonAutoConfiguration.class) // 目的:使用自己定义的 RedisTemplate Bean
|
@AutoConfiguration(before = RedissonAutoConfigurationV2.class) // 目的:使用自己定义的 RedisTemplate Bean
|
||||||
public class YudaoRedisAutoConfiguration {
|
public class YudaoRedisAutoConfiguration {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -36,17 +36,6 @@
|
||||||
<groupId>io.github.openfeign</groupId>
|
<groupId>io.github.openfeign</groupId>
|
||||||
<artifactId>feign-okhttp</artifactId>
|
<artifactId>feign-okhttp</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!--
|
|
||||||
TODO 芋艿:WxJava 4.8.x 的 AbstractWxMpConfigStorageConfiguration 仍引用了 HttpClient 4.x 的
|
|
||||||
org.apache.http.ssl.TrustStrategy 类。升级 Spring Cloud Alibaba 到 2025.0.0.0 后,Nacos 不再
|
|
||||||
传递 HttpClient 4.x(httpcore),导致 ClassNotFoundException。
|
|
||||||
临时解决:显式引入 httpclient 4.x。待 WxJava 修复后移除。
|
|
||||||
-->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.httpcomponents</groupId>
|
|
||||||
<artifactId>httpclient</artifactId>
|
|
||||||
<version>4.5.14</version>
|
|
||||||
</dependency>
|
|
||||||
|
|
||||||
<!-- 工具相关 -->
|
<!-- 工具相关 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
||||||
|
|
@ -8,11 +8,11 @@ import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
||||||
import cn.iocoder.yudao.framework.common.biz.system.logger.dto.OperateLogCreateReqDTO;
|
import cn.iocoder.yudao.framework.common.biz.system.logger.dto.OperateLogCreateReqDTO;
|
||||||
import com.mzt.logapi.beans.LogRecord;
|
import com.mzt.logapi.beans.LogRecord;
|
||||||
import com.mzt.logapi.service.ILogRecordService;
|
import com.mzt.logapi.service.ILogRecordService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Qualifier;
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
package cn.iocoder.yudao.framework.security.config;
|
package cn.iocoder.yudao.framework.security.config;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.web.config.WebProperties;
|
import cn.iocoder.yudao.framework.web.config.WebProperties;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.core.Ordered;
|
||||||
import org.springframework.security.config.Customizer;
|
import org.springframework.security.config.Customizer;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer;
|
import org.springframework.security.config.annotation.web.configurers.AuthorizeHttpRequestsConfigurer;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自定义的 URL 的安全配置
|
* 自定义的 URL 的安全配置
|
||||||
* 目的:每个 Maven Module 可以自定义规则!
|
* 目的:每个 Maven Module 可以自定义规则!
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,8 @@ import lombok.Data;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
import javax.validation.constraints.NotEmpty;
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
import javax.validation.constraints.NotNull;
|
import jakarta.validation.constraints.NotNull;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package cn.iocoder.yudao.framework.security.config;
|
package cn.iocoder.yudao.framework.security.config;
|
||||||
|
|
||||||
import cn.iocoder.yudao.framework.common.biz.system.oauth2.OAuth2TokenCommonApi;
|
|
||||||
import cn.iocoder.yudao.framework.common.biz.system.permission.PermissionCommonApi;
|
import cn.iocoder.yudao.framework.common.biz.system.permission.PermissionCommonApi;
|
||||||
import cn.iocoder.yudao.framework.security.core.context.TransmittableThreadLocalSecurityContextHolderStrategy;
|
import cn.iocoder.yudao.framework.security.core.context.TransmittableThreadLocalSecurityContextHolderStrategy;
|
||||||
import cn.iocoder.yudao.framework.security.core.filter.TokenAuthenticationFilter;
|
import cn.iocoder.yudao.framework.security.core.filter.TokenAuthenticationFilter;
|
||||||
|
|
@ -9,6 +8,8 @@ import cn.iocoder.yudao.framework.security.core.handler.AuthenticationEntryPoint
|
||||||
import cn.iocoder.yudao.framework.security.core.service.SecurityFrameworkService;
|
import cn.iocoder.yudao.framework.security.core.service.SecurityFrameworkService;
|
||||||
import cn.iocoder.yudao.framework.security.core.service.SecurityFrameworkServiceImpl;
|
import cn.iocoder.yudao.framework.security.core.service.SecurityFrameworkServiceImpl;
|
||||||
import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
|
import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
|
||||||
|
import cn.iocoder.yudao.framework.common.biz.system.oauth2.OAuth2TokenCommonApi;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
|
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
||||||
|
|
@ -20,8 +21,6 @@ import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||||
import org.springframework.security.web.access.AccessDeniedHandler;
|
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Spring Security 自动配置类,主要用于相关组件的配置
|
* Spring Security 自动配置类,主要用于相关组件的配置
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,9 @@ import cn.iocoder.yudao.framework.security.core.filter.TokenAuthenticationFilter
|
||||||
import cn.iocoder.yudao.framework.web.config.WebProperties;
|
import cn.iocoder.yudao.framework.web.config.WebProperties;
|
||||||
import com.google.common.collect.HashMultimap;
|
import com.google.common.collect.HashMultimap;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.annotation.security.PermitAll;
|
||||||
|
import jakarta.servlet.DispatcherType;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
|
|
@ -28,9 +31,6 @@ import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
|
||||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||||
import org.springframework.web.util.pattern.PathPattern;
|
import org.springframework.web.util.pattern.PathPattern;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
|
||||||
import javax.annotation.security.PermitAll;
|
|
||||||
import javax.servlet.DispatcherType;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,6 @@ package cn.iocoder.yudao.framework.security.core.filter;
|
||||||
|
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.yudao.framework.common.biz.system.oauth2.OAuth2TokenCommonApi;
|
|
||||||
import cn.iocoder.yudao.framework.common.biz.system.oauth2.dto.OAuth2AccessTokenCheckRespDTO;
|
|
||||||
import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
import cn.iocoder.yudao.framework.common.exception.ServiceException;
|
||||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||||
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
|
||||||
|
|
@ -13,16 +11,17 @@ import cn.iocoder.yudao.framework.security.core.LoginUser;
|
||||||
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
||||||
import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
|
import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
|
||||||
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
||||||
|
import cn.iocoder.yudao.framework.common.biz.system.oauth2.OAuth2TokenCommonApi;
|
||||||
|
import cn.iocoder.yudao.framework.common.biz.system.oauth2.dto.OAuth2AccessTokenCheckRespDTO;
|
||||||
|
import jakarta.servlet.FilterChain;
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.security.access.AccessDeniedException;
|
import org.springframework.security.access.AccessDeniedException;
|
||||||
import org.springframework.web.filter.OncePerRequestFilter;
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
import javax.servlet.FilterChain;
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
@ -129,14 +128,13 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
|
||||||
.setTenantId(WebFrameworkUtils.getTenantId(request));
|
.setTenantId(WebFrameworkUtils.getTenantId(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
private LoginUser buildLoginUserByHeader(HttpServletRequest request) {
|
private LoginUser buildLoginUserByHeader(HttpServletRequest request) {
|
||||||
String loginUserStr = request.getHeader(SecurityFrameworkUtils.LOGIN_USER_HEADER);
|
String loginUserStr = request.getHeader(SecurityFrameworkUtils.LOGIN_USER_HEADER);
|
||||||
if (StrUtil.isEmpty(loginUserStr)) {
|
if (StrUtil.isEmpty(loginUserStr)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
loginUserStr = URLDecoder.decode(loginUserStr, StandardCharsets.UTF_8.name()); // 解码,解决中文乱码问题
|
loginUserStr = URLDecoder.decode(loginUserStr, StandardCharsets.UTF_8); // 解码,解决中文乱码问题
|
||||||
LoginUser loginUser = JsonUtils.parseObject(loginUserStr, LoginUser.class);
|
LoginUser loginUser = JsonUtils.parseObject(loginUserStr, LoginUser.class);
|
||||||
// 用户类型不匹配,无权限
|
// 用户类型不匹配,无权限
|
||||||
// 注意:只有 /admin-api/* 和 /app-api/* 有 userType,才需要比对用户类型
|
// 注意:只有 /admin-api/* 和 /app-api/* 有 userType,才需要比对用户类型
|
||||||
|
|
|
||||||
|
|
@ -8,16 +8,14 @@ import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.security.access.AccessDeniedException;
|
import org.springframework.security.access.AccessDeniedException;
|
||||||
import org.springframework.security.web.access.AccessDeniedHandler;
|
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||||
import org.springframework.security.web.access.ExceptionTranslationFilter;
|
import org.springframework.security.web.access.ExceptionTranslationFilter;
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
import javax.servlet.FilterChain;
|
import jakarta.servlet.FilterChain;
|
||||||
import javax.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.FORBIDDEN;
|
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.FORBIDDEN;
|
||||||
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.UNAUTHORIZED;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 访问一个需要认证的 URL 资源,已经认证(登录)但是没有权限的情况下,返回 {@link GlobalErrorCodeConstants#FORBIDDEN} 错误码。
|
* 访问一个需要认证的 URL 资源,已经认证(登录)但是没有权限的情况下,返回 {@link GlobalErrorCodeConstants#FORBIDDEN} 错误码。
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,9 @@ import org.springframework.security.core.AuthenticationException;
|
||||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||||
import org.springframework.security.web.access.ExceptionTranslationFilter;
|
import org.springframework.security.web.access.ExceptionTranslationFilter;
|
||||||
|
|
||||||
import javax.servlet.FilterChain;
|
import jakarta.servlet.FilterChain;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.UNAUTHORIZED;
|
import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.UNAUTHORIZED;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import cn.iocoder.yudao.framework.security.core.LoginUser;
|
||||||
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
|
||||||
import feign.RequestInterceptor;
|
import feign.RequestInterceptor;
|
||||||
import feign.RequestTemplate;
|
import feign.RequestTemplate;
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
|
|
@ -20,7 +19,6 @@ import java.nio.charset.StandardCharsets;
|
||||||
public class LoginUserRequestInterceptor implements RequestInterceptor {
|
public class LoginUserRequestInterceptor implements RequestInterceptor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SneakyThrows
|
|
||||||
public void apply(RequestTemplate requestTemplate) {
|
public void apply(RequestTemplate requestTemplate) {
|
||||||
LoginUser user = SecurityFrameworkUtils.getLoginUser();
|
LoginUser user = SecurityFrameworkUtils.getLoginUser();
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
|
|
@ -28,7 +26,7 @@ public class LoginUserRequestInterceptor implements RequestInterceptor {
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
String userStr = JsonUtils.toJsonString(user);
|
String userStr = JsonUtils.toJsonString(user);
|
||||||
userStr = URLEncoder.encode(userStr, StandardCharsets.UTF_8.name()); // 编码,避免中文乱码
|
userStr = URLEncoder.encode(userStr, StandardCharsets.UTF_8); // 编码,避免中文乱码
|
||||||
requestTemplate.header(SecurityFrameworkUtils.LOGIN_USER_HEADER, userStr);
|
requestTemplate.header(SecurityFrameworkUtils.LOGIN_USER_HEADER, userStr);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
log.error("[apply][序列化 LoginUser({}) 发生异常]", user, ex);
|
log.error("[apply][序列化 LoginUser({}) 发生异常]", user, ex);
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration;
|
||||||
import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
|
import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
|
||||||
import cn.iocoder.yudao.framework.test.config.RedisTestConfiguration;
|
import cn.iocoder.yudao.framework.test.config.RedisTestConfiguration;
|
||||||
import cn.iocoder.yudao.framework.test.config.SqlInitializationTestConfiguration;
|
import cn.iocoder.yudao.framework.test.config.SqlInitializationTestConfiguration;
|
||||||
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
|
import com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceAutoConfigure;
|
||||||
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
|
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
|
||||||
import org.redisson.spring.starter.RedissonAutoConfiguration;
|
import org.redisson.spring.starter.RedissonAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
|
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import cn.hutool.extra.spring.SpringUtil;
|
||||||
import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration;
|
import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration;
|
||||||
import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration;
|
import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration;
|
||||||
import cn.iocoder.yudao.framework.test.config.SqlInitializationTestConfiguration;
|
import cn.iocoder.yudao.framework.test.config.SqlInitializationTestConfiguration;
|
||||||
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
|
import com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceAutoConfigure;
|
||||||
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
|
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
|
||||||
import com.github.yulichang.autoconfigure.MybatisPlusJoinAutoConfiguration;
|
import com.github.yulichang.autoconfigure.MybatisPlusJoinAutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import uk.co.jemos.podam.api.PodamFactory;
|
||||||
import uk.co.jemos.podam.api.PodamFactoryImpl;
|
import uk.co.jemos.podam.api.PodamFactoryImpl;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
@ -53,10 +52,6 @@ public class RandomUtils {
|
||||||
}
|
}
|
||||||
return RandomUtil.randomInt();
|
return RandomUtil.randomInt();
|
||||||
});
|
});
|
||||||
// BigDecimal:限制精度在 DECIMAL(10,2) 范围内,避免 H2 等数据库溢出
|
|
||||||
PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(BigDecimal.class,
|
|
||||||
(dataProviderStrategy, attributeMetadata, map) ->
|
|
||||||
BigDecimal.valueOf(RandomUtil.randomInt(0, 10000000), 2));
|
|
||||||
// LocalDateTime
|
// LocalDateTime
|
||||||
PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(LocalDateTime.class,
|
PODAM_FACTORY.getStrategy().addOrReplaceTypeManufacturer(LocalDateTime.class,
|
||||||
(dataProviderStrategy, attributeMetadata, map) -> randomLocalDateTime());
|
(dataProviderStrategy, attributeMetadata, map) -> randomLocalDateTime());
|
||||||
|
|
|
||||||
|
|
@ -46,12 +46,12 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.github.xiaoymin</groupId> <!-- 接口文档 -->
|
<groupId>com.github.xiaoymin</groupId>
|
||||||
<artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
|
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springdoc</groupId> <!-- 接口文档 -->
|
<groupId>org.springdoc</groupId>
|
||||||
<artifactId>springdoc-openapi-ui</artifactId>
|
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- RPC 远程调用相关 -->
|
<!-- RPC 远程调用相关 -->
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.biz.infra.logger.ApiAccessLogCommonApi;
|
||||||
import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
|
import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
|
||||||
import cn.iocoder.yudao.framework.web.config.WebProperties;
|
import cn.iocoder.yudao.framework.web.config.WebProperties;
|
||||||
import cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration;
|
import cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration;
|
||||||
|
import jakarta.servlet.Filter;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
|
@ -14,8 +15,6 @@ import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
import javax.servlet.Filter;
|
|
||||||
|
|
||||||
@AutoConfiguration(after = YudaoWebAutoConfiguration.class)
|
@AutoConfiguration(after = YudaoWebAutoConfiguration.class)
|
||||||
public class YudaoApiLogAutoConfiguration implements WebMvcConfigurer {
|
public class YudaoApiLogAutoConfiguration implements WebMvcConfigurer {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,14 +22,14 @@ import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.servlet.FilterChain;
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
import org.springframework.web.method.HandlerMethod;
|
import org.springframework.web.method.HandlerMethod;
|
||||||
|
|
||||||
import javax.servlet.FilterChain;
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.time.temporal.ChronoUnit;
|
import java.time.temporal.ChronoUnit;
|
||||||
|
|
@ -162,8 +162,7 @@ public class ApiAccessLogFilter extends ApiRequestFilter {
|
||||||
// ========== 解析 @ApiAccessLog、@Swagger 注解 ==========
|
// ========== 解析 @ApiAccessLog、@Swagger 注解 ==========
|
||||||
|
|
||||||
private static OperateTypeEnum parseOperateLogType(HttpServletRequest request) {
|
private static OperateTypeEnum parseOperateLogType(HttpServletRequest request) {
|
||||||
RequestMethod requestMethod = ArrayUtil.firstMatch(method ->
|
RequestMethod requestMethod = RequestMethod.resolve(request.getMethod());
|
||||||
StrUtil.equalsAnyIgnoreCase(method.name(), request.getMethod()), RequestMethod.values());
|
|
||||||
if (requestMethod == null) {
|
if (requestMethod == null) {
|
||||||
return OperateTypeEnum.OTHER;
|
return OperateTypeEnum.OTHER;
|
||||||
}
|
}
|
||||||
|
|
@ -238,7 +237,7 @@ public class ApiAccessLogFilter extends ApiRequestFilter {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 情况三:Object,遍历处理
|
// 情况三:Object,遍历处理
|
||||||
Iterator<Map.Entry<String, JsonNode>> iterator = node.fields();
|
Iterator<Map.Entry<String, JsonNode>> iterator = node.properties().iterator();
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
Map.Entry<String, JsonNode> entry = iterator.next();
|
Map.Entry<String, JsonNode> entry = iterator.next();
|
||||||
if (ArrayUtil.contains(sanitizeKeys, entry.getKey())
|
if (ArrayUtil.contains(sanitizeKeys, entry.getKey())
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,13 @@ import cn.hutool.core.io.resource.ResourceUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
|
||||||
import cn.iocoder.yudao.framework.common.util.spring.SpringUtils;
|
import cn.iocoder.yudao.framework.common.util.spring.SpringUtils;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.util.StopWatch;
|
import org.springframework.util.StopWatch;
|
||||||
import org.springframework.web.method.HandlerMethod;
|
import org.springframework.web.method.HandlerMethod;
|
||||||
import org.springframework.web.servlet.HandlerInterceptor;
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
|
||||||
|
|
@ -37,14 +37,8 @@ public class BannerApplicationRunner implements ApplicationRunner {
|
||||||
System.out.println("[商城系统 yudao-module-mall 教程][参考 https://cloud.iocoder.cn/mall/build/ 开启]");
|
System.out.println("[商城系统 yudao-module-mall 教程][参考 https://cloud.iocoder.cn/mall/build/ 开启]");
|
||||||
// ERP 系统
|
// ERP 系统
|
||||||
System.out.println("[ERP 系统 yudao-module-erp - 教程][参考 https://cloud.iocoder.cn/erp/build/ 开启]");
|
System.out.println("[ERP 系统 yudao-module-erp - 教程][参考 https://cloud.iocoder.cn/erp/build/ 开启]");
|
||||||
// WMS 仓库管理系统
|
|
||||||
System.out.println("[WMS 仓库管理系统 yudao-module-wms - 教程][参考 https://cloud.iocoder.cn/wms/build/ 开启]");
|
|
||||||
// CRM 系统
|
// CRM 系统
|
||||||
System.out.println("[CRM 系统 yudao-module-crm - 教程][参考 https://cloud.iocoder.cn/crm/build/ 开启]");
|
System.out.println("[CRM 系统 yudao-module-crm - 教程][参考 https://cloud.iocoder.cn/crm/build/ 开启]");
|
||||||
// MES 系统
|
|
||||||
System.out.println("[MES 系统 yudao-module-mes - 教程][参考 https://cloud.iocoder.cn/mes/build/ 开启]");
|
|
||||||
// IM 即时通讯
|
|
||||||
System.out.println("[IM 即时通讯 yudao-module-im - 教程][参考 https://cloud.iocoder.cn/im/build/ 开启]");
|
|
||||||
// 微信公众号
|
// 微信公众号
|
||||||
System.out.println("[微信公众号 yudao-module-mp 教程][参考 https://cloud.iocoder.cn/mp/build/ 开启]");
|
System.out.println("[微信公众号 yudao-module-mp 教程][参考 https://cloud.iocoder.cn/mp/build/ 开启]");
|
||||||
// 支付平台
|
// 支付平台
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package cn.iocoder.yudao.framework.desensitize.core.slider.handler;
|
package cn.iocoder.yudao.framework.desensitize.core.slider.handler;
|
||||||
|
|
||||||
import cn.hutool.core.util.StrUtil;
|
|
||||||
import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils;
|
import cn.iocoder.yudao.framework.common.util.spring.SpringExpressionUtils;
|
||||||
import cn.iocoder.yudao.framework.desensitize.core.base.handler.DesensitizationHandler;
|
import cn.iocoder.yudao.framework.desensitize.core.base.handler.DesensitizationHandler;
|
||||||
|
|
||||||
|
|
@ -48,7 +47,7 @@ public abstract class AbstractSliderDesensitizationHandler<T extends Annotation>
|
||||||
* @return 构建后的替换符
|
* @return 构建后的替换符
|
||||||
*/
|
*/
|
||||||
private String buildReplacerByLength(String replacer, int length) {
|
private String buildReplacerByLength(String replacer, int length) {
|
||||||
return StrUtil.repeat(replacer, length);
|
return replacer.repeat(length);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
package cn.iocoder.yudao.framework.encrypt.config;
|
package cn.iocoder.yudao.framework.encrypt.config;
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
import org.springframework.validation.annotation.Validated;
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
import javax.validation.constraints.NotEmpty;
|
|
||||||
import javax.validation.constraints.NotNull;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTTP API 加解密配置
|
* HTTP API 加解密配置
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,11 @@ import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.crypto.asymmetric.AsymmetricDecryptor;
|
import cn.hutool.crypto.asymmetric.AsymmetricDecryptor;
|
||||||
import cn.hutool.crypto.asymmetric.KeyType;
|
import cn.hutool.crypto.asymmetric.KeyType;
|
||||||
import cn.hutool.crypto.symmetric.SymmetricDecryptor;
|
import cn.hutool.crypto.symmetric.SymmetricDecryptor;
|
||||||
|
import jakarta.servlet.ReadListener;
|
||||||
|
import jakarta.servlet.ServletInputStream;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletRequestWrapper;
|
||||||
|
|
||||||
import javax.servlet.ReadListener;
|
|
||||||
import javax.servlet.ServletInputStream;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletRequestWrapper;
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,10 @@ import cn.iocoder.yudao.framework.encrypt.core.annotation.ApiEncrypt;
|
||||||
import cn.iocoder.yudao.framework.web.config.WebProperties;
|
import cn.iocoder.yudao.framework.web.config.WebProperties;
|
||||||
import cn.iocoder.yudao.framework.web.core.filter.ApiRequestFilter;
|
import cn.iocoder.yudao.framework.web.core.filter.ApiRequestFilter;
|
||||||
import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
|
import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
|
||||||
|
import jakarta.servlet.FilterChain;
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.web.method.HandlerMethod;
|
import org.springframework.web.method.HandlerMethod;
|
||||||
|
|
@ -21,10 +25,6 @@ import org.springframework.web.servlet.HandlerExecutionChain;
|
||||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
|
||||||
import org.springframework.web.util.ServletRequestPathUtils;
|
import org.springframework.web.util.ServletRequestPathUtils;
|
||||||
|
|
||||||
import javax.servlet.FilterChain;
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.invalidParamException;
|
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.invalidParamException;
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@ import cn.hutool.crypto.asymmetric.AsymmetricEncryptor;
|
||||||
import cn.hutool.crypto.asymmetric.KeyType;
|
import cn.hutool.crypto.asymmetric.KeyType;
|
||||||
import cn.hutool.crypto.symmetric.SymmetricEncryptor;
|
import cn.hutool.crypto.symmetric.SymmetricEncryptor;
|
||||||
import cn.iocoder.yudao.framework.encrypt.config.ApiEncryptProperties;
|
import cn.iocoder.yudao.framework.encrypt.config.ApiEncryptProperties;
|
||||||
|
import jakarta.servlet.ServletOutputStream;
|
||||||
|
import jakarta.servlet.WriteListener;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import jakarta.servlet.http.HttpServletResponseWrapper;
|
||||||
|
|
||||||
import javax.servlet.ServletOutputStream;
|
|
||||||
import javax.servlet.WriteListener;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import javax.servlet.http.HttpServletResponseWrapper;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import io.swagger.v3.oas.models.OpenAPI;
|
import io.swagger.v3.oas.models.OpenAPI;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import org.springdoc.core.SpringDocConfigProperties;
|
|
||||||
import org.springdoc.core.customizers.GlobalOpenApiCustomizer;
|
import org.springdoc.core.customizers.GlobalOpenApiCustomizer;
|
||||||
|
import org.springdoc.core.properties.SpringDocConfigProperties;
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ package cn.iocoder.yudao.framework.swagger.config;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
import javax.validation.constraints.NotEmpty;
|
import jakarta.validation.constraints.NotEmpty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Swagger 配置属性
|
* Swagger 配置属性
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,15 @@ import io.swagger.v3.oas.models.media.StringSchema;
|
||||||
import io.swagger.v3.oas.models.parameters.Parameter;
|
import io.swagger.v3.oas.models.parameters.Parameter;
|
||||||
import io.swagger.v3.oas.models.security.SecurityRequirement;
|
import io.swagger.v3.oas.models.security.SecurityRequirement;
|
||||||
import io.swagger.v3.oas.models.security.SecurityScheme;
|
import io.swagger.v3.oas.models.security.SecurityScheme;
|
||||||
import org.springdoc.core.*;
|
|
||||||
import org.springdoc.core.customizers.OpenApiBuilderCustomizer;
|
import org.springdoc.core.customizers.OpenApiBuilderCustomizer;
|
||||||
import org.springdoc.core.customizers.OperationCustomizer;
|
import org.springdoc.core.customizers.OperationCustomizer;
|
||||||
import org.springdoc.core.customizers.ServerBaseUrlCustomizer;
|
import org.springdoc.core.customizers.ServerBaseUrlCustomizer;
|
||||||
|
import org.springdoc.core.models.GroupedOpenApi;
|
||||||
|
import org.springdoc.core.properties.SpringDocConfigProperties;
|
||||||
import org.springdoc.core.providers.JavadocProvider;
|
import org.springdoc.core.providers.JavadocProvider;
|
||||||
|
import org.springdoc.core.service.OpenAPIService;
|
||||||
|
import org.springdoc.core.service.SecurityService;
|
||||||
|
import org.springdoc.core.utils.PropertyResolverUtils;
|
||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
|
|
||||||