Compare commits

..

158 Commits

Author SHA1 Message Date
b8e0d4391d Merge pull request #6200 from EightMonth/springboot3
修复 #6169
2024-04-30 13:52:00 +08:00
72b34d082b 修复 #6169 2024-04-30 11:53:59 +08:00
fbc312c35d Merge pull request #6173 from EightMonth/springboot3
修复#6127 #6130
2024-04-25 20:04:26 +08:00
b8162a4a6d 修复#6127 #6130 2024-04-25 16:01:58 +08:00
28404d2fd3 Merge pull request #6091 from EightMonth/springboot3
升级druid v1.2.22版本兼容处理
2024-04-08 15:26:49 +08:00
c92c9be49a 升级druid v1.2.22版本兼容处理 2024-04-08 14:04:07 +08:00
58e85e0569 Merge pull request #6081 from EightMonth/springboot3
升级druid1.2.22版本兼容处理
2024-04-03 16:35:30 +08:00
6fc34d8a39 升级druid1.2.22版本兼容处理 2024-04-03 16:18:31 +08:00
8aee4011a2 Merge pull request #6036 from EightMonth/springboot3
合并master变更,升级 3.6.3
2024-03-25 15:32:01 +08:00
6e0277c60a 升级druid版本,修复 #5936 2024-03-25 14:37:00 +08:00
e923654161 升级jimu版本至1.7.3,屏蔽flyway 2024-03-25 10:52:37 +08:00
06b41ae479 Merge branch 'master' into springboot3
# Conflicts:
#	db/tables_nacos.sql
#	jeecg-boot-base-core/pom.xml
#	jeecg-boot-base-core/src/main/java/org/jeecg/config/Swagger2Config.java
#	jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java
#	jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysFilesController.java
#	jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysRoleIndexController.java
#	jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/entity/SysFiles.java
#	jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/service/impl/SysPermissionServiceImpl.java
#	jeecg-module-system/jeecg-system-start/pom.xml
#	jeecg-module-system/jeecg-system-start/src/main/resources/application-dev.yml
#	jeecg-server-cloud/jeecg-cloud-gateway/pom.xml
#	jeecg-server-cloud/jeecg-visual/jeecg-cloud-sentinel/pom.xml
#	pom.xml
2024-03-25 09:39:13 +08:00
2cfc39b23f Merge branch 'master' of https://github.com/EightMonth/jeecg-boot 2024-03-22 17:12:32 +08:00
c8676b3040 优化注解生效范围配置 2024-03-22 17:11:18 +08:00
73bd04d04a Merge branch 'master' into master 2024-03-22 16:38:39 +08:00
0ca4badb77 修复 #6021 2024-03-22 16:37:00 +08:00
80b92ca132 flowable、activiti都支持 2024-03-22 16:22:48 +08:00
58865bef28 jimureport-drag:2.0.1 报错 java.lang.IllegalStateException: No TaglibFactory available #6021 2024-03-20 22:59:27 +08:00
9fd40d0973 代码生成器jar包中携带配置文件导致 spring.profiles.active 被覆盖 #6010 2024-03-20 10:07:54 +08:00
266ebd9122 修复 #5901 2024-03-19 09:41:29 +08:00
fee729e16c 【回滚】暂时回退mybatisplus、minidao版本,online模块不兼容 2024-03-18 14:06:09 +08:00
10a3e9c6ba 升级knife4j、mybatisplus、justauth、minidao版本 2024-03-18 10:11:05 +08:00
990f79fdfe 调整flyway配置,检查数据库类型只有mysql才启用 2024-03-18 09:27:54 +08:00
6360aee0ff 【QQYUN-8561】企业微信登陆请求接口设置上下文不一致,导致接口404 2024-03-18 09:25:51 +08:00
685b81e5ec Merge pull request #5930 from EightMonth/master
处理 #5601 ,添加@ignoreAuth注解
2024-03-15 15:30:48 +08:00
e38e395436 Merge branch 'master' into master 2024-03-15 15:29:35 +08:00
39af6e25ee ChatGPT AI助手,对接配置文档 2024-03-11 19:08:33 +08:00
b15e6e0422 【优化代码生成功能】uniapp调整目录 2024-03-09 22:30:41 +08:00
8f99a80352 【优化代码生成功能】uniapp调整目录、升级sql的命名改成flyway规则 2024-03-09 22:11:00 +08:00
936a87e738 积木报表 v1.7.2 紧急发布,修复 1.7.1 严重 Bug 2024-03-07 22:32:39 +08:00
2af165b201 【3.6.3版本发布】初始化sql有问题启动报flyway错误 2024-03-07 11:30:51 +08:00
3d5efc07ad 【3.6.3版本发布】升级积木报表的升级SQL 2024-03-06 19:02:39 +08:00
21e8d640d2 【3.6.3版本发布】升级积木报表的升级SQL 2024-03-06 18:55:35 +08:00
b0ce456909 【3.6.3版本发布】升级积木报表的升级SQL 2024-03-06 18:45:44 +08:00
b8e1306955 【3.6.3版本发布】升级积木报表的升级SQL 2024-03-06 18:44:35 +08:00
37a38ad288 【3.6.3版本发布】升级版本号 2024-03-06 17:13:05 +08:00
9ee05c9510 【3.6.3版本发布】新版数据库脚本 2024-03-06 17:00:54 +08:00
275a68bb6a 忽略文件 2024-03-06 16:24:23 +08:00
f3f70e8549 【3.6.3版本发布】代码修复 2024-03-06 16:22:36 +08:00
e15e9d80c4 【3.6.3版本发布】ai聊天模块新增代码 2024-03-06 16:22:03 +08:00
f7538c1ed8 【3.6.3版本发布】首页支持自定义 2024-03-06 16:20:49 +08:00
a9dba08a8d 【3.6.3版本发布】性能优化部分代码 2024-03-06 16:19:51 +08:00
4caff75cce Merge pull request #5935 from EightMonth/springboot3_config
修正spring boot3默认配置
2024-03-01 16:24:33 +08:00
811861a957 添加nacos sql自动创建nacos库 2024-03-01 16:15:06 +08:00
24623ba4b0 梳理服务配置信息 2024-03-01 16:06:12 +08:00
7c68b46943 添加springboot3的配置变更 2024-03-01 16:04:57 +08:00
acf0713385 Update ShiroConfig.java 2024-02-29 17:43:56 +08:00
7c34161369 删除无用文件 2024-02-29 17:41:13 +08:00
bc52aa918d gateway的配置改坏了,导致命名空间等不好使 2024-02-29 17:30:04 +08:00
cee872000a 处理 #5601 ,添加@ignoreAuth注解 2024-02-29 17:11:44 +08:00
4a857680d0 原生表单新增携带 createTime 等系统字段 #1033 2024-02-23 09:59:19 +08:00
a47d0984dc [issues/5755]vue代码不加入逻辑删除字段
[issue/#5711]修复用户选择组件在生成代码后变成部门用户选择组件
[issues/1022]我这个控件是哪里设置没对吗,为什么打开已有的记录,会触发提示“请输入”验证? #1022
fix 带条件字典存在单引号导致js编译错误
2024-02-19 16:40:33 +08:00
9dfdd47b36 springboot3版本的仪表盘依赖有问题,升级一个版本 2024-01-12 11:32:26 +08:00
272a7540eb 仪表盘升级为springboot3版本 2024-01-12 11:00:51 +08:00
ad796f079f flywaydb兼容springboot3报错,先注释掉 2024-01-12 11:00:37 +08:00
e7e7716d05 Merge pull request #5782 from EightMonth/springboot3
同步主干分支版本代码,并升级jedis至3.8.0
2024-01-12 10:39:24 +08:00
e333b126b6 微服务下字典拦截器报错 2024-01-10 14:58:01 +08:00
3618842f44 [issue/5787]增加非空判断防止代码生成时空指针异常 2024-01-09 19:12:16 +08:00
c5d620d2b2 升级jedis版本至3.8.0 2024-01-08 13:54:04 +08:00
cdea05ebb0 Merge branch 'master' into springboot3
# Conflicts:
#	jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java
#	jeecg-module-demo/src/main/java/org/jeecg/modules/demo/test/entity/JeecgDemo.java
#	jeecg-module-system/jeecg-system-biz/pom.xml
#	jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/SysTableWhiteListController.java
#	jeecg-module-system/jeecg-system-biz/src/main/java/org/jeecg/modules/system/controller/WechatVerifyController.java
#	jeecg-module-system/jeecg-system-start/pom.xml
#	jeecg-server-cloud/jeecg-visual/jeecg-cloud-sentinel/pom.xml
#	pom.xml
2024-01-08 13:52:33 +08:00
fd8c848c9e 修改小bug 2024-01-07 20:30:49 +08:00
09614a0239 修复几个bug 2024-01-07 20:28:41 +08:00
ca9a433f3c Merge pull request #5765 from hoperunChen/springboot3-fix-#5723
fix issue for springboot3 #5723: 指定jaxb-runtime版本,添加修改记录
2024-01-04 21:41:11 +08:00
2be6052cd4 Merge pull request #5766 from hoperunChen/springboot3-fix-#5742
fix issue for springboot3 #5742: 修改代码生成时的schema注解参数
2024-01-04 21:40:53 +08:00
68ed67ee49 shiro 无法使用 spring boot 3.X 自带的jedis,降版本处理 Merge pull request #5767 from hoperunChen/springboot3-fix-#5741
fix issue for springboot3 #5741: shiro 无法使用 spring boot 3.X 自带的jedis,降版本处理
2024-01-04 21:40:31 +08:00
d5903ba52a Merge remote-tracking branch 'upstream/springboot3' into springboot3-fix-#5741 2024-01-04 20:37:37 +08:00
3ee635eddf fix issue for springboot3 #5723: 指定jaxb-runtime版本,添加修改记录 2024-01-04 20:32:26 +08:00
21bc68fb53 fix issue for springboot3 #5741: shiro 无法使用 spring boot 3.X 自带的jedis,降版本处理 2024-01-04 20:19:46 +08:00
6fe8f1d81a 从3.6.2+版本增加flyway自动升级数据库机制 2024-01-04 14:56:06 +08:00
0bd7f715c4 默认删除人大金仓依赖,需要请自己放开 2024-01-04 13:57:23 +08:00
041d88161e 2024年首版本发布(antd4和仪表盘大升级) 2024-01-03 22:12:07 +08:00
79a62aa056 从3.6.2+版本增加flyway自动升级数据库机制 2024-01-03 22:07:27 +08:00
b86b4d9676 从3.6.2+版本增加flyway自动升级数据库机制 2024-01-03 22:01:07 +08:00
aeaac80012 2024年首版本发布(antd4和仪表盘大升级) 2024-01-03 19:46:35 +08:00
e0ef20cf08 3.6.2版本对应的数据库脚本 2024-01-03 18:58:30 +08:00
f532e57862 解决升级到springboot3, 表单excel导出失败,找不到 javax/servlet/ServletOutputStream #5738 2024-01-03 17:26:41 +08:00
169a66f5dd 升级新版本号3.6.2 2024-01-03 13:47:33 +08:00
7e39b31123 日志暂时不做权限控制 2024-01-03 13:44:36 +08:00
18765450a6 2024年首版本发布(仪表盘大升级) 2024-01-03 13:40:44 +08:00
dff8c84d9c 2024年首版本发布(仪表盘大升级) 2024-01-03 13:37:06 +08:00
d962c34846 新版数据库,有新升级sql和权限授权配置 2024-01-03 13:36:01 +08:00
da08adbea1 fix issue for springboot3 #5742: 修改代码生成时的schema注解参数 2024-01-02 13:41:54 +08:00
46e3e62b59 fix issue for springboot3 #5741: shiro 无法使用 spring boot 3.X 自带的jedis,降版本处理 2024-01-02 13:31:57 +08:00
cd9794d818 删除无用代码 2023-12-31 17:11:18 +08:00
5034b7cf18 提供新版仪表盘 2023-12-31 15:14:04 +08:00
fdde84c68a 代码生成器更新 2023-12-29 21:14:49 +08:00
4c54ff6f52 Merge branch 'master' of https://github.com/zhangdaiscott/jeecg-boot 2023-12-29 19:44:16 +08:00
de3285dc1b 通知公告 2023-12-29 19:43:12 +08:00
7f0c035c4c 企业微信集成改造 2023-12-29 19:42:36 +08:00
43593e8def 加权限注解 2023-12-29 19:42:24 +08:00
48b0b608d8 租户改造 2023-12-29 19:42:13 +08:00
69287a772b 小功能修改 2023-12-29 19:41:44 +08:00
3656264f8a 提供积木报表fastjson2版本 2023-12-28 22:34:23 +08:00
3361d48cd4 Merge branch 'springboot3' of https://github.com/zhangdaiscott/jeecg-boot into springboot3 2023-12-28 11:03:26 +08:00
ed86ea3da1 默认不需要nosql支持包 2023-12-28 11:03:10 +08:00
3deb0e5487 Merge pull request #5730 from EightMonth/springboot3
修改自动生成接口文档范围
2023-12-28 10:49:10 +08:00
9e4792941e 修改自动秣接口文档范围 2023-12-28 10:43:58 +08:00
b5fd5fe782 Merge pull request #5716 from EightMonth/springboot3
升级fastjson至2.0.43,替换tomcat为undertow
2023-12-26 17:21:30 +08:00
33c0104a02 增加undertow配置到test\prod 环境 2023-12-26 17:11:54 +08:00
81ed5100af 补充注释 2023-12-26 16:42:24 +08:00
87f9dc0064 去除无意义内容 2023-12-26 15:17:50 +08:00
b311fedc6b 升级fastjson至2.0.43,替换tomcat为undertow 2023-12-26 15:03:35 +08:00
337d5a9489 Merge pull request #5692 from hoperunChen/fix-QQYUN-7527
fix QQYUN-7527 vue3代码生成默认带上高级查询
2023-12-26 14:35:56 +08:00
cfeb81ee1e Merge branch 'master' of https://github.com/zhangdaiscott/jeecg-boot.git 2023-12-26 14:08:37 +08:00
09f92f01aa 提交online新依赖(解决online接口安全漏洞问题) 2023-12-26 14:08:20 +08:00
6d1094936b Merge pull request #5691 from hoperunChen/Fix-QQYUN-7583
fix QQYUN-7583 Vue3风格表单页面多选控件渲染成了下拉多选
2023-12-26 14:00:59 +08:00
8836a2793a Merge pull request #5690 from hoperunChen/fix-issues-#5658
fix issues #5658 树表复选框与展开按钮重叠问题
2023-12-26 13:59:52 +08:00
e321a0405f 升级aliyun.oss和minio的依赖 2023-12-26 10:01:57 +08:00
c36ece8923 补充信息 2023-12-23 19:24:15 +08:00
a82213b90c 还原错误提交 2023-12-21 15:47:28 +08:00
98facdd2ee Merge branch 'master' of https://github.com/zhangdaiscott/jeecg-boot.git 2023-12-21 15:45:21 +08:00
d080b0b5ea SpringBoot3+JDK17版本可以下载了 2023-12-21 15:36:09 +08:00
d8bc74794d 仪表盘也支持springboot3 2023-12-21 15:31:12 +08:00
338902ca0c Merge pull request #5706 from hoperunChen/fix-issue-vue3-#939
fix issue vue3 #939 npm run build 失败
2023-12-21 14:59:56 +08:00
732f05dc74 提供springboot3版本的online依赖支持 2023-12-21 14:57:14 +08:00
7ae6a11cf0 fix issue vue3 #939: modify file suffix 2023-12-21 14:31:51 +08:00
cdbe1cb1a9 fix issue vue3 #939 2023-12-21 13:31:04 +08:00
6ce92798c6 Merge pull request #5704 from EightMonth/springboot3
升级jeecg 3.6.1版本
2023-12-21 11:46:59 +08:00
f4454e9348 Merge branch 'springboot3' into springboot3 2023-12-21 09:52:14 +08:00
d9134ae0c8 Update WechatVerifyController.java 2023-12-21 09:46:52 +08:00
25180e41c8 更新minidao支持springboot3版本 2023-12-21 09:29:16 +08:00
a99e3f2268 更新积木报表支持springboot3版本 2023-12-21 09:28:00 +08:00
d27c354bf1 修改错误的配置 2023-12-21 09:26:40 +08:00
d818b1dd9d 更新jeecg-boot-starter3依赖 2023-12-21 09:26:39 +08:00
bcdbec0091 更新jeecg-boot-starter3依赖 2023-12-21 09:26:39 +08:00
098bb12b9e 更改jeecg-boot-starter3依赖 2023-12-21 09:26:39 +08:00
4a6c750b19 为注释内容添加注释原因 2023-12-21 09:26:39 +08:00
d396e5304a Update pom.xml 2023-12-21 09:26:38 +08:00
9bed25be8c spring3 2023-12-21 09:26:30 +08:00
232037ec58 1 2023-12-20 16:26:51 +08:00
b18c1120ab 流程引擎推荐 2023-12-20 16:25:45 +08:00
f6a7831963 1 2023-12-20 15:16:41 +08:00
08a4473bbc 1 2023-12-20 15:12:14 +08:00
9008ddafa4 1 2023-12-20 15:10:59 +08:00
7012ed4c2c 流程引擎 2023-12-20 15:08:54 +08:00
1d8c8c30d0 升级hutool版本号,解决hutool漏洞问题 CVE-2023-42278、CVE-2023-42277、CVE-2023-42276、CVE-2023-33695、CVE-2023-3276、CVE-2022-4565 2023-12-20 11:09:40 +08:00
7109b42092 Merge pull request #5698 from EightMonth/springboot3
更新积木报表、Minidao支持Springboot3版本
2023-12-20 10:10:51 +08:00
1667b14194 更新minidao支持springboot3版本 2023-12-20 10:00:14 +08:00
e9514873d2 更新积木报表支持springboot3版本 2023-12-19 14:31:17 +08:00
090f790df4 fix QQYUN-7527 vue3代码生成,默认带上高级查询 2023-12-19 11:06:05 +08:00
82d051f388 fix QQYUN-7583 Vue3风格表单页面多选控件渲染成了下拉多选 2023-12-19 11:05:16 +08:00
5a3631c332 fix issues #5658 树表复选框与展开按钮重叠问题 2023-12-19 11:03:18 +08:00
c00b5526c3 解决3.6.1版本添加online报表报错Subject does not have permission [online:report:add] #5672 2023-12-16 10:42:24 +08:00
2e35abd3a3 大龄码农的思考 2023-12-15 13:57:51 +08:00
9bc3f6c56e 源码下载说明 2023-12-15 13:53:42 +08:00
5588912b62 分支说明 2023-12-15 13:43:06 +08:00
37cf913d6d springboot3分支 2023-12-14 11:57:48 +08:00
94ba767090 SpringBoot3(JDK17)版本介绍 2023-12-14 11:54:44 +08:00
0ee090664e 修改错误的配置 2023-11-13 20:03:53 +08:00
4a9eda4ab0 Merge pull request #5567 from EightMonth/spring3
更新jeecg-boot-starter3依赖
2023-11-13 18:45:02 +08:00
2416c8b251 更新jeecg-boot-starter3依赖 2023-11-13 16:19:22 +08:00
5b056f9dd6 更新jeecg-boot-starter3依赖 2023-11-13 16:12:46 +08:00
a93998dc56 Merge pull request #5566 from EightMonth/spring3
更改jeecg-boot-starter3依赖
2023-11-13 15:43:21 +08:00
268c27a782 更改jeecg-boot-starter3依赖 2023-11-13 15:34:25 +08:00
23ace2712a Merge pull request #5563 from EightMonth/spring3
Spring Boot3 & JDK 17
2023-11-13 09:49:04 +08:00
157feeb925 为注释内容添加注释原因 2023-11-06 14:16:02 +08:00
4e25d4162f Update pom.xml 2023-11-06 14:11:23 +08:00
47a68f31e1 spring3 2023-11-06 12:41:57 +08:00
407 changed files with 28850 additions and 20023 deletions

5
.gitignore vendored
View File

@ -9,4 +9,7 @@ rebel.xml
## front
**/*.lock
os_del.cmd
os_del.cmd
os_del_doc.cmd
.svn
derby.log

View File

@ -7,13 +7,13 @@
JEECG BOOT Low Code Development Platform
===============
当前最新版本: 3.6.1发布日期2023-12-11
当前最新版本: 3.6.3发布日期2024-03-11
[![AUR](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg)](https://github.com/zhangdaiscott/jeecg-boot/blob/master/LICENSE)
[![](https://img.shields.io/badge/Author-guojusoft-orange.svg)](http://www.jeecg.com)
[![](https://img.shields.io/badge/Blog-blog-blue.svg)](https://jeecg.blog.csdn.net)
[![](https://img.shields.io/badge/version-3.6.1-brightgreen.svg)](https://github.com/zhangdaiscott/jeecg-boot)
[![](https://img.shields.io/badge/version-3.6.3-brightgreen.svg)](https://github.com/zhangdaiscott/jeecg-boot)
[![GitHub stars](https://img.shields.io/github/stars/zhangdaiscott/jeecg-boot.svg?style=social&label=Stars)](https://github.com/zhangdaiscott/jeecg-boot)
[![GitHub forks](https://img.shields.io/github/forks/zhangdaiscott/jeecg-boot.svg?style=social&label=Fork)](https://github.com/zhangdaiscott/jeecg-boot)
@ -58,13 +58,12 @@ Download the source code
| `jeecg-boot` | SpringBoot background source code (support microservices) |
| `jeecgboot-vue3` | Vue3+TS new front-end source code|
| `jeecg-uniapp` | [APP development framework, a code multi terminal adaptation, and support APP, small program, H5](https://github.com/jeecgboot/jeecg-uniapp) |
| `jeecg-boot-starter` | [Stater relies on the project to be maintained separately. Click Download](https://gitee.com/jeecg/jeecg-boot-starter) |
| `SpringBoot3+JDK17` | [BranchSourceCode](https://github.com/jeecgboot/jeecg-boot/tree/springboot3) [UpgradeBlog](https://blog.csdn.net/zhangdaiscott/article/details/134805602) |
| `More` | [Download more source code](http://jeecg.com/download) |
For the project
-----------------------------------
Jeecg-Boot low code development platform can be applied in the development of any J2EE project, especially for SAAS projects, enterprise information management system (MIS), internal office system (OA), enterprise resource planning system (ERP), customer relationship management system (CRM), etc. Its semi-intelligent manual Merge development method, Can significantly improve the development efficiency of more than 70%, greatly reduce the development cost.
@ -77,7 +76,7 @@ Docker starts the project
- [Docker starts the monomer background](https://help.jeecg.com/java/setup/docker/up.html)
- [Docker starts the Vue3 front-end](http://help.jeecg.com/publish/docker.html)
- [Docker starts the micro-service background](https://help.jeecg.com/java/springcloud/docker.html)
- [ChatGPT AI Config](https://help.jeecg.com/java/chatgpt.html)
@ -94,6 +93,11 @@ Technical documentation
Thinking
-----------------------------------
> We are pursuing the goal of implementing complex business systems without writing code! That has been done so far
- https://www.qiaoqiaoyun.com
Star charts
-----------------------------------
@ -437,6 +441,10 @@ Technical Architecture:
### Effect of system
##### ChatGPT AI Dialog
> Go to the JeecgBoot background home page and click "AI Assistant" in the middle of the right side of the home page. The AI Assistant dialog screen is displayed.
![](https://oscimg.oschina.net/oscnet/up-7c6405641a40f56638999d52da0cb5b4343.png)
##### PC
![](https://oscimg.oschina.net/oscnet/up-000530d95df337b43089ac77e562494f454.png)

View File

@ -7,13 +7,13 @@
JEECG BOOT 低代码开发平台
===============
当前最新版本: 3.6.1发布日期2023-12-11
当前最新版本: 3.6.3发布日期2024-03-11
[![AUR](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg)](https://github.com/zhangdaiscott/jeecg-boot/blob/master/LICENSE)
[![](https://img.shields.io/badge/Author-北京国炬软件-orange.svg)](http://jeecg.com/aboutusIndex)
[![](https://img.shields.io/badge/Blog-官方博客-blue.svg)](https://jeecg.blog.csdn.net)
[![](https://img.shields.io/badge/version-3.6.1-brightgreen.svg)](https://github.com/zhangdaiscott/jeecg-boot)
[![](https://img.shields.io/badge/version-3.6.3-brightgreen.svg)](https://github.com/zhangdaiscott/jeecg-boot)
[![GitHub stars](https://img.shields.io/github/stars/zhangdaiscott/jeecg-boot.svg?style=social&label=Stars)](https://github.com/zhangdaiscott/jeecg-boot)
[![GitHub forks](https://img.shields.io/github/forks/zhangdaiscott/jeecg-boot.svg?style=social&label=Fork)](https://github.com/zhangdaiscott/jeecg-boot)
@ -49,16 +49,17 @@ Jeecg-Boot低代码开发平台可以应用在任何J2EE项目的开发中
| Github | [jeecgboot-vue3](https://github.com/jeecgboot/jeecgboot-vue3) | [jeecg-boot](https://github.com/jeecgboot/jeecg-boot) |
| 码云 | [jeecgboot-vue3](https://gitee.com/jeecg/jeecgboot-vue3) | [jeecg-boot](https://gitee.com/jeecg/jeecg-boot) |
> 官方已推出 `SpringBoot3+JDK17版本` [分支源码下载](https://github.com/jeecgboot/jeecg-boot/tree/springboot3) | [升级SpringBoot3博客](https://blog.csdn.net/zhangdaiscott/article/details/134805602)
#### 项目说明
| 项目名 | 说明 |
|--------------------|------------------------|
| `jeecg-boot` | JAVA后台源码支持微服务 |
| `jeecgboot-vue3` | 前端源码 (Vue3版本) |
| `jeecg-boot` | 后端JAVA源码支持微服务 |
| `jeecg-uniapp` | [APP开发框架一份代码多终端适配同时支持APP、小程序、H5](https://github.com/jeecgboot/jeecg-uniapp) |
| `jeecg-boot-starter` | [Stater依赖项目单独维护点击下载](https://gitee.com/jeecg/jeecg-boot-starter) |
| `更多开源项目` | [更多源码下载](http://jeecg.com/download) |
| `更多开源项目` | [更多底层源码下载](http://jeecg.com/download) |
快速搭建开发环境
@ -68,7 +69,7 @@ Jeecg-Boot低代码开发平台可以应用在任何J2EE项目的开发中
- [通过IDEA启动前后端项目](https://help.jeecg.com/java/setup/idea/startup.html)
- [Vue3前端项目快速启动](http://help.jeecg.com/setup/startup.html)
- [单体快速切换为微服务版](https://help.jeecg.com/java/springcloud/switchcloud/monomer.html)
- [ChatGPT AI助手配置文档](https://help.jeecg.com/java/chatgpt.html)
Docker快速启动项目
-----------------------------------
@ -82,7 +83,7 @@ Docker快速启动项目
-----------------------------------
- 项目官网: [http://www.jeecg.com](http://www.jeecg.com)
- 开发文档: [http://help.jeecg.com](http://help.jeecg.com)
- 开发文档: [https://help.jeecg.com](https://help.jeecg.com)
- 新手指南: [快速入门](http://www.jeecg.com/doc/quickstart) | [常见问题 ](http://www.jeecg.com/doc/qa) | [视频教程](https://space.bilibili.com/454617261/channel/series) | [1分钟低代码体验](https://my.oschina.net/jeecg/blog/3083313)
- 在线演示 [Vue3演示](http://boot3.jeecg.com) | [APP演示](http://jeecg.com/appIndex) | [敲敲云零代码](https://qiaoqiaoyun.com)
@ -92,6 +93,12 @@ Docker快速启动项目
> ` 提醒【QQ群是自助服务群建议给帮助您解决问题的同学发送指定红包表示感谢】 `
大龄码农的思考
-----------------------------------
> 作为码农年纪大了写不动代码了怎么办??哎!!
所以我们团队在追求不写代码也可实现复杂业务系统!目前已经做到了,不信你到敲敲云零代码试试(通过流程串联修改业务数据)
- https://www.qiaoqiaoyun.com
技术支持
@ -104,8 +111,6 @@ Docker快速启动项目
VUE2版本专题介绍
-----------------------------------
#### 项目介绍
@ -191,8 +196,8 @@ Star走势图
* 17.支持SAAS服务模式提供SaaS多租户架构方案。
* 18.分布式文件服务集成minio、阿里OSS等优秀的第三方提供便捷的文件上传与管理同时也支持本地存储。
* 19.主流数据库兼容一套代码完全兼容Mysql、Postgresql、Oracle、Sqlserver、MariaDB、达梦等主流数据库。
* 20.集成工作流activiti、flowable并实现了只需在页面配置流程转向可极大的简化bpm工作流的开发用bpm的流程设计器画出了流程走向一个工作流基本就完成了只需写很少量的java代码
* 21.低代码能力:在线流程设计,采用开源Activiti流程引擎实现在线画流程,自定义表单,表单挂靠,业务流转
* 20.集成工作流flowable、activiti并实现了只需在页面配置流程转向可极大的简化bpm工作流的开发用bpm的流程设计器画出了流程走向一个工作流基本就完成了只需写很少量的java代码
* 21.低代码能力:在线流程设计,采用开源flowable、activiti流程引擎实现在线画流程,自定义表单,表单挂靠,业务流转
* 22.多数据源:及其简易的使用方式,在线配置数据源配置,便捷的从其他数据抓取数据;
* 23.提供单点登录CAS集成方案项目中已经提供完善的对接代码
* 24.低代码能力表单设计器支持用户自定义表单布局支持单表一对多表单、支持select、radio、checkbox、textarea、date、popup、列表、宏等控件
@ -462,13 +467,20 @@ Star走势图
```
### 流程引擎推荐
JeecgBoot企业版本默认集成了activiti和flowable两套方案大家在使用本开源项目时如果想进一步集成流程引擎推荐结合贺波老师的书 [《深入Activiti流程引擎核心原理与高阶实战》](https://item.m.jd.com/product/13928958.html?gx=RnAomTM2bmCImZxDqYAkVCoIHuIYVqc)
<img src="https://jeecgos.oss-cn-beijing.aliyuncs.com/files/tuijian20231220161656.png" width="25%" height="auto">
### 系统效果
##### ChatGPT AI交互
> 进入JeecgBoot后台首页点击首页右侧中间“AI助手”弹出AI助手对话界面。
![](https://oscimg.oschina.net/oscnet/up-7c6405641a40f56638999d52da0cb5b4343.png)
##### PC端
![](https://oscimg.oschina.net/oscnet/up-000530d95df337b43089ac77e562494f454.png)

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,11 +0,0 @@
-- 新增风格一对多内嵌和Tab风格
INSERT INTO sys_permission (id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('1691031996d5931315212', '1455100420297859074', 'AUTO在线一对多内嵌', '/online/cgformInnerTableList/:id', 'super/online/cgform/auto/innerTable/OnlCgformInnerTableList', 1, '', NULL, 1, NULL, '0', 1.00, 0, NULL, 1, 0, 1, 0, NULL, 'admin', '2023-08-14 18:20:20', 'admin', '2023-08-14 18:46:18', 0, 0, NULL, 0);
INSERT INTO sys_permission (id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('1691031996d5931315213', '1455100420297859074', 'AUTO在线Tab风格', '/online/cgformTabList/:id', 'super/online/cgform/auto/tab/OnlCgformTabList', 1, '', NULL, 1, NULL, '0', 1.00, 0, NULL, 1, 0, 1, 0, NULL, 'admin', '2023-08-14 18:20:20', 'admin', '2023-08-14 18:46:18', 0, 0, NULL, 0);
-- 安全online敏感接口加权限注解sql解析接口同步数据库接口导入表接口
INSERT INTO sys_permission (id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) VALUES ('1699374704168534017', '1460888189937176577', 'SQL解析', NULL, NULL, 0, NULL, NULL, 2, 'online:report:parseSql', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2023-09-06 18:51:17', NULL, NULL, 0, 0, '1', 0);
INSERT INTO sys_permission (id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) VALUES ('1699374509749960705', '1455101470794850305', '查询数据库表名', NULL, NULL, 0, NULL, NULL, 2, 'online:form:queryTables', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2023-09-06 18:50:31', NULL, NULL, 0, 0, '1', 0);
INSERT INTO sys_permission (id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) VALUES ('1699374269152100354', '1455101470794850305', '同步数据库', NULL, NULL, 0, NULL, NULL, 2, 'online:form:syncDb', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2023-09-06 18:49:33', NULL, NULL, 0, 0, '1', 0);
update sys_permission set is_leaf=0 where id in ('1460888189937176577','1455101470794850305');

View File

@ -1,11 +0,0 @@
版本升级方法?
JeecgBoot属于平台级产品每次升级改动内容较多目前做不到平滑升级。
升级方案建议:
1.代码升级 => 本地版本通过svn或者git做好主干在分支上做业务开发jeecg每次版本发布可以手工覆盖主干的代码对比合并代码
2.数据库升级 => 针对数据库我们每次发布会提供增量升级SQL可以通过执行增量SQL实现数据库的升级。
3.兼容问题 => 每次版本发布会针对不兼容地方标注说明,需要手工修改不兼容的代码。
注意: 升级sql目前只提供mysql版本执行完脚步后新菜单需要手工进行角色授权刷新首页才会出现。
【20230820 放开了系统管理等模块权限注解,如果没权限请通过角色授权授权对应的按钮权限】

15
db/版本升级说明.md Normal file
View File

@ -0,0 +1,15 @@
# 版本升级方法
> JeecgBoot属于平台级产品每次升级改动较大目前做不到平滑升级。
### 增量升级方案
#### 1.代码合并
本地通过svn或git做好主干在分支上做业务开发jeecg每次版本发布可以手工覆盖主干的代码对比合并代码
#### 2.数据库升级
- 从3.6.2+版本增加flyway自动升级数据库机制支持 mysql5.7、mysql8;
- 其他库请手工执行SQL, 目录: `jeecg-module-system\jeecg-system-start\src\main\resources\flyway\sql\mysql`
> 注意: 升级sql只提供mysql版本如果有权限升级, 还需要手工角色授权,退出重新登录才好使。
#### 3.兼容问题
每次发版,会针对不兼容地方重点说明。

View File

@ -4,11 +4,15 @@
<parent>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-parent</artifactId>
<version>3.6.1</version>
<version>3.6.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jeecg-boot-base-core</artifactId>
<properties>
<spring-boot.version>3.1.5</spring-boot.version>
</properties>
<repositories>
<repository>
<id>aliyun</id>
@ -43,12 +47,22 @@
<!--jeecg-tools-->
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-common</artifactId>
<artifactId>jeecg-boot-common3</artifactId>
</dependency>
<!--集成springmvc框架并实现自动配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<!-- websocket -->
<dependency>
@ -82,7 +96,7 @@
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons.version}</version>
<version>${commons-io.version}</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
@ -105,14 +119,14 @@
<!-- druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<artifactId>druid-spring-boot-3-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- 动态数据源 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<artifactId>dynamic-datasource-spring-boot3-starter</artifactId>
<version>${dynamic-datasource-spring-boot-starter.version}</version>
</dependency>
@ -164,6 +178,12 @@
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-starter</artifactId>
<version>${shiro.version}</version>
<exclusions>
<exclusion>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- shiro-redis -->
<dependency>
@ -179,13 +199,61 @@
<artifactId>checkstyle</artifactId>
<groupId>com.puppycrawl.tools</groupId>
</exclusion>
<!-- TODO shiro 无法使用 spring boot 3.X 自带的jedis降版本处理 -->
<exclusion>
<artifactId>jedis</artifactId>
<groupId>redis.clients</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- TODO shiro 无法使用 spring boot 3.X 自带的jedis降版本处理 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>${jedis.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<classifier>jakarta</classifier>
<version>${shiro.version}</version>
<!-- 排除仍使用了javax.servlet的依赖 -->
<exclusions>
<exclusion>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 引入适配jakarta的依赖包 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<classifier>jakarta</classifier>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<classifier>jakarta</classifier>
<version>${shiro.version}</version>
<exclusions>
<exclusion>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- knife4j -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<version>${knife4j-spring-boot-starter.version}</version>
</dependency>
@ -199,7 +267,7 @@
<!-- AutoPoi Excel工具类-->
<dependency>
<groupId>org.jeecgframework</groupId>
<groupId>org.jeecgframework.boot3</groupId>
<artifactId>autopoi-web</artifactId>
<version>${autopoi-web.version}</version>
<exclusions>
@ -242,6 +310,16 @@
<dependency>
<groupId>com.xkcoding.justauth</groupId>
<artifactId>justauth-spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
@ -256,6 +334,15 @@
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
</dependency>
<!--加载hutool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-crypto</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -22,10 +22,10 @@ public interface CommonAPI {
/**
* 2查询用户权限信息
* @param username
* @param userId
* @return
*/
Set<String> queryUserAuths(String username);
Set<String> queryUserAuths(String userId);
/**
* 3根据 id 查询数据库中存储的 DynamicDataSourceModel
@ -117,14 +117,17 @@ public interface CommonAPI {
*/
Map<String, List<DictModel>> translateManyDict(String dictCodes, String keys);
//update-begin---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
/**
* 15 字典表的 翻译,可批量
* @param table
* @param text
* @param code
* @param keys 多个用逗号分割
* @param dataSource 数据源
* @return
*/
List<DictModel> translateDictFromTableByKeys(String table, String text, String code, String keys);
List<DictModel> translateDictFromTableByKeys(String table, String text, String code, String keys, String dataSource);
//update-end---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
}

View File

@ -17,6 +17,8 @@ public class DataLogDTO {
private String type;
private String createName;
public DataLogDTO(){
}

View File

@ -2,7 +2,7 @@ package org.jeecg.common.api.dto;
import lombok.Data;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletResponse;
import java.io.Serializable;
/**

View File

@ -30,6 +30,13 @@ public class OnlineAuthDTO implements Serializable {
*/
private String onlineFormUrl;
//update-begin---author:chenrui ---date:20240123 for[QQYUN-7992]【online】工单申请下的online表单未配置online表单开发菜单操作报错无权限------------
/**
* online工单的地址
*/
private String onlineWorkOrderUrl;
//update-end---author:chenrui ---date:20240123 for[QQYUN-7992]【online】工单申请下的online表单未配置online表单开发菜单操作报错无权限------------
public OnlineAuthDTO(){
}

View File

@ -1,8 +1,7 @@
package org.jeecg.common.api.vo;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.jeecg.common.constant.CommonConstant;
@ -15,7 +14,7 @@ import java.io.Serializable;
* @date 2019年1月19日
*/
@Data
@ApiModel(value="接口返回对象", description="接口返回对象")
@Schema(description="接口返回对象")
public class Result<T> implements Serializable {
private static final long serialVersionUID = 1L;
@ -23,31 +22,31 @@ public class Result<T> implements Serializable {
/**
* 成功标志
*/
@ApiModelProperty(value = "成功标志")
@Schema(description = "成功标志")
private boolean success = true;
/**
* 返回处理消息
*/
@ApiModelProperty(value = "返回处理消息")
@Schema(description = "返回处理消息")
private String message = "";
/**
* 返回代码
*/
@ApiModelProperty(value = "返回代码")
@Schema(description = "返回代码")
private Integer code = 0;
/**
* 返回数据对象 data
*/
@ApiModelProperty(value = "返回数据对象")
@Schema(description = "返回数据对象")
private T result;
/**
* 时间戳
*/
@ApiModelProperty(value = "时间戳")
@Schema(description = "时间戳")
private long timestamp = System.currentTimeMillis();
public Result() {

View File

@ -21,13 +21,14 @@ import org.jeecg.common.util.IpUtils;
import org.jeecg.common.util.SpringContextUtils;
import org.jeecg.common.util.oConvertUtils;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.core.StandardReflectionParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;
@ -158,6 +159,9 @@ public class AutoLogAspect {
if(value!=null && value.toString().length()>length){
return false;
}
if(value instanceof MultipartFile){
return false;
}
return true;
}
};
@ -169,7 +173,7 @@ public class AutoLogAspect {
// 请求的方法参数值
Object[] args = joinPoint.getArgs();
// 请求的方法参数名称
LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
StandardReflectionParameterNameDiscoverer u=new StandardReflectionParameterNameDiscoverer();
String[] paramNames = u.getParameterNames(method);
if (args != null && paramNames != null) {
for (int i = 0; i < args.length; i++) {

View File

@ -140,11 +140,15 @@ public class DictAspect {
String code = field.getAnnotation(Dict.class).dicCode();
String text = field.getAnnotation(Dict.class).dicText();
String table = field.getAnnotation(Dict.class).dictTable();
//update-begin---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
String dataSource = field.getAnnotation(Dict.class).ds();
//update-end---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
List<String> dataList;
String dictCode = code;
if (!StringUtils.isEmpty(table)) {
dictCode = String.format("%s,%s,%s", table, text, code);
//update-begin---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
dictCode = String.format("%s,%s,%s,%s", table, text, code, dataSource);
//update-end---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
}
dataList = dataListMap.computeIfAbsent(dictCode, k -> new ArrayList<>());
this.listAddAllDeduplicate(dataList, Arrays.asList(value.split(",")));
@ -169,10 +173,15 @@ public class DictAspect {
String code = field.getAnnotation(Dict.class).dicCode();
String text = field.getAnnotation(Dict.class).dicText();
String table = field.getAnnotation(Dict.class).dictTable();
//update-begin---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
// 自定义的字典表数据源
String dataSource = field.getAnnotation(Dict.class).ds();
//update-end---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
String fieldDictCode = code;
if (!StringUtils.isEmpty(table)) {
fieldDictCode = String.format("%s,%s,%s", table, text, code);
//update-begin---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
fieldDictCode = String.format("%s,%s,%s,%s", table, text, code, dataSource);
//update-end---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
}
String value = record.getString(field.getName());
@ -274,9 +283,25 @@ public class DictAspect {
String[] arr = dictCode.split(",");
String table = arr[0], text = arr[1], code = arr[2];
String values = String.join(",", needTranslDataTable);
//update-begin---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
// 自定义的数据源
String dataSource = null;
if (arr.length > 3) {
dataSource = arr[3];
}
//update-end---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
log.debug("translateDictFromTableByKeys.dictCode:" + dictCode);
log.debug("translateDictFromTableByKeys.values:" + values);
List<DictModel> texts = commonApi.translateDictFromTableByKeys(table, text, code, values);
//update-begin---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
//update-begin---author:wangshuai---date:2024-01-09---for:微服务下为空报错没有参数需要传递空字符串---
if(null == dataSource){
dataSource = "";
}
//update-end---author:wangshuai---date:2024-01-09---for:微服务下为空报错没有参数需要传递空字符串---
List<DictModel> texts = commonApi.translateDictFromTableByKeys(table, text, code, values, dataSource);
//update-end---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
log.debug("translateDictFromTableByKeys.result:" + texts);
List<DictModel> list = translText.computeIfAbsent(dictCode, k -> new ArrayList<>());
list.addAll(texts);

View File

@ -21,7 +21,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.List;

View File

@ -39,4 +39,16 @@ public @interface Dict {
* @return 返回类型: String
*/
String dictTable() default "";
//update-begin---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
/**
* 方法描述: 数据字典表所在数据源名称
* 作 者: chenrui
* 日 期: 2023年12月20日-下午4:58
*
* @return 返回类型: String
*/
String ds() default "";
//update-end---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
}

View File

@ -69,6 +69,8 @@ public interface CommonConstant {
/** {@code 500 Server Error} (HTTP/1.0 - RFC 1945) */
Integer SC_INTERNAL_SERVER_ERROR_500 = 500;
/** {@code 404 Not Found} (HTTP/1.0 - RFC 1945) */
Integer SC_INTERNAL_NOT_FOUND_404 = 404;
/** {@code 200 OK} (HTTP/1.0 - RFC 1945) */
Integer SC_OK_200 = 200;
@ -375,6 +377,8 @@ public interface CommonConstant {
/**前端vue3版本Header参数名*/
String VERSION="X-Version";
String VERSION_V3 = "v3";
/**存储在线程变量里的动态表名*/
String DYNAMIC_TABLE_NAME="DYNAMIC_TABLE_NAME";
/**

View File

@ -17,6 +17,9 @@ public interface DataBaseConstant {
/**postgreSQL达梦数据库*/
public static final String DB_TYPE_POSTGRESQL = "POSTGRESQL";
/**人大金仓数据库*/
public static final String DB_TYPE_KINGBASEES = "KINGBASEES";
/**sqlserver数据库*/
public static final String DB_TYPE_SQLSERVER = "SQLSERVER";

View File

@ -13,12 +13,16 @@ import java.util.List;
public enum RoleIndexConfigEnum {
/**首页自定义 admin*/
ADMIN("admin", "dashboard/Analysis"),
// ADMIN("admin", "dashboard/Analysis"),
//TEST("test", "dashboard/IndexChart"),
/**首页自定义 hr*/
HR("hr", "dashboard/IndexBdc");
// HR("hr", "dashboard/IndexBdc");
//DM("dm", "dashboard/IndexTask"),
// 注:此值仅为防止报错,无任何实际意义
ROLE_INDEX_CONFIG_ENUM("RoleIndexConfigEnumDefault", "dashboard/Analysis");
/**
* 角色编码
*/

View File

@ -1,5 +1,7 @@
package org.jeecg.common.exception;
import org.jeecg.common.constant.CommonConstant;
/**
* @Description: jeecg-boot自定义异常
* @author: jeecg-boot
@ -7,10 +9,24 @@ package org.jeecg.common.exception;
public class JeecgBootException extends RuntimeException {
private static final long serialVersionUID = 1L;
/**
* 返回给前端的错误code
*/
private int errCode = CommonConstant.SC_INTERNAL_SERVER_ERROR_500;
public JeecgBootException(String message){
super(message);
}
public JeecgBootException(String message, int errCode){
super(message);
this.errCode = errCode;
}
public int getErrCode() {
return errCode;
}
public JeecgBootException(Throwable cause)
{
super(cause);

View File

@ -33,7 +33,7 @@ public class JeecgBootExceptionHandler {
@ExceptionHandler(JeecgBootException.class)
public Result<?> handleJeecgBootException(JeecgBootException e){
log.error(e.getMessage(), e);
return Result.error(e.getMessage());
return Result.error(e.getErrCode(), e.getMessage());
}
/**

View File

@ -23,9 +23,9 @@ import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

View File

@ -9,10 +9,10 @@ import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import io.swagger.v3.oas.annotations.media.Schema;
/**
* @Description: Entity基类
@ -30,20 +30,20 @@ public class JeecgEntity implements Serializable {
* ID
*/
@TableId(type = IdType.ASSIGN_ID)
@ApiModelProperty(value = "ID")
@Schema(description = "ID")
private java.lang.String id;
/**
* 创建人
*/
@ApiModelProperty(value = "创建人")
@Schema(description = "创建人")
@Excel(name = "创建人", width = 15)
private java.lang.String createBy;
/**
* 创建时间
*/
@ApiModelProperty(value = "创建时间")
@Schema(description = "创建时间")
@Excel(name = "创建时间", width = 20, format = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@ -52,14 +52,14 @@ public class JeecgEntity implements Serializable {
/**
* 更新人
*/
@ApiModelProperty(value = "更新人")
@Schema(description = "更新人")
@Excel(name = "更新人", width = 15)
private java.lang.String updateBy;
/**
* 更新时间
*/
@ApiModelProperty(value = "更新时间")
@Schema(description = "更新时间")
@Excel(name = "更新时间", width = 20, format = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")

View File

@ -5,7 +5,7 @@ import org.jeecg.common.system.vo.SysUserCacheInfo;
import org.jeecg.common.util.SpringContextUtils;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;

View File

@ -11,10 +11,10 @@ import com.google.common.base.Joiner;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Date;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;

View File

@ -19,6 +19,8 @@ public class SysFilesModel {
private String storeType;
/**文件大小kb*/
private Double fileSize;
/**租户id*/
private String tenantId;
public String getId() {
return id;
@ -67,4 +69,12 @@ public class SysFilesModel {
public void setFileSize(Double fileSize) {
this.fileSize = fileSize;
}
public String getTenantId() {
return tenantId;
}
public void setTenantId(String tenantId) {
this.tenantId = tenantId;
}
}

View File

@ -5,7 +5,7 @@ import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequest;
/**
*

View File

@ -19,7 +19,7 @@ import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequest;
import javax.sql.DataSource;
import java.io.ByteArrayInputStream;
import java.io.File;
@ -28,7 +28,9 @@ import java.io.InputStream;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -302,7 +304,7 @@ public class CommonUtils {
DB_TYPE = DataBaseConstant.DB_TYPE_ORACLE;
}else if(dbType.indexOf(DataBaseConstant.DB_TYPE_SQLSERVER)>=0||dbType.indexOf(sqlserver)>=0) {
DB_TYPE = DataBaseConstant.DB_TYPE_SQLSERVER;
}else if(dbType.indexOf(DataBaseConstant.DB_TYPE_POSTGRESQL)>=0) {
}else if(dbType.indexOf(DataBaseConstant.DB_TYPE_POSTGRESQL)>=0 || dbType.indexOf(DataBaseConstant.DB_TYPE_KINGBASEES)>=0) {
DB_TYPE = DataBaseConstant.DB_TYPE_POSTGRESQL;
}else if(dbType.indexOf(DataBaseConstant.DB_TYPE_MARIADB)>=0) {
DB_TYPE = DataBaseConstant.DB_TYPE_MARIADB;
@ -346,8 +348,11 @@ public class CommonUtils {
//返回 host domain
String baseDomainPath = null;
int length = 80;
if(length == serverPort){
//update-begin---author:wangshuai---date:2024-03-15---for:【QQYUN-8561】企业微信登陆请求接口设置上下文不一致导致接口404---
int httpPort = 80;
int httpsPort = 443;
if(httpPort == serverPort || httpsPort == serverPort){
//update-end---author:wangshuai---date:2024-03-15---for:【QQYUN-8561】企业微信登陆请求接口设置上下文不一致导致接口404---~
baseDomainPath = scheme + "://" + serverName + contextPath ;
}else{
baseDomainPath = scheme + "://" + serverName + ":" + serverPort + contextPath ;
@ -467,4 +472,19 @@ public class CommonUtils {
}
return false;
}
/**
* 输出info日志会捕获异常防止因为日志问题导致程序异常
*
* @param msg
* @param objects
*/
public static void logInfo(String msg, Object... objects) {
try {
log.info(msg, objects);
} catch (Exception e) {
log.warn("{} —— {}", msg, e.getMessage());
}
}
}

View File

@ -62,8 +62,8 @@ public class DySmsHelper {
//update-begin-authortaoyan date:20200811 for:配置类数据获取
StaticConfig staticConfig = SpringContextUtils.getBean(StaticConfig.class);
logger.info("阿里大鱼短信秘钥 accessKeyId" + staticConfig.getAccessKeyId());
logger.info("阿里大鱼短信秘钥 accessKeySecret"+ staticConfig.getAccessKeySecret());
//logger.info("阿里大鱼短信秘钥 accessKeyId" + staticConfig.getAccessKeyId());
//logger.info("阿里大鱼短信秘钥 accessKeySecret"+ staticConfig.getAccessKeySecret());
setAccessKeyId(staticConfig.getAccessKeyId());
setAccessKeySecret(staticConfig.getAccessKeySecret());
//update-end-authortaoyan date:20200811 for:配置类数据获取

View File

@ -1,6 +1,6 @@
package org.jeecg.common.util;
import javax.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.constant.CommonConstant;

View File

@ -1,7 +1,7 @@
package org.jeecg.common.util;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.ServiceNameConstants;

View File

@ -29,6 +29,17 @@ public class SqlInjectionUtil {
* 字典专用—sql注入关键词
*/
private static String specialDictSqlXssStr = "exec |peformance_schema|information_schema|extractvalue|updatexml|geohash|gtid_subset|gtid_subtract|insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |;|+|--";
/**
* 完整匹配的key不需要考虑前空格
*/
private static List<String> FULL_MATCHING_KEYWRODS = new ArrayList<>();
static {
FULL_MATCHING_KEYWRODS.add(";");
FULL_MATCHING_KEYWRODS.add("+");
FULL_MATCHING_KEYWRODS.add("--");
}
/**
* sql注入风险的 正则关键字
*
@ -50,6 +61,8 @@ public class SqlInjectionUtil {
* sql注释的正则
*/
private final static Pattern SQL_ANNOTATION = Pattern.compile("/\\*[\\s\\S]*\\*/");
private final static String SQL_ANNOTATION2 = "--";
/**
* sql注入提示语
*/
@ -128,7 +141,13 @@ public class SqlInjectionUtil {
if (sql.startsWith(keyword.trim())) {
return true;
} else if (sql.contains(keyword)) {
if (sql.contains(" " + keyword)) {
// 需要匹配的sql注入关键词
String matchingText = " " + keyword;
if(FULL_MATCHING_KEYWRODS.contains(keyword)){
matchingText = keyword;
}
if (sql.contains(matchingText)) {
return true;
} else {
String regularStr = "\\s+\\S+" + keyword;
@ -244,6 +263,13 @@ public class SqlInjectionUtil {
* @return
*/
public static void checkSqlAnnotation(String str){
if(str.contains(SQL_ANNOTATION2)){
String error = "请注意SQL中不允许含注释有安全风险";
log.error(error);
throw new RuntimeException(error);
}
Matcher matcher = SQL_ANNOTATION.matcher(str);
if(matcher.find()){
String error = "请注意值可能存在SQL注入风险---> \\*.*\\";
@ -260,7 +286,7 @@ public class SqlInjectionUtil {
*
* @param table
*/
private static Pattern tableNamePattern = Pattern.compile("^[a-zA-Z][a-zA-Z0-9_]{0,63}$");
private static Pattern tableNamePattern = Pattern.compile("^[a-zA-Z][a-zA-Z0-9_\\$]{0,63}$");
public static String getSqlInjectTableName(String table) {
if(oConvertUtils.isEmpty(table)){
return table;

View File

@ -11,7 +11,7 @@ import org.jeecg.common.exception.JeecgBoot401Exception;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.LoginUser;
import javax.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequest;
/**
* @Author scott

View File

@ -61,6 +61,10 @@ public class SsrfFileTypeFilter {
FILE_TYPE_WHITE_LIST.add("7z");
FILE_TYPE_WHITE_LIST.add("tar");
//app文件后缀
FILE_TYPE_WHITE_LIST.add("apk");
FILE_TYPE_WHITE_LIST.add("wgt");
//设置禁止文件的头部标记
FILE_TYPE_MAP.put("3c25402070616765206c", "jsp");
FILE_TYPE_MAP.put("3c3f7068700a0a2f2a2a0a202a205048", "php");

View File

@ -7,7 +7,7 @@ import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.SymbolConstant;
import org.springframework.beans.BeanUtils;
import javax.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
@ -413,7 +413,7 @@ public class oConvertUtils {
return false;
}
String[] childs = childArray.toArray(new String[]{});
String[] childs = (String[]) childArray.toArray();
for (String v : childs) {
if (!isIn(v, all)) {
return false;

View File

@ -1,55 +1,6 @@
package org.jeecg.common.util.sqlInjection.parse;
import net.sf.jsqlparser.expression.AllValue;
import net.sf.jsqlparser.expression.AnalyticExpression;
import net.sf.jsqlparser.expression.AnyComparisonExpression;
import net.sf.jsqlparser.expression.ArrayConstructor;
import net.sf.jsqlparser.expression.ArrayExpression;
import net.sf.jsqlparser.expression.BinaryExpression;
import net.sf.jsqlparser.expression.CaseExpression;
import net.sf.jsqlparser.expression.CastExpression;
import net.sf.jsqlparser.expression.CollateExpression;
import net.sf.jsqlparser.expression.ConnectByRootOperator;
import net.sf.jsqlparser.expression.DateTimeLiteralExpression;
import net.sf.jsqlparser.expression.DateValue;
import net.sf.jsqlparser.expression.DoubleValue;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.ExpressionVisitor;
import net.sf.jsqlparser.expression.ExtractExpression;
import net.sf.jsqlparser.expression.Function;
import net.sf.jsqlparser.expression.HexValue;
import net.sf.jsqlparser.expression.IntervalExpression;
import net.sf.jsqlparser.expression.JdbcNamedParameter;
import net.sf.jsqlparser.expression.JdbcParameter;
import net.sf.jsqlparser.expression.JsonAggregateFunction;
import net.sf.jsqlparser.expression.JsonExpression;
import net.sf.jsqlparser.expression.JsonFunction;
import net.sf.jsqlparser.expression.JsonFunctionExpression;
import net.sf.jsqlparser.expression.KeepExpression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.MySQLGroupConcat;
import net.sf.jsqlparser.expression.NextValExpression;
import net.sf.jsqlparser.expression.NotExpression;
import net.sf.jsqlparser.expression.NullValue;
import net.sf.jsqlparser.expression.NumericBind;
import net.sf.jsqlparser.expression.OracleHierarchicalExpression;
import net.sf.jsqlparser.expression.OracleHint;
import net.sf.jsqlparser.expression.OracleNamedFunctionParameter;
import net.sf.jsqlparser.expression.Parenthesis;
import net.sf.jsqlparser.expression.RowConstructor;
import net.sf.jsqlparser.expression.RowGetExpression;
import net.sf.jsqlparser.expression.SignedExpression;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.TimeKeyExpression;
import net.sf.jsqlparser.expression.TimeValue;
import net.sf.jsqlparser.expression.TimestampValue;
import net.sf.jsqlparser.expression.TimezoneExpression;
import net.sf.jsqlparser.expression.TryCastExpression;
import net.sf.jsqlparser.expression.UserVariable;
import net.sf.jsqlparser.expression.ValueListExpression;
import net.sf.jsqlparser.expression.VariableAssignment;
import net.sf.jsqlparser.expression.WhenClause;
import net.sf.jsqlparser.expression.XMLSerializeExpr;
import net.sf.jsqlparser.expression.*;
import net.sf.jsqlparser.expression.operators.arithmetic.Addition;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseAnd;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseLeftShift;
@ -215,6 +166,23 @@ public class ConstAnalyzer implements ExpressionVisitor, ItemsListVisitor {
expr.getBetweenExpressionEnd().accept(this);
}
// /**
// * 用于处理 OverlapsCondition 类型的表达式
// * @param overlapsCondition
// */
// @Override
// public void visit(OverlapsCondition overlapsCondition) {
// constFlag.set(false);
// }
// /**
// * 用于处理 SafeCastExpression 类型的表达式。
// * @param safeCastExpression
// */
// @Override
// public void visit(SafeCastExpression safeCastExpression) {
// constFlag.set(false);
// }
@Override
public void visit(EqualsTo expr) {
visitBinaryExpression(expr);

View File

@ -3,7 +3,7 @@ package org.jeecg.config;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Resource;
import jakarta.annotation.Resource;
import org.jeecg.common.api.CommonAPI;
import org.jeecg.common.system.vo.DictModel;

View File

@ -2,7 +2,9 @@ package org.jeecg.config;
import java.io.IOException;
import javax.servlet.*;
import com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceAutoConfigure;
import com.alibaba.druid.spring.boot3.autoconfigure.properties.DruidStatProperties;
import jakarta.servlet.*;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@ -11,8 +13,6 @@ import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
import com.alibaba.druid.util.Utils;
/**

View File

@ -0,0 +1,47 @@
package org.jeecg.config;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringApplicationRunListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;
import java.util.HashMap;
import java.util.Map;
/**
* @author eightmonth@qq.com
* @date 2024/4/8 11:37
*/
public class DruidWallConfigRegister implements SpringApplicationRunListener {
public SpringApplication application;
private String[] args;
/**
* 必备,否则启动报错
* @param application
* @param args
*/
public DruidWallConfigRegister(SpringApplication application, String[] args) {
this.application = application;
this.args = args;
}
@Override
public void contextLoaded(ConfigurableApplicationContext context) {
ConfigurableEnvironment env = context.getEnvironment();
Map<String, Object> props = new HashMap<>();
props.put("spring.datasource.dynamic.druid.wall.selectWhereAlwayTrueCheck", false);
MutablePropertySources propertySources = env.getPropertySources();
PropertySource<Map<String, Object>> propertySource = new MapPropertySource("jeecg-datasource-config", props);
propertySources.addLast(propertySource);
}
}

View File

@ -1,183 +1,183 @@
package org.jeecg.config;
import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import io.swagger.annotations.ApiOperation;
import org.jeecg.common.constant.CommonConstant;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.spring.web.plugins.WebFluxRequestHandlerProvider;
import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* @Author scott
*/
@Configuration
@EnableSwagger2 //开启 Swagger2
@EnableKnife4j //开启 knife4j可以不写
@Import(BeanValidatorPluginsConfiguration.class)
public class Swagger2Config implements WebMvcConfigurer {
/**
*
* 显示swagger-ui.html文档展示页还必须注入swagger资源
*
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
/**
* swagger2的配置文件这里可以配置swagger2的一些基本的内容比如扫描的包等等
*
* @return Docket
*/
@Bean(value = "defaultApi2")
public Docket defaultApi2() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
//此包路径下的类,才生成接口文档
.apis(RequestHandlerSelectors.basePackage("org.jeecg"))
//加了ApiOperation注解的类才生成接口文档
.apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build()
.securitySchemes(Collections.singletonList(securityScheme()))
.securityContexts(securityContexts())
.globalOperationParameters(setHeaderToken());
}
/***
* oauth2配置
* 需要增加swagger授权回调地址
* http://localhost:8888/webjars/springfox-swagger-ui/o2c.html
* @return
*/
@Bean
SecurityScheme securityScheme() {
return new ApiKey(CommonConstant.X_ACCESS_TOKEN, CommonConstant.X_ACCESS_TOKEN, "header");
}
/**
* JWT token
* @return
*/
private List<Parameter> setHeaderToken() {
ParameterBuilder tokenPar = new ParameterBuilder();
List<Parameter> pars = new ArrayList<>();
tokenPar.name(CommonConstant.X_ACCESS_TOKEN).description("token").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
pars.add(tokenPar.build());
return pars;
}
/**
* api文档的详细信息函数,注意这里的注解引用的是哪个
*
* @return
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
// //大标题
.title("JeecgBoot 后台服务API接口文档")
// 版本号
.version("1.0")
// .termsOfServiceUrl("NO terms of service")
// 描述
.description("后台API接口")
// 作者
.contact(new Contact("北京国炬信息技术有限公司","www.jeccg.com","jeecgos@163.com"))
.license("The Apache License, Version 2.0")
.licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html")
.build();
}
/**
* 新增 securityContexts 保持登录状态
*/
private List<SecurityContext> securityContexts() {
return new ArrayList(
Collections.singleton(SecurityContext.builder()
.securityReferences(defaultAuth())
.forPaths(PathSelectors.regex("^(?!auth).*$"))
.build())
);
}
private List<SecurityReference> defaultAuth() {
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
return new ArrayList(
Collections.singleton(new SecurityReference(CommonConstant.X_ACCESS_TOKEN, authorizationScopes)));
}
/**
* 解决springboot2.6 和springfox不兼容问题
* @return
*/
@Bean
public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
return new BeanPostProcessor() {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
}
return bean;
}
private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {
List<T> copy = mappings.stream()
.filter(mapping -> mapping.getPatternParser() == null)
.collect(Collectors.toList());
mappings.clear();
mappings.addAll(copy);
}
@SuppressWarnings("unchecked")
private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {
try {
Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
field.setAccessible(true);
return (List<RequestMappingInfoHandlerMapping>) field.get(bean);
} catch (IllegalArgumentException | IllegalAccessException e) {
throw new IllegalStateException(e);
}
}
};
}
}
//package org.jeecg.config;
//
// 已使用swagger3config平替
//import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
//import io.swagger.annotations.ApiOperation;
//import org.jeecg.common.constant.CommonConstant;
//import org.springframework.beans.BeansException;
//import org.springframework.beans.factory.config.BeanPostProcessor;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//import org.springframework.context.annotation.Import;
//import org.springframework.util.ReflectionUtils;
//import org.springframework.web.bind.annotation.RestController;
//import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
//import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
//import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
//import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
//import springfox.documentation.builders.ApiInfoBuilder;
//import springfox.documentation.builders.ParameterBuilder;
//import springfox.documentation.builders.PathSelectors;
//import springfox.documentation.builders.RequestHandlerSelectors;
//import springfox.documentation.oas.annotations.EnableOpenApi;
//import springfox.documentation.schema.ModelRef;
//import springfox.documentation.service.*;
//import springfox.documentation.spi.DocumentationType;
//import springfox.documentation.spi.service.contexts.SecurityContext;
//import springfox.documentation.spring.web.plugins.Docket;
//import springfox.documentation.spring.web.plugins.WebFluxRequestHandlerProvider;
//import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider;
//import springfox.documentation.swagger2.annotations.EnableSwagger2;
//
//import java.lang.reflect.Field;
//import java.util.ArrayList;
//import java.util.Collections;
//import java.util.List;
//import java.util.stream.Collectors;
//
///**
// * @Author scott
// */
//@Configuration
//@EnableSwagger2 //开启 Swagger2
//@EnableKnife4j //开启 knife4j可以不写
//@Import(BeanValidatorPluginsConfiguration.class)
//public class Swagger2Config implements WebMvcConfigurer {
//
// /**
// *
// * 显示swagger-ui.html文档展示页还必须注入swagger资源
// *
// * @param registry
// */
// @Override
// public void addResourceHandlers(ResourceHandlerRegistry registry) {
// registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
// registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
// registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
// }
//
// /**
// * swagger2的配置文件这里可以配置swagger2的一些基本的内容比如扫描的包等等
// *
// * @return Docket
// */
// @Bean(value = "defaultApi2")
// public Docket defaultApi2() {
// return new Docket(DocumentationType.SWAGGER_2)
// .apiInfo(apiInfo())
// .select()
// //此包路径下的类,才生成接口文档
// .apis(RequestHandlerSelectors.basePackage("org.jeecg"))
// //加了ApiOperation注解的类才生成接口文档
// .apis(RequestHandlerSelectors.withClassAnnotation(RestController.class))
// .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
// .paths(PathSelectors.any())
// .build()
// .securitySchemes(Collections.singletonList(securityScheme()))
// .securityContexts(securityContexts())
// .globalOperationParameters(setHeaderToken());
// }
//
// /***
// * oauth2配置
// * 需要增加swagger授权回调地址
// * http://localhost:8888/webjars/springfox-swagger-ui/o2c.html
// * @return
// */
// @Bean
// SecurityScheme securityScheme() {
// return new ApiKey(CommonConstant.X_ACCESS_TOKEN, CommonConstant.X_ACCESS_TOKEN, "header");
// }
// /**
// * JWT token
// * @return
// */
// private List<Parameter> setHeaderToken() {
// ParameterBuilder tokenPar = new ParameterBuilder();
// List<Parameter> pars = new ArrayList<>();
// tokenPar.name(CommonConstant.X_ACCESS_TOKEN).description("token").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
// pars.add(tokenPar.build());
// return pars;
// }
//
// /**
// * api文档的详细信息函数,注意这里的注解引用的是哪个
// *
// * @return
// */
// private ApiInfo apiInfo() {
// return new ApiInfoBuilder()
// // //大标题
// .title("JeecgBoot 后台服务API接口文档")
// // 版本号
// .version("1.0")
//// .termsOfServiceUrl("NO terms of service")
// // 描述
// .description("后台API接口")
// // 作者
// .contact(new Contact("北京国炬信息技术有限公司","www.jeccg.com","jeecgos@163.com"))
// .license("The Apache License, Version 2.0")
// .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html")
// .build();
// }
//
// /**
// * 新增 securityContexts 保持登录状态
// */
// private List<SecurityContext> securityContexts() {
// return new ArrayList(
// Collections.singleton(SecurityContext.builder()
// .securityReferences(defaultAuth())
// .forPaths(PathSelectors.regex("^(?!auth).*$"))
// .build())
// );
// }
//
// private List<SecurityReference> defaultAuth() {
// AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
// AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
// authorizationScopes[0] = authorizationScope;
// return new ArrayList(
// Collections.singleton(new SecurityReference(CommonConstant.X_ACCESS_TOKEN, authorizationScopes)));
// }
//
// /**
// * 解决springboot2.6 和springfox不兼容问题
// * @return
// */
// @Bean
// public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
// return new BeanPostProcessor() {
//
// @Override
// public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
// if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
// customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
// }
// return bean;
// }
//
// private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {
// List<T> copy = mappings.stream()
// .filter(mapping -> mapping.getPatternParser() == null)
// .collect(Collectors.toList());
// mappings.clear();
// mappings.addAll(copy);
// }
//
// @SuppressWarnings("unchecked")
// private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {
// try {
// Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
// field.setAccessible(true);
// return (List<RequestMappingInfoHandlerMapping>) field.get(bean);
// } catch (IllegalArgumentException | IllegalAccessException e) {
// throw new IllegalStateException(e);
// }
// }
// };
// }
//
//
//}

View File

@ -0,0 +1,59 @@
package org.jeecg.config;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Paths;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.jeecg.common.constant.CommonConstant;
import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class Swagger3Config implements WebMvcConfigurer {
/**
*
* 显示swagger-ui.html文档展示页还必须注入swagger资源
*
* @param registry
*/
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
@Bean
public GroupedOpenApi swaggerOpenApi() {
return GroupedOpenApi.builder()
.group("default")
.packagesToScan("org.jeecg")
// 剔除以下几个包路径的接口生成文档
.packagesToExclude("org.jeecg.modules.drag", "org.jeecg.modules.online", "org.jeecg.modules.jmreport")
// 加了Operation注解的方法才生成接口文档
.addOpenApiMethodFilter(method -> method.isAnnotationPresent(Operation.class))
.build();
}
@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.info(new Info()
.title("JeecgBoot 后台服务API接口文档")
.version("1.0")
.contact(new Contact().name("北京国炬信息技术有限公司").url("www.jeccg.com").email("jeecgos@163.com"))
.description( "后台API接口")
.termsOfService("NO terms of service")
.license(new License().name("Apache 2.0").url("http://www.apache.org/licenses/LICENSE-2.0.html"))
);
}
}

View File

@ -0,0 +1,19 @@
package org.jeecg.config;
import io.undertow.server.DefaultByteBufferPool;
import io.undertow.websockets.jsr.WebSocketDeploymentInfo;
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.stereotype.Component;
@Component
public class UndertowCustomizer implements WebServerFactoryCustomizer<UndertowServletWebServerFactory> {
@Override
public void customize(UndertowServletWebServerFactory factory) {
factory.addDeploymentInfoCustomizers(deploymentInfo -> {
WebSocketDeploymentInfo webSocketDeploymentInfo = new WebSocketDeploymentInfo();
webSocketDeploymentInfo.setBuffers(new DefaultByteBufferPool(false, 1024));
deploymentInfo.addServletContextAttribute("io.undertow.websockets.jsr.WebSocketDeploymentInfo", webSocketDeploymentInfo);
});
}
}

View File

@ -10,12 +10,15 @@ import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.prometheus.PrometheusMeterRegistry;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.actuate.trace.http.InMemoryHttpTraceRepository;
import org.springframework.boot.actuate.autoconfigure.metrics.MeterRegistryCustomizer;
import org.springframework.boot.actuate.web.exchanges.InMemoryHttpExchangeRepository;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
@ -30,7 +33,6 @@ import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
@ -133,8 +135,11 @@ public class WebMvcConfiguration implements WebMvcConfigurer {
* https://blog.csdn.net/u013810234/article/details/110097201
*/
@Bean
public InMemoryHttpTraceRepository getInMemoryHttpTrace(){
return new InMemoryHttpTraceRepository();
public InMemoryHttpExchangeRepository getInMemoryHttpTrace(){
InMemoryHttpExchangeRepository repository = new InMemoryHttpExchangeRepository();
// 默认保存1000条http请求记录
repository.setCapacity(1000);
return repository;
}

View File

@ -31,7 +31,7 @@ public class WebSocketConfig {
FilterRegistrationBean bean = new FilterRegistrationBean();
bean.setFilter(websocketFilter());
//TODO 临时注释掉测试下线上socket总断的问题
bean.addUrlPatterns("/websocket/*","/eoaSocket/*","/eoaNewChatSocket/*", "/newsWebsocket/*", "/vxeSocket/*");
bean.addUrlPatterns("/taskCountSocket/*", "/websocket/*","/eoaSocket/*","/eoaNewChatSocket/*", "/newsWebsocket/*", "/vxeSocket/*");
return bean;
}

View File

@ -3,8 +3,8 @@ package org.jeecg.config.filter;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.config.sign.util.BodyReaderHttpServletRequestWrapper;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;
/**

View File

@ -7,9 +7,9 @@ import org.jeecg.common.util.SpringContextUtils;
import org.jeecg.common.util.TokenUtils;
import org.jeecg.common.util.oConvertUtils;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
/**

View File

@ -17,9 +17,9 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Set;

View File

@ -11,7 +11,7 @@ import org.jeecg.common.util.SpringContextUtils;
import org.jeecg.config.mybatis.ThreadLocalDataHelper;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
/**

View File

@ -6,8 +6,8 @@ import org.apache.commons.lang3.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
/**
* 动态数据源切换拦截器

View File

@ -0,0 +1,16 @@
package org.jeecg.config.shiro;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 免认证注解认证系统结合spring MVC的@RequestMapping获取请求路径进行免登录配置
* @author eightmonth@qq.com
* @date 2024/2/28 9:58
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface IgnoreAuth {
}

View File

@ -1,5 +1,6 @@
package org.jeecg.config.shiro;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
@ -17,21 +18,26 @@ import org.jeecg.config.shiro.filters.CustomShiroFilterFactoryBean;
import org.jeecg.config.shiro.filters.JwtFilter;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.*;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.env.Environment;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.filter.DelegatingFilterProxy;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import javax.annotation.Resource;
import javax.servlet.Filter;
import jakarta.annotation.Resource;
import jakarta.servlet.Filter;
import jakarta.servlet.DispatcherType;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author: Scott
@ -41,6 +47,8 @@ import java.util.stream.Collectors;
@Slf4j
@Configuration
// 免认证注解 @IgnoreAuth 注解生效范围配置
@ComponentScan(basePackages = {"org.jeecg"})
public class ShiroConfig {
@Resource
@ -51,7 +59,6 @@ public class ShiroConfig {
private JeecgBaseConfig jeecgBaseConfig;
@Autowired(required = false)
private RedisProperties redisProperties;
/**
* Filter Chain定义说明
*
@ -76,6 +83,7 @@ public class ShiroConfig {
}
}
}
// 配置不会被拦截的链接 顺序判断
filterChainDefinitionMap.put("/sys/cas/client/validateLogin", "anon"); //cas验证登录
filterChainDefinitionMap.put("/sys/randomImage/**", "anon"); //登录验证码接口排除
@ -94,6 +102,9 @@ public class ShiroConfig {
filterChainDefinitionMap.put("/auth/2step-code", "anon");//登录验证码
filterChainDefinitionMap.put("/sys/common/static/**", "anon");//图片预览 &下载文件不限制token
filterChainDefinitionMap.put("/sys/common/pdf/**", "anon");//pdf预览
//filterChainDefinitionMap.put("/sys/common/view/**", "anon");//图片预览不限制token
//filterChainDefinitionMap.put("/sys/common/download/**", "anon");//文件下载不限制token
filterChainDefinitionMap.put("/generic/**", "anon");//pdf预览需要文件
filterChainDefinitionMap.put("/sys/getLoginQrcode/**", "anon"); //登录二维码
@ -101,6 +112,7 @@ public class ShiroConfig {
filterChainDefinitionMap.put("/sys/checkAuth", "anon"); //授权接口排除
//update-begin--Author:scott Date:20221116 for排除静态资源后缀
filterChainDefinitionMap.put("/", "anon");
filterChainDefinitionMap.put("/doc.html", "anon");
filterChainDefinitionMap.put("/**/*.js", "anon");
@ -115,16 +127,17 @@ public class ShiroConfig {
filterChainDefinitionMap.put("/**/*.ttf", "anon");
filterChainDefinitionMap.put("/**/*.woff", "anon");
filterChainDefinitionMap.put("/**/*.woff2", "anon");
//update-end--Author:scott Date:20221116 for排除静态资源后缀
filterChainDefinitionMap.put("/druid/**", "anon");
filterChainDefinitionMap.put("/swagger-ui.html", "anon");
filterChainDefinitionMap.put("/swagger**/**", "anon");
filterChainDefinitionMap.put("/webjars/**", "anon");
filterChainDefinitionMap.put("/v2/**", "anon");
// 企业微信证书排除
filterChainDefinitionMap.put("/WW_verify*", "anon");
filterChainDefinitionMap.put("/v3/**", "anon");
// update-begin--Author:sunjianlei Date:20210510 for排除消息通告查看详情页面用于第三方APP
filterChainDefinitionMap.put("/sys/annountCement/show/**", "anon");
// update-end--Author:sunjianlei Date:20210510 for排除消息通告查看详情页面用于第三方APP
//积木报表排除
filterChainDefinitionMap.put("/jmreport/**", "anon");
@ -155,10 +168,20 @@ public class ShiroConfig {
//测试模块排除
filterChainDefinitionMap.put("/test/seata/**", "anon");
// update-begin--author:liusq Date:20230522 for[issues/4829]访问不存在的url时会提示Token失效请重新登录呢
//错误路径排除
filterChainDefinitionMap.put("/error", "anon");
// update-end--author:liusq Date:20230522 for[issues/4829]访问不存在的url时会提示Token失效请重新登录呢
// 企业微信证书排除
filterChainDefinitionMap.put("/WW_verify*", "anon");
// 通过注解免登录url
List<String> ignoreAuthUrlList = collectIgnoreAuthUrl();
if (!CollectionUtils.isEmpty(ignoreAuthUrlList)) {
for (String url : ignoreAuthUrlList) {
filterChainDefinitionMap.put(url, "anon");
}
}
// 添加自己的过滤器并且取名为jwt
Map<String, Filter> filterMap = new HashMap<String, Filter>(1);
@ -176,6 +199,20 @@ public class ShiroConfig {
return shiroFilterFactoryBean;
}
//update-begin---author:chenrui ---date:20240126 for【QQYUN-7932】AI助手------------
@Bean
public FilterRegistrationBean shiroFilterRegistration() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new DelegatingFilterProxy("shiroFilterFactoryBean"));
registration.setEnabled(true);
registration.addUrlPatterns("/*");
//支持异步
registration.setAsyncSupported(true);
registration.setDispatcherTypes(DispatcherType.REQUEST, DispatcherType.ASYNC);
return registration;
}
//update-end---author:chenrui ---date:20240126 for【QQYUN-7932】AI助手------------
@Bean("securityManager")
public DefaultWebSecurityManager securityManager(ShiroRealm myRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
@ -253,8 +290,7 @@ public class ShiroConfig {
public IRedisManager redisManager() {
log.info("===============(2)创建RedisManager,连接Redis..");
IRedisManager manager;
// sentinel cluster redis
// sentinel cluster redis【issues/5569】shiro集成 redis 不支持 sentinel 方式部署的redis集群 #5569
if (Objects.nonNull(redisProperties)
&& Objects.nonNull(redisProperties.getSentinel())
&& !CollectionUtils.isEmpty(redisProperties.getSentinel().getNodes())) {
@ -266,6 +302,7 @@ public class ShiroConfig {
return sentinelManager;
}
// redis 单机支持,在集群为空,或者集群无机器时候使用 add by jzyadmin@163.com
if (lettuceConnectionFactory.getClusterConfiguration() == null || lettuceConnectionFactory.getClusterConfiguration().getClusterNodes().isEmpty()) {
RedisManager redisManager = new RedisManager();
@ -298,4 +335,74 @@ public class ShiroConfig {
return manager;
}
@SneakyThrows
public List<String> collectIgnoreAuthUrl() {
List<String> ignoreAuthUrls = new ArrayList<>();
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
provider.addIncludeFilter(new AnnotationTypeFilter(RestController.class));
// 获取当前类的扫描注解的配置
Set<BeanDefinition> components = new HashSet<>();
for (String basePackage : AnnotationUtils.getAnnotation(ShiroConfig.class, ComponentScan.class).basePackages()) {
components.addAll(provider.findCandidateComponents(basePackage));
}
// 逐个匹配获取免认证路径
for (BeanDefinition component : components) {
String beanClassName = component.getBeanClassName();
Class<?> clazz = Class.forName(beanClassName);
RequestMapping base = clazz.getAnnotation(RequestMapping.class);
String[] baseUrl = {};
if (Objects.nonNull(base)) {
baseUrl = base.value();
}
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(RequestMapping.class)) {
RequestMapping requestMapping = method.getAnnotation(RequestMapping.class);
String[] uri = requestMapping.value();
ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
} else if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(GetMapping.class)) {
GetMapping requestMapping = method.getAnnotation(GetMapping.class);
String[] uri = requestMapping.value();
ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
} else if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(PostMapping.class)) {
PostMapping requestMapping = method.getAnnotation(PostMapping.class);
String[] uri = requestMapping.value();
ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
} else if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(PutMapping.class)) {
PutMapping requestMapping = method.getAnnotation(PutMapping.class);
String[] uri = requestMapping.value();
ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
} else if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(DeleteMapping.class)) {
DeleteMapping requestMapping = method.getAnnotation(DeleteMapping.class);
String[] uri = requestMapping.value();
ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
} else if (method.isAnnotationPresent(IgnoreAuth.class) && method.isAnnotationPresent(PatchMapping.class)) {
PatchMapping requestMapping = method.getAnnotation(PatchMapping.class);
String[] uri = requestMapping.value();
ignoreAuthUrls.addAll(rebuildUrl(baseUrl, uri));
}
}
}
return ignoreAuthUrls;
}
private List<String> rebuildUrl(String[] bases, String[] uris) {
List<String> urls = new ArrayList<>();
for (String base : bases) {
for (String uri : uris) {
urls.add(prefix(base)+prefix(uri));
}
}
return urls;
}
private String prefix(String seg) {
return seg.startsWith("/") ? seg : "/"+seg;
}
}

View File

@ -22,8 +22,8 @@ import org.jeecg.common.util.oConvertUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import java.util.Set;
/**
@ -62,9 +62,11 @@ public class ShiroRealm extends AuthorizingRealm {
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
log.debug("===============Shiro权限认证开始============ [ roles、permissions]==========");
String username = null;
String userId = null;
if (principals != null) {
LoginUser sysUser = (LoginUser) principals.getPrimaryPrincipal();
username = sysUser.getUsername();
userId = sysUser.getId();
}
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
@ -74,7 +76,7 @@ public class ShiroRealm extends AuthorizingRealm {
info.setRoles(roleSet);
// 设置用户拥有的权限集合比如“sys:role:add,sys:user:add”
Set<String> permissionSet = commonApi.queryUserAuths(username);
Set<String> permissionSet = commonApi.queryUserAuths(userId);
info.addStringPermissions(permissionSet);
//System.out.println(permissionSet);
log.info("===============Shiro权限认证成功==============");

View File

@ -12,7 +12,7 @@ import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.apache.shiro.mgt.SecurityManager;
import org.springframework.beans.factory.BeanInitializationException;
import javax.servlet.Filter;
import jakarta.servlet.Filter;
import java.util.Map;
/**

View File

@ -12,10 +12,10 @@ import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
/**
* @Description: 鉴权登录拦截器

View File

@ -1,9 +1,9 @@
package org.jeecg.config.shiro.filters;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;
import lombok.extern.slf4j.Slf4j;

View File

@ -10,7 +10,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;
import jakarta.annotation.Resource;
/**
* 签名 拦截器配置

View File

@ -4,8 +4,8 @@ package org.jeecg.config.sign.interceptor;
import java.io.PrintWriter;
import java.util.SortedMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;

View File

@ -1,10 +1,10 @@
package org.jeecg.config.sign.util;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import jakarta.servlet.ReadListener;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import java.io.*;
import java.nio.charset.Charset;

View File

@ -10,7 +10,7 @@ import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.SymbolConstant;
@ -172,7 +172,11 @@ public class HttpUtils {
String[] params = param.split("&");
for (String s : params) {
int index = s.indexOf("=");
result.put(s.substring(0, index), s.substring(index + 1));
//update-begin---author:chenrui ---date:20240222 for[issues/5879]数据查询传ds=“”造成的异常------------
if (index != -1) {
result.put(s.substring(0, index), s.substring(index + 1));
}
//update-end---author:chenrui ---date:20240222 for[issues/5879]数据查询传ds=“”造成的异常------------
}
return result;
}
@ -196,7 +200,11 @@ public class HttpUtils {
String[] params = param.split("&");
for (String s : params) {
int index = s.indexOf("=");
result.put(s.substring(0, index), s.substring(index + 1));
//update-begin---author:chenrui ---date:20240222 for[issues/5879]数据查询传ds=“”造成的异常------------
if (index != -1) {
result.put(s.substring(0, index), s.substring(index + 1));
}
//update-end---author:chenrui ---date:20240222 for[issues/5879]数据查询传ds=“”造成的异常------------
}
return result;
}

View File

@ -35,4 +35,5 @@ public class Firewall {
public void setLowCodeMode(String lowCodeMode) {
this.lowCodeMode = lowCodeMode;
}
}

View File

@ -12,8 +12,8 @@ import org.jeecg.common.util.SpringContextUtils;
import org.jeecg.common.util.oConvertUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import java.util.*;
/**

View File

@ -0,0 +1,2 @@
org.springframework.boot.SpringApplicationRunListener=\
org.jeecg.config.DruidWallConfigRegister

View File

@ -56,7 +56,7 @@
</div>
<div style="width: 600px; margin: 0 auto; margin-top: 50px; font-size: 12px; -webkit-font-smoothing: subpixel-antialiased; text-size-adjust: 100%;">
<p style="text-align: center; line-height: 20.4px; text-size-adjust: 100%; font-family: 'Microsoft YaHei'!important; padding: 0px !important; margin: 0px !important; color: #7e8890 !important;">
<span class="appleLinks">Copyright © 2023-2024 北京国炬科技股份有限公司. 保留所有权利。</span>
<span class="appleLinks">Copyright © 2023-2024 北京国炬信息技术有限公司. 保留所有权利。</span>
</p>
<p style="text-align: center;line-height: 20.4px; text-size-adjust: 100%; font-family: 'Microsoft YaHei'!important; padding: 0px !important; margin: 0px; color: #7e8890 !important; margin-top: 10px;">
<span class="appleLinks">邮件由系统自动发送,请勿直接回复本邮件!</span>

View File

@ -6,7 +6,10 @@
<body>
<div class="box-content">
<div class="info-top">
<img src="https://jeecgdev.oss-cn-beijing.aliyuncs.com/temp/logo(1)_1697180761742.png" style="float: left; margin: 0 10px 0 0; width: 32px;height:32px" /><div style="color:#fff"><strong>【重要】新数据提醒</strong></div>
<img src="https://qiaoqiaoyun.oss-cn-beijing.aliyuncs.com/site/qqyunemaillogo.png" style="width: 35px;height:35px; background: #5e8ee5; border-radius: 5px;" />
<div style="color:#fff;">
<strong>【重要】新数据提醒</strong>
</div>
</div>
<div class="info-wrap">
<div class="tips" style="padding:15px;">
@ -23,12 +26,12 @@
<a style="color: #006eff;" href="${moreLink}" target="_blank" rel="noopener">[查看所有数据]</a>
</p>
</div>
<div class="footer">北京国炬平台</div>
<div class="footer">敲敲云平台</div>
<div class="footer" id="currentTime"></div>
</div>
<div style="width: 600px; margin: 0 auto; margin-top: 50px; font-size: 12px; -webkit-font-smoothing: subpixel-antialiased; text-size-adjust: 100%;">
<p style="text-align: center; line-height: 20.4px; text-size-adjust: 100%; font-family: 'Microsoft YaHei'!important; padding: 0px !important; margin: 0px !important; color: #7e8890 !important;">
<span class="appleLinks">Copyright © 2023-2024 北京国炬科技股份有限公司. 保留所有权利。</span>
<span class="appleLinks">Copyright © 2023-2024 北京敲敲云科技有限公司. 保留所有权利。</span>
</p>
<p style="text-align: center;line-height: 20.4px; text-size-adjust: 100%; font-family: 'Microsoft YaHei'!important; padding: 0px !important; margin: 0px; color: #7e8890 !important; margin-top: 10px;">
<span class="appleLinks">邮件由系统自动发送,请勿直接回复本邮件!</span>
@ -46,6 +49,8 @@
}
.info-top{
display: flex;
align-items: center;
padding: 15px 25px;
border-top-left-radius: 10px;
border-top-right-radius: 10px;

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-boot-parent</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.6.1</version>
<version>3.6.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -16,6 +16,12 @@
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-base-core</artifactId>
</dependency>
<!-- chatgpt -->
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-starter-chatgpt</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -8,7 +8,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import jakarta.annotation.Resource;
/**
* 服务端提供方——feign接口
@ -24,7 +24,7 @@ public class JcloudDemoProviderController {
private JcloudDemoService jcloudDemoService;
@GetMapping("/getMessage")
public String getMessage(@RequestParam String name) {
public String getMessage(@RequestParam(name = "name") String name) {
String msg = jcloudDemoService.getMessage(name);
log.info(" 微服务被调用:{} ",msg);
return msg;

View File

@ -0,0 +1,34 @@
package org.jeecg.modules.demo.gpt.cache;
import cn.hutool.cache.CacheUtil;
import cn.hutool.cache.impl.TimedCache;
import cn.hutool.core.date.DateUnit;
//update-begin---author:chenrui ---date:20240126 for【QQYUN-7932】AI助手------------
/**
* 聊天记录本地缓存
* @author chenrui
* @date 2024/1/26 20:06
*/
public class LocalCache {
/**
* 缓存时长
*/
public static final long TIMEOUT = 5 * DateUnit.MINUTE.getMillis();
/**
* 清理间隔
*/
private static final long CLEAN_TIMEOUT = 5 * DateUnit.MINUTE.getMillis();
/**
* 缓存对象
*/
public static final TimedCache<String, Object> CACHE = CacheUtil.newTimedCache(TIMEOUT);
static {
//启动定时任务
CACHE.schedulePrune(CLEAN_TIMEOUT);
}
}
//update-end---author:chenrui ---date:20240126 forQQYUN-7932AI助手------------

View File

@ -0,0 +1,74 @@
package org.jeecg.modules.demo.gpt.controller;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.demo.gpt.service.ChatService;
import org.jeecg.modules.demo.gpt.vo.ChatHistoryVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
//update-begin---author:chenrui ---date:20240126 for【QQYUN-7932】AI助手------------
/**
* @Description: chatGpt-聊天接口
* @Author: chenrui
* @Date: 2024/1/9 16:30
*/
@Controller
@RequestMapping("/ai/chat")
public class ChatController {
@Autowired
ChatService chatService;
/**
* 创建sse连接
*
* @return
*/
@GetMapping(value = "/send")
public SseEmitter createConnect(@RequestParam(name = "topicId", required = false) String topicId, @RequestParam(name = "message", required = true) String message) {
SseEmitter sse = chatService.createChat();
chatService.sendMessage(topicId, message);
return sse;
}
//update-begin---author:chenrui ---date:20240223 for[QQYUN-8225]聊天记录保存------------
/**
* 保存聊天记录
* @param chatHistoryVO
* @return
* @author chenrui
* @date 2024/2/22 13:54
*/
@PostMapping(value = "/history/save")
@ResponseBody
public Result<?> saveHistory(@RequestBody ChatHistoryVO chatHistoryVO) {
return chatService.saveHistory(chatHistoryVO);
}
/**
* 查询聊天记录
* @return
* @author chenrui
* @date 2024/2/22 14:03
*/
@GetMapping(value = "/history/get")
@ResponseBody
public Result<ChatHistoryVO> getHistoryByTopic() {
return chatService.getHistoryByTopic();
}
//update-end---author:chenrui ---date:20240223 for[QQYUN-8225]聊天记录保存------------
/**
* 关闭连接
*/
@GetMapping(value = "/close")
public void closeConnect() {
chatService.closeChat();
}
}
//update-end---author:chenrui ---date:20240126 for【QQYUN-7932】AI助手------------

View File

@ -0,0 +1,136 @@
package org.jeecg.modules.demo.gpt.listeners;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.unfbx.chatgpt.entity.chat.ChatCompletionResponse;
import com.unfbx.chatgpt.entity.chat.Message;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.sse.EventSource;
import okhttp3.sse.EventSourceListener;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.util.Objects;
//update-begin---author:chenrui ---date:20240126 for【QQYUN-7932】AI助手------------
/**
* OpenAI的SSE监听
* @author chenrui
* @date 2024/1/26 20:06
*/
@Slf4j
public class OpenAISSEEventSourceListener extends EventSourceListener {
private long tokens;
private SseEmitter sseEmitter;
private String topicId;
public OpenAISSEEventSourceListener(SseEmitter sseEmitter) {
this.sseEmitter = sseEmitter;
}
public OpenAISSEEventSourceListener(String topicId,SseEmitter sseEmitter){
this.topicId = topicId;
this.sseEmitter = sseEmitter;
}
/**
* {@inheritDoc}
*/
@Override
public void onOpen(@NotNull EventSource eventSource, @NotNull Response response) {
log.info("OpenAI建立sse连接...");
}
/**
* {@inheritDoc}
*/
@SneakyThrows
@Override
public void onEvent(@NotNull EventSource eventSource, String id, String type, @NotNull String data) {
log.debug("OpenAI返回数据{}", data);
tokens += 1;
if (data.equals("[DONE]")) {
log.info("OpenAI返回数据结束了");
sseEmitter.send(SseEmitter.event()
.id("[TOKENS]")
.data("<br/><br/>tokens" + tokens())
.reconnectTime(3000));
sseEmitter.send(SseEmitter.event()
.id("[DONE]")
.data("[DONE]")
.reconnectTime(3000));
// 传输完成后自动关闭sse
sseEmitter.complete();
return;
}
ObjectMapper mapper = new ObjectMapper();
ChatCompletionResponse completionResponse = mapper.readValue(data, ChatCompletionResponse.class); // 读取Json
try {
sseEmitter.send(SseEmitter.event()
.id(this.topicId)
.data(completionResponse.getChoices().get(0).getDelta())
.reconnectTime(3000));
} catch (Exception e) {
log.error(e.getMessage(),e);
eventSource.cancel();
}
}
@Override
public void onClosed(@NotNull EventSource eventSource) {
log.info("流式输出返回值总共{}tokens", tokens() - 2);
log.info("OpenAI关闭sse连接...");
}
@SneakyThrows
@Override
public void onFailure(@NotNull EventSource eventSource, Throwable t, Response response) {
String errMsg = "";
ResponseBody body = null == response ? null:response.body();
if (Objects.nonNull(body)) {
log.error("OpenAI sse连接异常data{},异常:{}", body.string(), t.getMessage());
errMsg = body.string();
} else {
log.error("OpenAI sse连接异常data{},异常:{}", response, t.getMessage());
errMsg = t.getMessage();
}
eventSource.cancel();
sseEmitter.send(SseEmitter.event()
.id("[ERR]")
.data(Message.builder().content(explainErr(errMsg)).build())
.reconnectTime(3000));
sseEmitter.send(SseEmitter.event()
.id("[DONE]")
.data("[DONE]")
.reconnectTime(3000));
sseEmitter.complete();
}
private String explainErr(String errMsg){
if(StringUtils.isEmpty(errMsg)){
return "";
}
if(errMsg.contains("Rate limit")){
return "请求频率太快了,请等待20秒再试.";
}
return errMsg;
}
/**
* tokens
* @return
*/
public long tokens() {
return tokens;
}
}
//update-end---author:chenrui ---date:20240126 forQQYUN-7932AI助手------------

View File

@ -0,0 +1,56 @@
package org.jeecg.modules.demo.gpt.service;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.demo.gpt.vo.ChatHistoryVO;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
//update-begin---author:chenrui ---date:20240126 for【QQYUN-7932】AI助手------------
/**
* AI助手聊天Service
* @author chenrui
* @date 2024/1/26 20:08
*/
public interface ChatService {
/**
* 创建SSE
* @return
*/
SseEmitter createChat();
/**
* 关闭SSE
*/
void closeChat();
/**
* 客户端发送消息到服务端
*
* @param topicId
* @param message
* @author chenrui
* @date 2024/1/26 20:01
*/
void sendMessage(String topicId, String message);
//update-begin---author:chenrui ---date:20240223 for[QQYUN-8225]聊天记录保存------------
/**
* 保存聊天记录
* @param chatHistoryVO
* @return
* @author chenrui
* @date 2024/2/22 13:37
*/
Result<?> saveHistory(ChatHistoryVO chatHistoryVO);
/**
* 查询聊天记录
* @return
* @author chenrui
* @date 2024/2/22 13:59
*/
Result<ChatHistoryVO> getHistoryByTopic();
//update-end---author:chenrui ---date:20240223 for[QQYUN-8225]聊天记录保存------------
}
//update-end---author:chenrui ---date:20240126 forQQYUN-7932AI助手------------

View File

@ -0,0 +1,199 @@
package org.jeecg.modules.demo.gpt.service.impl;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONArray;
import com.unfbx.chatgpt.OpenAiStreamClient;
import com.unfbx.chatgpt.entity.chat.ChatCompletion;
import com.unfbx.chatgpt.entity.chat.Message;
import com.unfbx.chatgpt.exception.BaseException;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.SpringContextUtils;
import org.jeecg.common.util.UUIDGenerator;
import org.jeecg.modules.demo.gpt.cache.LocalCache;
import org.jeecg.modules.demo.gpt.listeners.OpenAISSEEventSourceListener;
import org.jeecg.modules.demo.gpt.service.ChatService;
import org.jeecg.modules.demo.gpt.vo.ChatHistoryVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
//update-begin---author:chenrui ---date:20240126 for【QQYUN-7932】AI助手------------
/**
* AI助手聊天Service
* @author chenrui
* @date 2024/1/26 20:07
*/
@Service
@Slf4j
public class ChatServiceImpl implements ChatService {
//update-begin---author:chenrui ---date:20240223 for[QQYUN-8225]聊天记录保存------------
private static final String CACHE_KEY_PREFIX = "ai:chart:";
/**
*
*/
private static final String CACHE_KEY_MSG_CONTEXT = "msg_content";
/**
*
*/
private static final String CACHE_KEY_MSG_HISTORY = "msg_history";
@Autowired
RedisTemplate redisTemplate;
//update-end---author:chenrui ---date:20240223 for[QQYUN-8225]聊天记录保存------------
private OpenAiStreamClient openAiStreamClient = null;
//update-begin---author:chenrui ---date:20240131 for[QQYUN-8212]fix 没有配置启动报错------------
public ChatServiceImpl() {
try {
this.openAiStreamClient = SpringContextUtils.getBean(OpenAiStreamClient.class);
} catch (Exception ignored) {
}
}
/**
* 防止client不能成功注入
* @return
* @author chenrui
* @date 2024/2/3 23:08
*/
private OpenAiStreamClient ensureClient(){
if(null == this.openAiStreamClient){
this.openAiStreamClient = SpringContextUtils.getBean(OpenAiStreamClient.class);
}
return this.openAiStreamClient;
}
//update-end---author:chenrui ---date:20240131 for[QQYUN-8212]fix 没有配置启动报错------------
private String getUserId() {
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
return sysUser.getId();
}
@Override
public SseEmitter createChat() {
String uid = getUserId();
//默认30秒超时,设置为0L则永不超时
SseEmitter sseEmitter = new SseEmitter(-0L);
//完成后回调
sseEmitter.onCompletion(() -> {
log.info("[{}]结束连接...................",uid);
LocalCache.CACHE.remove(uid);
});
//超时回调
sseEmitter.onTimeout(() -> {
log.info("[{}]连接超时...................", uid);
});
//异常回调
sseEmitter.onError(
throwable -> {
try {
log.info("[{}]连接异常,{}", uid, throwable.toString());
sseEmitter.send(SseEmitter.event()
.id(uid)
.name("发生异常!")
.data(Message.builder().content("发生异常请重试!").build())
.reconnectTime(3000));
LocalCache.CACHE.put(uid, sseEmitter);
} catch (IOException e) {
log.error(e.getMessage(),e);
}
}
);
try {
sseEmitter.send(SseEmitter.event().reconnectTime(5000));
} catch (IOException e) {
log.error(e.getMessage(),e);
}
LocalCache.CACHE.put(uid, sseEmitter);
log.info("[{}]创建sse连接成功", uid);
return sseEmitter;
}
@Override
public void closeChat() {
String uid = getUserId();
SseEmitter sse = (SseEmitter) LocalCache.CACHE.get(uid);
if (sse != null) {
sse.complete();
//移除
LocalCache.CACHE.remove(uid);
}
}
@Override
public void sendMessage(String topicId, String message) {
String uid = getUserId();
if (StrUtil.isBlank(message)) {
log.info("参数异常message为null");
throw new BaseException("参数异常message不能为空~");
}
if (StrUtil.isBlank(topicId)) {
topicId = UUIDGenerator.generate();
}
//update-begin---author:chenrui ---date:20240223 for[QQYUN-8225]聊天记录保存------------
log.info("话题id:{}", topicId);
String cacheKey = CACHE_KEY_PREFIX + uid + "_" + topicId;
String messageContext = (String) redisTemplate.opsForHash().get(cacheKey, CACHE_KEY_MSG_CONTEXT);
List<Message> msgHistory = new ArrayList<>();
if (StrUtil.isNotBlank(messageContext)) {
List<Message> messages = JSONArray.parseArray(messageContext, Message.class);
msgHistory = messages == null ? new ArrayList<>() : messages;
}
Message currentMessage = Message.builder().content(message).role(Message.Role.USER).build();
msgHistory.add(currentMessage);
SseEmitter sseEmitter = (SseEmitter) LocalCache.CACHE.get(uid);
if (sseEmitter == null) {
log.info("聊天消息推送失败uid:[{}],没有创建连接,请重试。", uid);
throw new JeecgBootException("聊天消息推送失败uid:[{}],没有创建连接,请重试。~");
}
OpenAISSEEventSourceListener openAIEventSourceListener = new OpenAISSEEventSourceListener(topicId, sseEmitter);
ChatCompletion completion = ChatCompletion
.builder()
.messages(msgHistory)
.model(ChatCompletion.Model.GPT_3_5_TURBO.getName())
.build();
ensureClient().streamChatCompletion(completion, openAIEventSourceListener);
redisTemplate.opsForHash().put(cacheKey, CACHE_KEY_MSG_CONTEXT, JSONUtil.toJsonStr(msgHistory));
//update-end---author:chenrui ---date:20240223 for[QQYUN-8225]聊天记录保存------------
Result.ok(completion.tokens());
}
//update-begin---author:chenrui ---date:20240223 for[QQYUN-8225]聊天记录保存------------
@Override
public Result<?> saveHistory(ChatHistoryVO chatHistoryVO) {
String uid = getUserId();
String cacheKey = CACHE_KEY_PREFIX + CACHE_KEY_MSG_HISTORY + ":" + uid;
redisTemplate.opsForValue().set(cacheKey, chatHistoryVO.getContent());
return Result.OK("保存成功");
}
@Override
public Result<ChatHistoryVO> getHistoryByTopic() {
String uid = getUserId();
String cacheKey = CACHE_KEY_PREFIX + CACHE_KEY_MSG_HISTORY + ":" + uid;
String historyContent = (String) redisTemplate.opsForValue().get(cacheKey);
ChatHistoryVO chatHistoryVO = new ChatHistoryVO();
chatHistoryVO.setContent(historyContent);
return Result.OK(chatHistoryVO);
}
//update-end---author:chenrui ---date:20240223 for[QQYUN-8225]聊天记录保存------------
}
//update-end---author:chenrui ---date:20240126 for【QQYUN-7932】AI助手------------

View File

@ -0,0 +1,25 @@
package org.jeecg.modules.demo.gpt.vo;
import lombok.Data;
import java.io.Serializable;
/**
* @Description: 聊天记录
* @Author: chenrui
* @Date: 2024/2/22 13:36
*/
@Data
public class ChatHistoryVO implements Serializable {
private static final long serialVersionUID = 3238429500037511283L;
/**
* 话题id
*/
String topicId;
/**
* 聊天记录内容
*/
String content;
}

View File

@ -6,8 +6,8 @@ import org.apache.commons.io.IOUtils;
import org.jeecg.common.api.vo.Result;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import javax.swing.filechooser.FileSystemView;
import java.io.File;
import java.io.IOException;

View File

@ -18,7 +18,7 @@ import org.jeecg.modules.demo.mock.vxe.entity.MockEntity;
import org.jeecg.modules.demo.mock.vxe.websocket.VxeSocket;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLDecoder;

View File

@ -6,12 +6,12 @@ import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.VxeSocketConst;
import org.springframework.stereotype.Component;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import jakarta.websocket.OnClose;
import jakarta.websocket.OnMessage;
import jakarta.websocket.OnOpen;
import jakarta.websocket.Session;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

View File

@ -4,13 +4,12 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.mgt.DefaultSecurityManager;
@ -30,8 +29,6 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import reactor.core.publisher.Mono;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
@ -44,7 +41,7 @@ import java.util.List;
* @Version:V2.0
*/
@Slf4j
@Api(tags = "单表DEMO")
@Tag(name = "单表DEMO")
@RestController
@RequestMapping("/test/jeecgDemo")
public class JeecgDemoController extends JeecgController<JeecgDemo, IJeecgDemoService> {
@ -63,7 +60,7 @@ public class JeecgDemoController extends JeecgController<JeecgDemo, IJeecgDemoSe
* @param req
* @return
*/
@ApiOperation(value = "获取Demo数据列表", notes = "获取所有Demo数据列表")
@Operation(summary = "获取所有Demo数据列表")
@GetMapping(value = "/list")
@PermissionData(pageComponent = "jeecg/JeecgDemoList")
public Result<?> list(JeecgDemo jeecgDemo, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo, @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
@ -88,7 +85,7 @@ public class JeecgDemoController extends JeecgController<JeecgDemo, IJeecgDemoSe
*/
@PostMapping(value = "/add")
@AutoLog(value = "添加测试DEMO")
@ApiOperation(value = "添加DEMO", notes = "添加DEMO")
@Operation(summary = "添加DEMO")
public Result<?> add(@RequestBody JeecgDemo jeecgDemo) {
jeecgDemoService.save(jeecgDemo);
return Result.OK("添加成功!");
@ -101,7 +98,7 @@ public class JeecgDemoController extends JeecgController<JeecgDemo, IJeecgDemoSe
* @return
*/
@AutoLog(value = "编辑DEMO", operateType = CommonConstant.OPERATE_TYPE_3)
@ApiOperation(value = "编辑DEMO", notes = "编辑DEMO")
@Operation(summary = "编辑DEMO")
@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
public Result<?> edit(@RequestBody JeecgDemo jeecgDemo) {
jeecgDemoService.updateById(jeecgDemo);
@ -116,7 +113,7 @@ public class JeecgDemoController extends JeecgController<JeecgDemo, IJeecgDemoSe
*/
@AutoLog(value = "删除测试DEMO")
@DeleteMapping(value = "/delete")
@ApiOperation(value = "通过ID删除DEMO", notes = "通过ID删除DEMO")
@Operation(summary = "通过ID删除DEMO")
public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
jeecgDemoService.removeById(id);
return Result.OK("删除成功!");
@ -129,7 +126,7 @@ public class JeecgDemoController extends JeecgController<JeecgDemo, IJeecgDemoSe
* @return
*/
@DeleteMapping(value = "/deleteBatch")
@ApiOperation(value = "批量删除DEMO", notes = "批量删除DEMO")
@Operation(summary = "批量删除DEMO")
public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
this.jeecgDemoService.removeByIds(Arrays.asList(ids.split(",")));
return Result.OK("批量删除成功!");
@ -142,8 +139,8 @@ public class JeecgDemoController extends JeecgController<JeecgDemo, IJeecgDemoSe
* @return
*/
@GetMapping(value = "/queryById")
@ApiOperation(value = "通过ID查询DEMO", notes = "通过ID查询DEMO")
public Result<?> queryById(@ApiParam(name = "id", value = "示例id", required = true) @RequestParam(name = "id", required = true) String id) {
@Operation(summary = "通过ID查询DEMO")
public Result<?> queryById(/*@ApiParam(name = "id", value = "示例id", required = true)*/ @RequestParam(name = "id", required = true) String id) {
JeecgDemo jeecgDemo = jeecgDemoService.getById(id);
return Result.OK(jeecgDemo);
}
@ -475,7 +472,7 @@ public class JeecgDemoController extends JeecgController<JeecgDemo, IJeecgDemoSe
* 测试Mono对象
* @return
*/
@ApiOperation("Mono测试")
@Operation(summary = "Mono测试")
@GetMapping(value ="/test")
public Mono<String> test() {
//解决shiro报错No SecurityManager accessible to the calling code, either bound to the org.apache.shiro

View File

@ -1,8 +1,7 @@
package org.jeecg.modules.demo.test.controller;
import io.lettuce.core.dynamic.annotation.Param;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
@ -11,7 +10,10 @@ import org.jeecg.modules.demo.test.entity.JeecgDemo;
import org.jeecg.modules.demo.test.service.IJeecgDemoService;
import org.jeecg.modules.demo.test.service.IJeecgDynamicDataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@ -21,7 +23,7 @@ import java.util.List;
* @Date:2020-04-21
*/
@Slf4j
@Api(tags = "动态数据源测试")
@Tag(name = "动态数据源测试")
@RestController
@RequestMapping("/test/dynamic")
public class JeecgDynamicDataController extends JeecgController<JeecgDemo, IJeecgDemoService> {
@ -37,7 +39,7 @@ public class JeecgDynamicDataController extends JeecgController<JeecgDemo, IJeec
*/
@PostMapping(value = "/test1")
@AutoLog(value = "动态切换数据源")
@ApiOperation(value = "动态切换数据源", notes = "动态切换数据源")
@Operation(summary = "动态切换数据源")
public Result<List<JeecgDemo>> selectSpelByKey(@RequestParam(required = false) String dsName) {
List<JeecgDemo> list = jeecgDynamicDataService.selectSpelByKey(dsName);
return Result.OK(list);

View File

@ -17,7 +17,7 @@ import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequest;
import java.util.Arrays;
/**

View File

@ -5,8 +5,8 @@ import java.util.Arrays;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;

View File

@ -7,8 +7,8 @@ import java.util.Arrays;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.query.QueryGenerator;

View File

@ -3,6 +3,7 @@ package org.jeecg.modules.demo.test.entity;
import java.io.Serializable;
import com.baomidou.mybatisplus.annotation.Version;
import io.swagger.v3.oas.annotations.media.Schema;
import org.jeecg.common.system.base.entity.JeecgEntity;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.springframework.format.annotation.DateTimeFormat;
@ -10,8 +11,6 @@ import org.springframework.format.annotation.DateTimeFormat;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
@ -25,59 +24,59 @@ import lombok.experimental.Accessors;
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@ApiModel(value="测试DEMO对象", description="测试DEMO")
@Schema(description="测试DEMO")
@TableName("demo")
public class JeecgDemo extends JeecgEntity implements Serializable {
private static final long serialVersionUID = 1L;
/** 姓名 */
@Excel(name="姓名",width=25)
@ApiModelProperty(value = "姓名")
@Schema(description = "姓名")
private java.lang.String name;
/** 关键词 */
@ApiModelProperty(value = "关键词")
@Schema(description = "关键词")
@Excel(name="关键词",width=15)
private java.lang.String keyWord;
/** 打卡时间 */
@ApiModelProperty(value = "打卡时间")
@Schema(description = "打卡时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@Excel(name="打卡时间",width=20,format="yyyy-MM-dd HH:mm:ss")
private java.util.Date punchTime;
/** 工资 */
@ApiModelProperty(value = "工资",example = "0")
@Excel(name="工资",width=15)
@Schema(description = "工资",example = "0")
@Excel(name="工资",type = 4,width=15)
private java.math.BigDecimal salaryMoney;
/** 奖金 */
@ApiModelProperty(value = "奖金",example = "0")
@Excel(name="奖金",width=15)
@Schema(description = "奖金",example = "0")
@Excel(name="奖金",type = 4,width=15)
private java.lang.Double bonusMoney;
/** 性别 {男:1,女:2} */
@ApiModelProperty(value = "性别")
@Schema(description = "性别")
@Excel(name = "性别", width = 15, dicCode = "sex")
private java.lang.String sex;
/** 年龄 */
@ApiModelProperty(value = "年龄",example = "0")
@Excel(name="年龄",width=15)
@Schema(description = "年龄",example = "0")
@Excel(name="年龄",type = 4,width=15)
private java.lang.Integer age;
/** 生日 */
@ApiModelProperty(value = "生日")
@Schema(description = "生日")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
@Excel(name="生日",format="yyyy-MM-dd")
private java.util.Date birthday;
/** 邮箱 */
@ApiModelProperty(value = "邮箱")
@Schema(description = "邮箱")
@Excel(name="邮箱",width=30)
private java.lang.String email;
/** 个人简介 */
@ApiModelProperty(value = "个人简介")
@Schema(description = "个人简介")
private java.lang.String content;
/** 部门编码 */
@Excel(name="部门编码",width=25)
@ApiModelProperty(value = "部门编码")
@Schema(description = "部门编码")
private java.lang.String sysOrgCode;
@ApiModelProperty(value = "租户ID")
// @Schema(description = "租户ID")
private java.lang.Integer tenantId;
/** 乐观锁字段 */
@Version

View File

@ -18,7 +18,7 @@ import org.jeecg.modules.demo.mock.vxe.websocket.VxeSocket;
import org.jeecg.modules.dlglong.entity.MockEntity;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLDecoder;

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-system-api</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.6.1</version>
<version>3.6.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -94,6 +94,22 @@ public interface ISysBaseAPI extends CommonAPI {
@GetMapping("/sys/api/getDepartIdsByUsername")
List<String> getDepartIdsByUsername(@RequestParam("username") String username);
/**
* 8.2 通过用户账号查询部门父ID集合
* @param username
* @return 部门 parentIds
*/
@GetMapping("/sys/api/getDepartParentIdsByUsername")
Set<String> getDepartParentIdsByUsername(@RequestParam("username")String username);
/**
* 8.3 查询部门父ID集合
* @param depIds
* @return 部门 parentIds
*/
@GetMapping("/sys/api/getDepartParentIdsByDepIds")
Set<String> getDepartParentIdsByDepIds(@RequestParam("depIds") Set<String> depIds);
/**
* 9通过用户账号查询部门 name
* @param username
@ -197,7 +213,7 @@ public interface ISysBaseAPI extends CommonAPI {
* @return
*/
@GetMapping("/sys/api/queryAllUser")
public JSONObject queryAllUser(@RequestParam(name="userIds",required=false)String userIds, @RequestParam(name="pageNo",required=false) Integer pageNo,@RequestParam(name="pageSize",required=false) int pageSize);
public JSONObject queryAllUser(@RequestParam(name="userIds",required=false)String userIds, @RequestParam(name="pageNo",required=false) Integer pageNo,@RequestParam(name="pageSize",required=false) Integer pageSize);
/**
@ -291,11 +307,11 @@ public interface ISysBaseAPI extends CommonAPI {
/**
* 31获取用户的权限集合
* @param username
* @param userId
* @return
*/
@GetMapping("/sys/api/getUserPermissionSet")
Set<String> getUserPermissionSet(@RequestParam("username") String username);
Set<String> getUserPermissionSet(@RequestParam("userId") String userId);
/**
* 32判断是否有online访问的权限
@ -335,12 +351,12 @@ public interface ISysBaseAPI extends CommonAPI {
/**
* 36查询用户权限信息
* @param username
* @param userId
* @return
*/
@Override
@GetMapping("/sys/api/queryUserAuths")
Set<String> queryUserAuths(@RequestParam("username")String username);
Set<String> queryUserAuths(@RequestParam("userId")String userId);
/**
* 37根据 id 查询数据库中存储的 DynamicDataSourceModel
@ -481,6 +497,14 @@ public interface ISysBaseAPI extends CommonAPI {
@GetMapping("/sys/api/loadCategoryDictItem")
List<String> loadCategoryDictItem(@RequestParam("ids") String ids);
/**
* 44 反向翻译分类字典,用于导入
*
* @param names 名称,逗号分割
*/
@GetMapping("/sys/api/loadCategoryDictItemByNames")
List<String> loadCategoryDictItemByNames(@RequestParam("names") String names, @RequestParam("delNotExist") boolean delNotExist);
/**
* 43 根据字典code加载字典text
*
@ -551,17 +575,20 @@ public interface ISysBaseAPI extends CommonAPI {
@GetMapping("/sys/api/translateManyDict")
Map<String, List<DictModel>> translateManyDict(@RequestParam("dictCodes") String dictCodes, @RequestParam("keys") String keys);
//update-begin---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
/**
* 49 字典表的 翻译,可批量
* @param table
* @param text
* @param code
* @param keys 多个用逗号分割
* @param ds
* @return
*/
@Override
@GetMapping("/sys/api/translateDictFromTableByKeys")
List<DictModel> translateDictFromTableByKeys(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("keys") String keys);
List<DictModel> translateDictFromTableByKeys(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("keys") String keys, @RequestParam("ds") String ds);
//update-end---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
/**
* 发送模板消息
@ -584,20 +611,6 @@ public interface ISysBaseAPI extends CommonAPI {
@PostMapping("/sys/api/saveDataLog")
void saveDataLog(DataLogDTO dataLogDto);
/**
* 添加文件到知识库
* @param sysFilesModel
*/
@PostMapping("/sys/api/addSysFiles")
void addSysFiles(SysFilesModel sysFilesModel);
/**
* 通过文件路径获取文件id
* @param fileId
*/
@GetMapping("/sys/api/getFileUrl")
String getFileUrl(@RequestParam(name="fileId") String fileId);
/**
* 更新头像
* @param loginUser
@ -734,7 +747,7 @@ public interface ISysBaseAPI extends CommonAPI {
@GetMapping("/sys/api/dictTableWhiteListCheckByDict")
boolean dictTableWhiteListCheckByDict(
@RequestParam("tableOrDictCode") String tableOrDictCode,
@RequestParam(value = "fields", required = false) String[] fields
@RequestParam(value = "fields", required = false) String... fields
);
}

View File

@ -65,6 +65,16 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
return null;
}
@Override
public Set<String> getDepartParentIdsByUsername(String username) {
return null;
}
@Override
public Set<String> getDepartParentIdsByDepIds(Set<String> depIds) {
return null;
}
@Override
public List<String> getDepartNamesByUsername(String username) {
return null;
@ -123,7 +133,7 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
}
@Override
public JSONObject queryAllUser(String userIds, Integer pageNo, int pageSize) {
public JSONObject queryAllUser(String userIds, Integer pageNo, Integer pageSize) {
return null;
}
@ -184,7 +194,7 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
}
@Override
public Set<String> getUserPermissionSet(String username) {
public Set<String> getUserPermissionSet(String userId) {
return null;
}
@ -209,7 +219,7 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
}
@Override
public Set<String> queryUserAuths(String username) {
public Set<String> queryUserAuths(String userId) {
return null;
}
@ -275,10 +285,12 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
return null;
}
//update-begin---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
@Override
public List<DictModel> translateDictFromTableByKeys(String table, String text, String code, String keys) {
public List<DictModel> translateDictFromTableByKeys(String table, String text, String code, String keys, String dataSource) {
return null;
}
//update-end---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
@Override
public void sendTemplateMessage(MessageDTO message) {
@ -319,6 +331,11 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
return null;
}
@Override
public List<String> loadCategoryDictItemByNames(String names, boolean delNotExist) {
return null;
}
@Override
public List<String> loadDictItem(String dictCode, String keys) {
return null;
@ -344,17 +361,6 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
return null;
}
@Override
public void addSysFiles(SysFilesModel sysFilesModel) {
}
@Override
public String getFileUrl(String fileId) {
return null;
}
@Override
public void updateAvatar(LoginUser loginUser) { }
@ -429,7 +435,7 @@ public class SysBaseAPIFallback implements ISysBaseAPI {
}
@Override
public boolean dictTableWhiteListCheckByDict(String tableOrDictCode, String[] fields) {
public boolean dictTableWhiteListCheckByDict(String tableOrDictCode, String... fields) {
return false;
}

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-system-api</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.6.1</version>
<version>3.6.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -89,6 +89,20 @@ public interface ISysBaseAPI extends CommonAPI {
*/
List<String> getDepartIdsByUsername(String username);
/**
* 8.2 通过用户账号查询部门父ID集合
* @param username
* @return 部门 parentIds
*/
Set<String> getDepartParentIdsByUsername(String username);
/**
* 8.2 查询部门父ID集合
* @param depIds
* @return 部门 parentIds
*/
Set<String> getDepartParentIdsByDepIds(Set<String> depIds);
/**
* 9通过用户账号查询部门 name
* @param username
@ -288,10 +302,10 @@ public interface ISysBaseAPI extends CommonAPI {
/**
* 32获取用户的权限集合
* @param username
* @param userId
* @return
*/
Set<String> getUserPermissionSet(String username);
Set<String> getUserPermissionSet(String userId);
/**
* 33判断是否有online访问的权限
@ -373,6 +387,13 @@ public interface ISysBaseAPI extends CommonAPI {
*/
List<String> loadCategoryDictItem(String ids);
/**
* 反向翻译分类字典,用于导入
*
* @param names 名称,逗号分割
*/
List<String> loadCategoryDictItemByNames(String names, boolean delNotExist);
/**
* 根据字典code加载字典text
*
@ -424,19 +445,6 @@ public interface ISysBaseAPI extends CommonAPI {
* @param dataLogDto
*/
void saveDataLog(DataLogDTO dataLogDto);
/**
* 添加文件到知识库
* @param sysFilesModel
*/
void addSysFiles(SysFilesModel sysFilesModel);
/**
* 通过文件路径获取文件id
* @param fileId
*/
String getFileUrl(String fileId);
/**
* 更新头像
* @param loginUser

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-module-system</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.6.1</version>
<version>3.6.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-module-system</artifactId>
<version>3.6.1</version>
<version>3.6.3</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -20,7 +20,7 @@
<artifactId>hibernate-core</artifactId>
</dependency>
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<groupId>org.jeecgframework.boot3</groupId>
<artifactId>hibernate-re</artifactId>
</dependency>
@ -32,12 +32,12 @@
<!-- 积木报表 -->
<dependency>
<groupId>org.jeecgframework.jimureport</groupId>
<artifactId>jimureport-spring-boot-starter</artifactId>
<artifactId>jimureport-spring-boot3-starter-fastjson2</artifactId>
</dependency>
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>drag-free</artifactId>
<version>1.0.2</version>
<groupId>org.jeecgframework.boot3</groupId>
<artifactId>jimureport-drag</artifactId>
<version>2.0.2</version>
</dependency>
<!-- 积木报表 mongo redis 支持包
<dependency>

View File

@ -1,33 +1,33 @@
package org.jeecg.config.init;
import org.apache.catalina.Context;
import org.apache.tomcat.util.scan.StandardJarScanner;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Description: TomcatFactoryConfig
* @author: scott
* @date: 2021年01月25日 11:40
*/
@Configuration
public class TomcatFactoryConfig {
/**
* tomcat-embed-jasper引用后提示jar找不到的问题
*/
@Bean
public TomcatServletWebServerFactory tomcatFactory() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory() {
@Override
protected void postProcessContext(Context context) {
((StandardJarScanner) context.getJarScanner()).setScanManifest(false);
}
};
factory.addConnectorCustomizers(connector -> {
connector.setProperty("relaxedPathChars", "[]{}");
connector.setProperty("relaxedQueryChars", "[]{}");
});
return factory;
}
}
//package org.jeecg.config.init;
//
//import org.apache.catalina.Context;
//import org.apache.tomcat.util.scan.StandardJarScanner;
//import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
//import org.springframework.context.annotation.Bean;
//import org.springframework.context.annotation.Configuration;
//
///**
// * @Description: TomcatFactoryConfig
// * @author: scott
// * @date: 2021年01月25日 11:40
// */
//@Configuration
//public class TomcatFactoryConfig {
// /**
// * tomcat-embed-jasper引用后提示jar找不到的问题
// */
// @Bean
// public TomcatServletWebServerFactory tomcatFactory() {
// TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory() {
// @Override
// protected void postProcessContext(Context context) {
// ((StandardJarScanner) context.getJarScanner()).setScanManifest(false);
// }
// };
// factory.addConnectorCustomizers(connector -> {
// connector.setProperty("relaxedPathChars", "[]{}");
// connector.setProperty("relaxedQueryChars", "[]{}");
// });
// return factory;
// }
//}

View File

@ -1,81 +1,81 @@
package org.jeecg.config.jimureport;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.SysUserCacheInfo;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.TokenUtils;
import org.jeecg.modules.jmreport.api.JmReportTokenServiceI;
import org.jeecg.modules.system.service.impl.SysBaseApiImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* 自定义积木报表鉴权(如果不进行自定义,则所有请求不做权限控制)
* * 1.自定义获取登录token
* * 2.自定义获取登录用户
* @author: jeecg-boot
*/
@Slf4j
@Component
public class JimuReportTokenService implements JmReportTokenServiceI {
@Autowired
private SysBaseApiImpl sysBaseApi;
@Autowired
@Lazy
private RedisUtil redisUtil;
@Override
public String getToken(HttpServletRequest request) {
return TokenUtils.getTokenByRequest(request);
}
@Override
public String getUsername(String token) {
return JwtUtil.getUsername(token);
}
@Override
public String[] getRoles(String token) {
String username = JwtUtil.getUsername(token);
Set roles = sysBaseApi.getUserRoleSet(username);
if(CollectionUtils.isEmpty(roles)){
return null;
}
return (String[]) roles.toArray(new String[roles.size()]);
}
@Override
public Boolean verifyToken(String token) {
return TokenUtils.verifyToken(token, sysBaseApi, redisUtil);
}
@Override
public Map<String, Object> getUserInfo(String token) {
Map<String, Object> map = new HashMap(5);
String username = JwtUtil.getUsername(token);
//此处通过token只能拿到一个信息 用户账号 后面的就是根据账号获取其他信息 查询数据或是走redis 用户根据自身业务可自定义
SysUserCacheInfo userInfo = null;
try {
userInfo = sysBaseApi.getCacheUser(username);
} catch (Exception e) {
log.error("获取用户信息异常:"+ e.getMessage());
return map;
}
//设置账号名
map.put(SYS_USER_CODE, userInfo.getSysUserCode());
//设置部门编码
map.put(SYS_ORG_CODE, userInfo.getSysOrgCode());
// 将所有信息存放至map 解析sql/api会根据map的键值解析
return map;
}
}
//package org.jeecg.config.jimureport;
//
//import lombok.extern.slf4j.Slf4j;
//import org.jeecg.common.system.util.JwtUtil;
//import org.jeecg.common.system.vo.SysUserCacheInfo;
//import org.jeecg.common.util.RedisUtil;
//import org.jeecg.common.util.TokenUtils;
//import org.jeecg.modules.jmreport.api.JmReportTokenServiceI;
//import org.jeecg.modules.system.service.impl.SysBaseApiImpl;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.context.annotation.Lazy;
//import org.springframework.stereotype.Component;
//import org.springframework.util.CollectionUtils;
//
//import jakarta.servlet.http.HttpServletRequest;
//import java.util.HashMap;
//import java.util.Map;
//import java.util.Set;
//
///**
// * 自定义积木报表鉴权(如果不进行自定义,则所有请求不做权限控制)
// * * 1.自定义获取登录token
// * * 2.自定义获取登录用户
// * @author: jeecg-boot
// */
//
//
//@Slf4j
//@Component
//public class JimuReportTokenService implements JmReportTokenServiceI {
// @Autowired
// private SysBaseApiImpl sysBaseApi;
// @Autowired
// @Lazy
// private RedisUtil redisUtil;
//
// @Override
// public String getToken(HttpServletRequest request) {
// return TokenUtils.getTokenByRequest(request);
// }
//
// @Override
// public String getUsername(String token) {
// return JwtUtil.getUsername(token);
// }
//
// @Override
// public String[] getRoles(String token) {
// String username = JwtUtil.getUsername(token);
// Set roles = sysBaseApi.getUserRoleSet(username);
// if(CollectionUtils.isEmpty(roles)){
// return null;
// }
// return (String[]) roles.toArray(new String[roles.size()]);
// }
//
// @Override
// public Boolean verifyToken(String token) {
// return TokenUtils.verifyToken(token, sysBaseApi, redisUtil);
// }
//
// @Override
// public Map<String, Object> getUserInfo(String token) {
// Map<String, Object> map = new HashMap(5);
// String username = JwtUtil.getUsername(token);
// //此处通过token只能拿到一个信息 用户账号 后面的就是根据账号获取其他信息 查询数据或是走redis 用户根据自身业务可自定义
// SysUserCacheInfo userInfo = null;
// try {
// userInfo = sysBaseApi.getCacheUser(username);
// } catch (Exception e) {
// log.error("获取用户信息异常:"+ e.getMessage());
// return map;
// }
// //设置账号名
// map.put(SYS_USER_CODE, userInfo.getSysUserCode());
// //设置部门编码
// map.put(SYS_ORG_CODE, userInfo.getSysOrgCode());
// // 将所有信息存放至map 解析sql/api会根据map的键值解析
// return map;
// }
//}

View File

@ -14,7 +14,7 @@ import org.jeecg.modules.system.entity.SysTenantPack;
import org.jeecg.modules.system.entity.SysTenantPackUser;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import jakarta.annotation.Resource;
import java.lang.reflect.Method;
import java.util.Date;

View File

@ -140,6 +140,26 @@ public class SystemApiController {
return sysBaseApi.getDepartIdsByUsername(username);
}
/**
* 通过用户账号查询部门父ID集合
* @param username
* @return 部门 id
*/
@GetMapping("/getDepartParentIdsByUsername")
Set<String> getDepartParentIdsByUsername(@RequestParam("username") String username){
return sysBaseApi.getDepartParentIdsByUsername(username);
}
/**
* 查询部门父ID集合
* @param depIds
* @return 部门 id
*/
@GetMapping("/getDepartParentIdsByDepIds")
Set<String> getDepartParentIdsByDepIds(@RequestParam("depIds") Set<String> depIds){
return sysBaseApi.getDepartParentIdsByDepIds(depIds);
}
/**
* 通过用户账号查询部门 name
* @param username
@ -327,7 +347,7 @@ public class SystemApiController {
* @return
*/
@GetMapping("/queryAllUser")
public JSONObject queryAllUser(@RequestParam(name="userIds",required=false)String userIds, @RequestParam(name="pageNo",required=false) Integer pageNo,@RequestParam(name="pageSize",required=false) int pageSize){
public JSONObject queryAllUser(@RequestParam(name="userIds",required=false)String userIds, @RequestParam(name="pageNo",required=false) Integer pageNo,@RequestParam(name="pageSize",required=false) Integer pageSize){
return sysBaseApi.queryAllUser(userIds, pageNo, pageSize);
}
@ -366,12 +386,12 @@ public class SystemApiController {
/**
* 获取用户的权限集合
* @param username
* @param userId 用户表ID
* @return
*/
@GetMapping("/getUserPermissionSet")
public Set<String> getUserPermissionSet(@RequestParam("username") String username){
return sysBaseApi.getUserPermissionSet(username);
public Set<String> getUserPermissionSet(@RequestParam("userId") String userId){
return sysBaseApi.getUserPermissionSet(userId);
}
//-----
@ -399,12 +419,12 @@ public class SystemApiController {
/**
* 查询用户权限信息
* @param username
* @param userId
* @return
*/
@GetMapping("/queryUserAuths")
public Set<String> queryUserAuths(@RequestParam("username") String username){
return sysUserService.getUserPermissionsSet(username);
public Set<String> queryUserAuths(@RequestParam("userId") String userId){
return sysUserService.getUserPermissionsSet(userId);
}
/**
@ -527,6 +547,17 @@ public class SystemApiController {
return sysBaseApi.loadCategoryDictItem(ids);
}
/**
* 反向翻译分类字典,用于导入
*
* @param names 名称,逗号分割
* @return
*/
@GetMapping("/loadCategoryDictItemByNames")
List<String> loadCategoryDictItemByNames(@RequestParam("names") String names, @RequestParam("delNotExist") boolean delNotExist) {
return sysBaseApi.loadCategoryDictItemByNames(names, delNotExist);
}
/**
* 根据字典code加载字典text
*
@ -547,7 +578,7 @@ public class SystemApiController {
* @param tenantId 新的租户ID
* @return Map<String, String> Map<原字典编码, 新字典编码>
*/
@GetMapping("/sys/api/copyLowAppDict")
@GetMapping("/copyLowAppDict")
Map<String, String> copyLowAppDict(@RequestParam("originalAppId") String originalAppId, @RequestParam("appId") String appId, @RequestParam("tenantId") String tenantId) {
return sysBaseApi.copyLowAppDict(originalAppId, appId, tenantId);
}
@ -655,6 +686,7 @@ public class SystemApiController {
}
//update-begin---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
/**
* 【接口签名验证】
* 49 字典表的 翻译,可批量
@ -663,12 +695,14 @@ public class SystemApiController {
* @param text
* @param code
* @param keys 多个用逗号分割
* @param ds 数据源
* @return
*/
@GetMapping("/translateDictFromTableByKeys")
public List<DictModel> translateDictFromTableByKeys(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("keys") String keys) {
return this.sysBaseApi.translateDictFromTableByKeys(table, text, code, keys);
public List<DictModel> translateDictFromTableByKeys(@RequestParam("table") String table, @RequestParam("text") String text, @RequestParam("code") String code, @RequestParam("keys") String keys, @RequestParam("ds") String ds) {
return this.sysBaseApi.translateDictFromTableByKeys(table, text, code, keys, ds);
}
//update-end---author:chenrui ---date:20231221 for[issues/#5643]解决分布式下表字典跨库无法查询问题------------
/**
* 发送模板信息
@ -698,14 +732,6 @@ public class SystemApiController {
this.sysBaseApi.saveDataLog(dataLogDto);
}
@PostMapping("/addSysFiles")
public void addSysFiles(@RequestBody SysFilesModel sysFilesModel){this.sysBaseApi.addSysFiles(sysFilesModel);}
@GetMapping("/getFileUrl")
public String getFileUrl(@RequestParam(name="fileId") String fileId){
return this.sysBaseApi.getFileUrl(fileId);
}
/**
* 更新头像
* @param loginUser
@ -824,7 +850,7 @@ public class SystemApiController {
* @param deptIds
* @return
*/
@GetMapping("/sys/api/queryUserIdsByDeptIds")
@GetMapping("/queryUserIdsByDeptIds")
public List<String> queryUserIdsByDeptIds(@RequestParam("deptIds") List<String> deptIds){
return sysBaseApi.queryUserIdsByDeptIds(deptIds);
}
@ -834,7 +860,7 @@ public class SystemApiController {
* @param deptIds
* @return
*/
@GetMapping("/sys/api/queryUserAccountsByDeptIds")
@GetMapping("/queryUserAccountsByDeptIds")
public List<String> queryUserAccountsByDeptIds(@RequestParam("deptIds") List<String> deptIds){
return sysBaseApi.queryUserAccountsByDeptIds(deptIds);
}
@ -844,7 +870,7 @@ public class SystemApiController {
* @param roleCodes
* @return
*/
@GetMapping("/sys/api/queryUserIdsByRoleds")
@GetMapping("/queryUserIdsByRoleds")
public List<String> queryUserIdsByRoleds(@RequestParam("roleCodes") List<String> roleCodes){
return sysBaseApi.queryUserIdsByRoleds(roleCodes);
}
@ -854,7 +880,7 @@ public class SystemApiController {
* @param positionIds
* @return
*/
@GetMapping("/sys/api/queryUserIdsByPositionIds")
@GetMapping("/queryUserIdsByPositionIds")
public List<String> queryUserIdsByPositionIds(@RequestParam("positionIds") List<String> positionIds){
return sysBaseApi.queryUserIdsByPositionIds(positionIds);
}
@ -866,7 +892,7 @@ public class SystemApiController {
* @param orgCode 部门编码
* @return
*/
@GetMapping("/sys/api/getUserAccountsByDepCode")
@GetMapping("/getUserAccountsByDepCode")
public List<String> getUserAccountsByDepCode(String orgCode){
return sysBaseApi.getUserAccountsByDepCode(orgCode);
}
@ -877,7 +903,7 @@ public class SystemApiController {
* @param selectSql
* @return
*/
@GetMapping("/sys/api/dictTableWhiteListCheckBySql")
@GetMapping("/dictTableWhiteListCheckBySql")
public boolean dictTableWhiteListCheckBySql(@RequestParam("selectSql") String selectSql) {
return sysBaseApi.dictTableWhiteListCheckBySql(selectSql);
}
@ -889,10 +915,10 @@ public class SystemApiController {
* @param fields 如果传的是dictCode则该参数必须传null
* @return
*/
@GetMapping("/sys/api/dictTableWhiteListCheckByDict")
@GetMapping("/dictTableWhiteListCheckByDict")
public boolean dictTableWhiteListCheckByDict(
@RequestParam("tableOrDictCode") String tableOrDictCode,
@RequestParam(value = "fields", required = false) String[] fields
@RequestParam(value = "fields", required = false) String... fields
) {
return sysBaseApi.dictTableWhiteListCheckByDict(tableOrDictCode, fields);
}

View File

@ -2,8 +2,8 @@ package org.jeecg.modules.cas.controller;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.api.vo.Result;

View File

@ -2,8 +2,8 @@ package org.jeecg.modules.message.controller;
import java.util.Arrays;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.base.controller.JeecgController;

Some files were not shown because too many files have changed in this diff Show More