diff --git a/LICENSE b/LICENSE index 6364cff6112763064f7a2e3da158d0f4d15b9183..300577bf1335da552ff9982a79b022f2fc70b1ef 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,21 @@ -MIT License - -Copyright (c) 2023 疯狂的挖掘机 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +MIT License + +Copyright (c) 2023 Otis Duer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.en.md b/README.en.md deleted file mode 100644 index 3b32d4976e3b49302d99ea9fbf5a42f8189e3c0c..0000000000000000000000000000000000000000 --- a/README.en.md +++ /dev/null @@ -1,36 +0,0 @@ -# data_harness-be - -#### Description -驭数轻云后端代码仓库 - -#### Software Architecture -Software architecture description - -#### Installation - -1. xxxx -2. xxxx -3. xxxx - -#### Instructions - -1. xxxx -2. xxxx -3. xxxx - -#### Contribution - -1. Fork the repository -2. Create Feat_xxx branch -3. Commit your code -4. Create Pull Request - - -#### Gitee Feature - -1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md -2. Gitee blog [blog.gitee.com](https://blog.gitee.com) -3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore) -4. The most valuable open source project [GVP](https://gitee.com/gvp) -5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help) -6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/README.md b/README.md index 8995200f4a99ba9a4a7cb28510b4cc34e4ed75f0..b58c9fdc95edff812c0f39f1f76256aba8baa119 100644 --- a/README.md +++ b/README.md @@ -3,23 +3,20 @@ 📃 [[Gitee](https://gitee.com/data_harness_cloud/data_harness-be)] [[GitHub](https://github.com/data-harness-cloud/data_harness-be.git)] -    👋 加入我们的 [[WeChat]] +    👋 加入我们的 WeChat -## 介绍 +## 介绍(代码将在下周更新到仓库) “驭数轻云数据平台”(以下简称驭数平台)是驭数团队开源的数据平台,平台致力于为中小企业提供易用、低门槛基于大模型打造的数据平台,助力企业便捷、低成本的实现“掌控数据、轻盈如云”的愿景。驭数平台短期目标致力于满足企业的基础数据梳理、数据治理、数据中台等数据功能,远景目标是基于大模型为广大企业提供开源可用的Data Fabric实现平台。
开发团队是一群热爱开源的小伙伴,各自在多年的工作以及项目实践中发现,很多企业想建设企业自己的数据平台的时候往往找不到一款趁手工具。而且商业平台的价格昂贵,实施成本高,基本不可能进行二次开发。往往企业可能需要的功能只是其中的一点,但是不得不面对大集群、多功能的捆绑购买。团队经过一段时间的准备,为企业、个人在数据的应用以及数据平台建设,提供多一种选择。同时随着大模型的发展,团队将深入思考大模型在数据领域的应用,以及在数据领域的各个环节如何与大模型结合,并且这些成果将会同步更新在开源平台。
平台的开发刚起步,还有非常多的问题,希望社区的小伙伴多一些包容,也欢迎更多的小伙伴能够加入到团队一起共建。 -### [ **驭数轻云数据平台系统演示** ](http://175.24.190.217:30666/#/dashboard/index) -因集成了AI服务,有限的算力需要不断的用于训练模型,暂时需要申请体验,用户名与密码请联系开发团队,后期算力改善后将完全开放体验。 - 驭数平台由如下特性: 1. **基于大模型的数据平台:** 驭数平台是基于大模型为驱动的综合数据平台,支持企业将自身结构以及非结构化数据成果与大模型结合,平台将支持基于大模型的数据应用,例如:数据探源、图表生成、数据报告、数据归因、技术元数据与业务元数据融合等等。 2. **更完整的数据功能:** 驭数平台的功能将会完整的支撑企业数据使用的各个环节,从作为基础数据平台的数据积累、数据中台、数据治理、大模型落地应用。 3. **全面的开源支撑:** 除了数据平台全部开源,在大模型领域的成果也会开源,包括我们基于项目进行微调的私有模型,例如业务元数据与技术元数据的微调模型、数据治理成果的微调模型等等,团队以完全开放的心态与社区小伙伴共建数据平台。 4. **轻量化平台:** 团队小伙伴来自于五湖四海,多年在开发以及数据领域的经验教训,深刻认识到数据平台的轻量化对中小企业的是一个不小的福音,我们本次开发的是基于单体服务的平台,并且暂时没有考虑Hadoop体系,而是以Doris为作为基础的存算基础平台,大大的减轻大家的使用负担。同时也兼容单机MySQL,完全轻装上阵,实现数据平台的建设以及落地应用。 -5. **高质量的界面UI:** 颜值即正义,我们很荣幸的邀请到UI设计师与团队一起推动开源平台的建设,直接输出企业级UI,大家开箱即用,不虚任何场合的演示。 +5. **高质量的界面UI:**颜值即正义,我们很荣幸的邀请到UI设计师与团队一起推动开源平台的建设,直接输出企业级UI,大家开箱即用,不虚任何场合的演示。 --- @@ -27,97 +24,50 @@ 由于会提供模型,尽管模型在训练的各个阶段都尽力确保数据的合规性和准确性,但由于模型规模较小,且模型受概率随机性因素影响,无法保证输出内容的准确。同时模型的输出容易被用户的输入误导。**本项目不承担开源模型和代码导致的数据安全、舆情风险或发生任何模型被误导、滥用、传播、不当利用而产生的风险和责任。** - -## 架构图 -### 整体架构图 -![输入图片说明](picture/%E6%8A%80%E6%9C%AF%E6%9E%B6%E6%9E%84%E5%9B%BE.png) - -### 数据架构图 -![输入图片说明](picture/%E6%95%B0%E6%8D%AE%E6%9E%B6%E6%9E%84.png) - -## 单体服务模块列表 -| 模块 | Doris/MySQL | Hadoop体系 | -| --- | --- | --- | -| 系统管理模块 | 开发中| 待计划| -| 数据资源模块 | 开发中| 待计划| -| 数据蓝图模块 | 开发中| 待计划| -| 数据开发模块 | 开发中| 待计划| -| 数据发现模块 | 计划| 待计划| -| 数据服务模块 | 计划| 待计划| -| 数据工厂模块 | 计划| 待计划| -| 数据可视模块 | 计划| 待计划| -| 数据运营模块 | 计划| 待计划| -| AI大模型探索模块 | 计划| 待计划| - -## 微服务模块列表 -| 模块 | Doris/MySQL | Hadoop体系 | -| --- | --- | --- | -| 系统管理模块 | 计划| 待计划| -| 数据资源模块 | 计划| 待计划| -| 数据蓝图模块 | 计划| 待计划| -| 数据开发模块 | 计划| 待计划| -| 数据发现模块 | 计划| 待计划| -| 数据服务模块 | 计划| 待计划| -| 数据工厂模块 | 计划| 待计划| -| 数据可视模块 | 计划| 待计划| -| 数据运营模块 | 计划| 待计划| -| AI大模型探索模块 | 计划| 待计划| +## 模块列表 +| 模块 | 完成度 | +| --- | --- | +| 系统管理模块 | 开发中| +| 数据资源模块 | 开发中| +| 数据蓝图模块 | 开发中| +| 数据开发模块 | 开发中| +| 数据发现模块 | 计划| +| 数据服务模块 | 计划| +| 数据工厂模块 | 计划| +| 数据可视模块 | 计划| +| 数据运营模块 | 计划| +| AI大模型探索模块 | 计划| ## 项目截图 -项目登录页
-![输入图片说明](picture/picture%E7%99%BB%E5%BD%95%E9%A1%B5.png) +项目登录页
![image.png](https://cdn.nlark.com/yuque/0/2023/png/94862/1699102363782-2349d3f3-a6fb-463c-ac4a-620a1eb7a5b2.png#averageHue=%23e9ecf6&clientId=u50d661d9-c305-4&from=paste&height=968&id=u70cb7fef&originHeight=968&originWidth=1914&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1178489&status=done&style=none&taskId=u1392ffc6-2a1d-417c-82d0-20dbc7608d0&title=&width=1914) 项目首页 -![输入图片说明](picture/picture%E9%A6%96%E9%A1%B5.png) - -目录边栏
-![输入图片说明](picture/picture%E7%9B%AE%E5%BD%95%E8%BE%B9%E6%A0%8F.png) +## ![image.png](https://cdn.nlark.com/yuque/0/2023/png/94862/1699102403639-763f5163-09bb-4baa-bf64-8df40caf51f9.png#averageHue=%23d8dcf1&clientId=u50d661d9-c305-4&from=paste&height=964&id=u7697e1d9&originHeight=964&originWidth=1915&originalType=binary&ratio=1&rotation=0&showTitle=false&size=1084522&status=done&style=none&taskId=u019a9375-909f-4af6-b161-e813ecfb193&title=&width=1915) -AI大模型对话
-![输入图片说明](picture/pictureAI%E5%AF%B9%E8%AF%9D%E6%A8%A1%E5%9E%8B.png) +目录边栏
![image.png](https://cdn.nlark.com/yuque/0/2023/png/94862/1699102556171-490c2afc-4337-4195-8e75-50e6a6a57312.png#averageHue=%239e9f9f&clientId=u50d661d9-c305-4&from=paste&height=963&id=u053ed3fb&originHeight=963&originWidth=1914&originalType=binary&ratio=1&rotation=0&showTitle=false&size=787756&status=done&style=none&taskId=u429a2595-840a-403a-aef5-d66e6211285&title=&width=1914) -AI大模型对话示例
-![输入图片说明](picture/pictureAI%E5%AF%B9%E8%AF%9D%E7%A4%BA%E4%BE%8B.png) +AI大模型对话
![image.png](https://cdn.nlark.com/yuque/0/2023/png/94862/1699102686484-08710899-179f-463a-b36a-eaeab29f8e8e.png#averageHue=%23eff1f6&clientId=u50d661d9-c305-4&from=paste&height=964&id=ufbc5abd4&originHeight=964&originWidth=1917&originalType=binary&ratio=1&rotation=0&showTitle=false&size=252018&status=done&style=none&taskId=u5ee3ac8c-c8a6-42c1-8bed-8968da7a379&title=&width=1917) -数据规划
-![输入图片说明](picture/picture%E6%95%B0%E6%8D%AE%E8%A7%84%E5%88%92.png) +AI大模型对话示例
![image.png](https://cdn.nlark.com/yuque/0/2023/png/94862/1699103667122-dcd6afd0-8187-4fa0-a188-6a5c9e263e9d.png#averageHue=%23e1e3e3&clientId=u50d661d9-c305-4&from=paste&height=964&id=u10d0c6f3&originHeight=964&originWidth=1919&originalType=binary&ratio=1&rotation=0&showTitle=false&size=213459&status=done&style=none&taskId=u88a2a83f-c568-45e7-8a77-33d74449396&title=&width=1919) -模型概览和设计
-![输入图片说明](picture/picture%E6%A8%A1%E5%9E%8B%E6%A6%82%E8%A7%88%E5%92%8C%E8%AE%BE%E8%AE%A11.png) -![输入图片说明](picture/picture%E6%A8%A1%E5%9E%8B%E6%A6%82%E8%A7%88%E8%AE%BE%E8%AE%A12.png) +数据规划
![image.png](https://cdn.nlark.com/yuque/0/2023/png/94862/1699103730811-2628cff0-f8e3-4288-9786-8e0816b7c9b7.png#averageHue=%23eff2f4&clientId=u50d661d9-c305-4&from=paste&height=965&id=ubebd6203&originHeight=965&originWidth=1912&originalType=binary&ratio=1&rotation=0&showTitle=false&size=125573&status=done&style=none&taskId=ub18836d8-521d-4b50-ada0-5bfa60413ff&title=&width=1912) -新建模型
-![输入图片说明](picture/picture%E6%96%B0%E5%BB%BA%E6%A8%A1%E5%9E%8B.png) +模型概览和设计
![image.png](https://cdn.nlark.com/yuque/0/2023/png/94862/1699103847922-59e41f6d-50ca-4e60-b095-703c4f6ad245.png#averageHue=%23c1c3c1&clientId=u50d661d9-c305-4&from=paste&height=960&id=u6d4c1d2c&originHeight=960&originWidth=1913&originalType=binary&ratio=1&rotation=0&showTitle=false&size=172238&status=done&style=none&taskId=u3b4019a1-6cde-4a38-8ae9-6f5fed6c15b&title=&width=1913)
![image.png](https://cdn.nlark.com/yuque/0/2023/png/94862/1699103801977-24de1ea6-6f40-4757-9a40-4f3b57e10193.png#averageHue=%2380cf9b&clientId=u50d661d9-c305-4&from=paste&height=964&id=ud404ed07&originHeight=964&originWidth=1904&originalType=binary&ratio=1&rotation=0&showTitle=false&size=225447&status=done&style=none&taskId=ue3f36de8-e9d4-4ae8-ba7d-07783741b06&title=&width=1904) -数据开发
-![输入图片说明](picture/picture%E6%95%B0%E6%8D%AE%E5%BC%80%E5%8F%91.png) +新建模型
![image.png](https://cdn.nlark.com/yuque/0/2023/png/94862/1699103829368-ff768b18-5fc8-486e-be19-19da9ec4148f.png#averageHue=%23dbc95d&clientId=u50d661d9-c305-4&from=paste&height=957&id=udf1ad499&originHeight=957&originWidth=1907&originalType=binary&ratio=1&rotation=0&showTitle=false&size=150969&status=done&style=none&taskId=u484a6c74-b807-43c6-95c7-f9a3050dd5e&title=&width=1907) -数据传输
-![输入图片说明](picture/picture%E6%95%B0%E6%8D%AE%E4%BC%A0%E8%BE%93.png) +数据开发
![image.png](https://cdn.nlark.com/yuque/0/2023/png/94862/1699103905036-4f0d98a5-6375-4f4c-a0c6-69d0dbca6318.png#averageHue=%23c0d0c7&clientId=u50d661d9-c305-4&from=paste&height=962&id=uc775e255&originHeight=962&originWidth=1906&originalType=binary&ratio=1&rotation=0&showTitle=false&size=145492&status=done&style=none&taskId=u45b4ec52-9530-4d71-9596-b7f3aae72c8&title=&width=1906) -任务调度列表
-![输入图片说明](picture/picture%E4%BB%BB%E5%8A%A1%E8%B0%83%E5%BA%A6.png) +数据传输
![image.png](https://cdn.nlark.com/yuque/0/2023/png/94862/1699103943235-2b9bc830-3d29-4a23-bc3c-4cc220ef90bf.png#averageHue=%23a1cdcb&clientId=u50d661d9-c305-4&from=paste&height=965&id=u94c95154&originHeight=965&originWidth=1918&originalType=binary&ratio=1&rotation=0&showTitle=false&size=155213&status=done&style=none&taskId=u2b190670-768f-48f2-b7b5-3e11f518c5a&title=&width=1918) +任务调度列表
![image.png](https://cdn.nlark.com/yuque/0/2023/png/94862/1699103980224-c4cb2296-dbcb-42ed-8fdf-e21990656785.png#averageHue=%23eab5aa&clientId=u50d661d9-c305-4&from=paste&height=966&id=u6b2a58c0&originHeight=966&originWidth=1912&originalType=binary&ratio=1&rotation=0&showTitle=false&size=123989&status=done&style=none&taskId=u5bb2d12c-a9f9-46ed-9c25-e1ade5e94a4&title=&width=1912) ## 技术栈 -| 模块 | 组件 | 版本 | 计划 | -|------|------------|-----|-----------------| -| 前端 | vue | 3.x | TS | -| 后端 | Springboot | 2.x | 3.x | -| 架构 | 单体 | -- | 微服务 | -| 部署 | Docker | -- | K8S | -| 数据传输 | Seatunnel | 2.x | flink | -| 任务调度 | Quartz | -- | DolphinSchedule | -| 存算引擎 | Doris/MySQl | -- | Hadoop | -| LLM大模型 | 开源模型/商用模型 | -- | 微调数据行业模型 | - - +待补充... ### 部署过程 -[前端工程-基于Vue3](https://gitee.com/data_harness_cloud/data_harness-fe) - -[部署工程-一键部署](https://gitee.com/data_harness_cloud/data_harness_deployment) \ No newline at end of file +待补充... diff --git a/application-webadmin/src/main/java/supie/webadmin/app/controller/DatabaseManagementController.java b/application-webadmin/src/main/java/supie/webadmin/app/controller/DatabaseManagementController.java index d435a076da65effa07e7a6ca88cab38d06f85e2d..2335f0d00c6f09a993dd4b77cafc9d4095bc4a21 100644 --- a/application-webadmin/src/main/java/supie/webadmin/app/controller/DatabaseManagementController.java +++ b/application-webadmin/src/main/java/supie/webadmin/app/controller/DatabaseManagementController.java @@ -50,7 +50,7 @@ public class DatabaseManagementController { strategy.closeAll(); } catch (Exception e) { log.error("数据源连接失败", e); - return ResponseResult.error("500", "连接失败:"+e.getMessage()); + return ResponseResult.error("500", "连接失败:"+e.getMessage()); } return ResponseResult.success("连接成功!"); } @@ -69,11 +69,11 @@ public class DatabaseManagementController { Strategy strategy = strategyFactory.getStrategy( databaseManagement.getDatabaseType(), databaseManagement.getIp(), databaseManagement.getPort(), databaseManagement.getDatabaseName(), databaseManagement.getUsername(), databaseManagement.getPassword()); - price = strategy.queryDatabaseTable(databaseManagement); + price = strategy.queryDatabaseTable(databaseManagement.getDatabaseName()); strategy.closeAll(); } catch (Exception e) { log.error("数据源连接失败", e); - return ResponseResult.error("500", e.getMessage()); + return ResponseResult.error("500", e.getMessage()); } return ResponseResult.success(price); } @@ -92,11 +92,11 @@ public class DatabaseManagementController { Strategy strategy = strategyFactory.getStrategy( databaseManagement.getDatabaseType(), databaseManagement.getIp(), databaseManagement.getPort(), databaseManagement.getDatabaseName(), databaseManagement.getUsername(), databaseManagement.getPassword()); - price = strategy.queryTableFields(databaseManagement); + price = strategy.queryTableFields(databaseManagement.getDatabaseName(), databaseManagement.getTableName()); strategy.closeAll(); } catch (Exception e) { - log.error("数据源连接失败",e); - return ResponseResult.error("500",e.getMessage()); + log.error("数据源连接失败", e); + return ResponseResult.error("500", e.getMessage()); } return ResponseResult.success(price); } @@ -112,13 +112,21 @@ public class DatabaseManagementController { resultData = strategy.executeSqlList(sql); strategy.closeAll(); } catch (Exception e) { - log.error("数据源连接失败",e); - return ResponseResult.error("500", e.getMessage()); + log.error("数据源连接失败", e); + return ResponseResult.error("500", e.getMessage()); } return ResponseResult.success(resultData); } -} - - + @PostMapping("/getAllDatabaseName") + @ApiOperation("获取可操作的所有数据库名称") + public ResponseResult> getAllDatabaseName(@MyRequestBody DatabaseManagement databaseManagement){ + Strategy strategy = strategyFactory.getStrategy( + databaseManagement.getDatabaseType(), databaseManagement.getIp(), databaseManagement.getPort(), + databaseManagement.getDatabaseName(), databaseManagement.getUsername(), databaseManagement.getPassword()); + List resultData = strategy.queryAllDatabaseName(); + strategy.closeAll(); + return ResponseResult.success(resultData); + } +} diff --git a/application-webadmin/src/main/java/supie/webadmin/app/controller/ProjectEngineController.java b/application-webadmin/src/main/java/supie/webadmin/app/controller/ProjectEngineController.java index 4788dfd50a270584ae81059bc031a02496537d34..aee911b746aa9b8affa09afe5ade909634adc9a8 100644 --- a/application-webadmin/src/main/java/supie/webadmin/app/controller/ProjectEngineController.java +++ b/application-webadmin/src/main/java/supie/webadmin/app/controller/ProjectEngineController.java @@ -1,8 +1,14 @@ package supie.webadmin.app.controller; +import cn.hutool.core.util.StrUtil; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiImplicitParams; +import io.swagger.annotations.ApiOperation; import supie.common.log.annotation.OperationLog; import supie.common.log.model.constant.SysOperationLogType; import com.github.pagehelper.page.PageMethod; +import supie.webadmin.app.service.databasemanagement.Strategy; +import supie.webadmin.app.service.databasemanagement.StrategyFactory; import supie.webadmin.app.vo.*; import supie.webadmin.app.dto.*; import supie.webadmin.app.model.*; @@ -33,6 +39,10 @@ public class ProjectEngineController { @Autowired private ProjectEngineService projectEngineService; + @Autowired + private ProjectMainService projectMainService; + @Autowired + private StrategyFactory strategyFactory; /** * 新增数据项目-存算引擎表数据。 @@ -198,4 +208,64 @@ public class ProjectEngineController { } return ResponseResult.success(); } + + /** + * 获取可操作的数据库集 + * + * @param projectId 项目 ID + * @return 返回结果 + * @author 王立宏 + * @date 2023/11/14 05:30 + */ + @PostMapping("/getAllDatabaseName") + @ApiOperation("获取可操作的所有数据库名称") + public ResponseResult> getAllDatabaseName(@MyRequestBody Long projectId){ + if (projectId == null) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + ProjectMain projectMain = projectMainService.getByIdWithRelation(projectId, MyRelationParam.full()); + if (projectMain == null || projectMain.getProjectEngineId() == null || projectMain.getProjectEngine() == null) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, + "数据验证失败,当前 [数据] 并不存在,请刷新后重试!"); + } + ProjectEngine projectEngine = projectMain.getProjectEngine(); + Strategy strategy = strategyFactory.getStrategy( + projectEngine.getEngineType(), projectEngine.getEngineHost(), projectEngine.getEnginePort(), + null, projectEngine.getEngineUsername(), projectEngine.getEnginePassword()); + List resultData = strategy.queryAllDatabaseName(); + strategy.closeAll(); + return ResponseResult.success(resultData); + } + + /** + * 执行 SQL + * + * @param sql SQL语句 + * @param databaseName 目标数据库名称 + * @param projectId 项目 ID + * @return 响应结果 + * @author 王立宏 + * @date 2023/11/14 05:30 + */ + @ApiOperation("执行sql接口") + @PostMapping("/executeSql") + public ResponseResult>> executeSql( + @MyRequestBody String sql, @MyRequestBody String databaseName, @MyRequestBody Long projectId){ + if (projectId == null || StrUtil.isBlank(sql) || StrUtil.isBlank(databaseName)) { + return ResponseResult.error(ErrorCodeEnum.ARGUMENT_NULL_EXIST); + } + ProjectMain projectMain = projectMainService.getByIdWithRelation(projectId, MyRelationParam.full()); + if (projectMain == null || projectMain.getProjectEngineId() == null || projectMain.getProjectEngine() == null) { + return ResponseResult.error(ErrorCodeEnum.DATA_NOT_EXIST, + "数据验证失败,当前 [数据] 并不存在,请刷新后重试!"); + } + ProjectEngine projectEngine = projectMain.getProjectEngine(); + Strategy strategy = strategyFactory.getStrategy( + projectEngine.getEngineType(), projectEngine.getEngineHost(), projectEngine.getEnginePort(), + databaseName, projectEngine.getEngineUsername(), projectEngine.getEnginePassword()); + List> resultData = strategy.executeSqlList(sql); + strategy.closeAll(); + return ResponseResult.success(resultData); + } + } diff --git a/application-webadmin/src/main/java/supie/webadmin/app/controller/RemoteHostController.java b/application-webadmin/src/main/java/supie/webadmin/app/controller/RemoteHostController.java index d0903865ce2de8e16ca42a2be558906fcd57da9f..b03a0de1ca31db25b0fc37d4e2e44001aa35c5ad 100644 --- a/application-webadmin/src/main/java/supie/webadmin/app/controller/RemoteHostController.java +++ b/application-webadmin/src/main/java/supie/webadmin/app/controller/RemoteHostController.java @@ -5,7 +5,6 @@ import supie.common.core.annotation.NoAuthInterface; import supie.common.log.annotation.OperationLog; import supie.common.log.model.constant.SysOperationLogType; import com.github.pagehelper.page.PageMethod; -import supie.webadmin.app.util.remoteshell.JschUtil; import supie.webadmin.app.vo.*; import supie.webadmin.app.dto.*; import supie.webadmin.app.model.*; @@ -173,17 +172,17 @@ public class RemoteHostController { return ResponseResult.success(); } - @PostMapping("/testConnection") - @ApiOperation("测试shh连接测试") - public ResponseResult testConnection(@MyRequestBody RemoteHostDto remoteHostDtoFilter,@MyRequestBody String commands) { - + @ApiOperation("ssh连接测试") + public ResponseResult testConnection( + @MyRequestBody RemoteHostDto remoteHostDtoFilter, @MyRequestBody List commandList) { RemoteHost remoteHostFilter = MyModelUtil.copyTo(remoteHostDtoFilter, RemoteHost.class); - - String data= remoteHostService.testConnection("",remoteHostFilter,commands); - if (data.isEmpty()){ - return ResponseResult.error("500","请联系管理员"); + String resultMessage; + try { + resultMessage = remoteHostService.testConnection(remoteHostFilter, commandList); + } catch (Exception e) { + return ResponseResult.error(ErrorCodeEnum.NO_ERROR, e.getMessage()); } - return ResponseResult.success("成功"); + return ResponseResult.success(resultMessage); } } diff --git a/application-webadmin/src/main/java/supie/webadmin/app/controller/dynamicRoutingAPI/DynamicRoutingController.java b/application-webadmin/src/main/java/supie/webadmin/app/controller/dynamicRoutingAPI/DynamicRoutingController.java new file mode 100644 index 0000000000000000000000000000000000000000..da1882a9af6d15c69bb38d3aef966a0610274575 --- /dev/null +++ b/application-webadmin/src/main/java/supie/webadmin/app/controller/dynamicRoutingAPI/DynamicRoutingController.java @@ -0,0 +1,111 @@ +package supie.webadmin.app.controller.dynamicRoutingAPI; + +import cn.hutool.json.JSONUtil; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.mvc.method.RequestMappingInfo; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; +import org.springframework.web.util.pattern.PathPatternParser; +import supie.common.core.annotation.MyRequestBody; +import supie.common.core.object.ResponseResult; +import supie.common.core.util.ApplicationContextHolder; + +import java.lang.reflect.Method; +import java.util.Map; + +/** + * 描述: + * + * @author 王立宏 + * @date 2023/11/15 15:08 + * @path SDT-supie.webadmin.app.controller.dynamicRoutingAPI-DynamicRoutingController + */ +@Slf4j +@RestController +@ApiOperation("动态路由测试") +public class DynamicRoutingController { + + private static RequestMappingHandlerMapping requestMappingHandlerMapping = null; + + @PostMapping("/registerApi") + public String registerApi( + @MyRequestBody String path, @MyRequestBody Map params) throws NoSuchMethodException { +// RequestMappingInfo.BuilderConfiguration builderConfiguration = new RequestMappingInfo.BuilderConfiguration(); +// builderConfiguration.setPatternParser(new PathPatternParser()); +// +// RequestMappingInfo mappingInfo = RequestMappingInfo +// .paths(path) +// .methods(RequestMethod.GET) +// .options(builderConfiguration) +// .build(); + log.warn("添加路由[" + path + "]"); + RequestMappingInfo mappingInfo = RequestMappingInfo + .paths(path) + .methods(RequestMethod.POST) + .build(); + + // 反射获取ExampleController中的hello方法,用于执行实际逻辑 + Method method = MyDynamicController.class.getDeclaredMethod("test", Map.class); + + // 使用SpringRouterUtils注册这个新的路由 +// ApplicationContextHolder.register(mappingInfo, new MyDynamicController(), method); + if (requestMappingHandlerMapping == null) { +// requestMappingHandlerMapping = (RequestMappingHandlerMapping) applicationContext.getBean("requestMappingHandlerMapping"); +// requestMappingHandlerMapping = applicationContext.getBean(RequestMappingHandlerMapping.class); + requestMappingHandlerMapping = ApplicationContextHolder.getBean("requestMappingHandlerMapping"); +// requestMappingHandlerMapping = ApplicationContextHolder.getBean(requestMappingHandlerMapping.class); + } + MyDynamicController myDynamicController = ApplicationContextHolder.getBean(MyDynamicController.class); + requestMappingHandlerMapping.registerMapping(mappingInfo, myDynamicController, method); + + return "SUCCESS"; + } + + @PostMapping("/removeApi") + public String removeApi(@MyRequestBody String path) throws NoSuchMethodException { +// RequestMappingInfo.BuilderConfiguration builderConfiguration = new RequestMappingInfo.BuilderConfiguration(); +// builderConfiguration.setPatternParser(new PathPatternParser()); +// +// RequestMappingInfo mappingInfo = RequestMappingInfo +// .paths(path) +// .methods(RequestMethod.GET) +// .options(builderConfiguration) +// .build(); + + // 使用SpringRouterUtils注册这个新的路由 +// ApplicationContextHolder.remove(mappingInfo); + if (requestMappingHandlerMapping == null) { +// requestMappingHandlerMapping = (RequestMappingHandlerMapping) applicationContext.getBean("requestMappingHandlerMapping"); +// requestMappingHandlerMapping = applicationContext.getBean(RequestMappingHandlerMapping.class); + requestMappingHandlerMapping = ApplicationContextHolder.getBean("requestMappingHandlerMapping"); +// requestMappingHandlerMapping = ApplicationContextHolder.getBean(RequestMappingHandlerMapping.class); + } +// requestMappingHandlerMapping.unregisterMapping(mappingInfo); + + RequestMappingInfo requestMappingInfo = requestMappingHandlerMapping.getHandlerMethods().keySet().stream() + .filter(mapping -> mapping.getPatternsCondition().getPatterns().contains(path)) + .findFirst() + .orElse(null); + log.warn("删除路由[" + path + "]"); + // 删除指定路径的映射 + requestMappingHandlerMapping.unregisterMapping(requestMappingInfo); + + return "SUCCESS"; + } + + @GetMapping("/getAllMappings") + public ResponseResult getAllMappings() { + if (requestMappingHandlerMapping == null) { + requestMappingHandlerMapping = ApplicationContextHolder.getBean("requestMappingHandlerMapping"); + } + Map handlerMethods = requestMappingHandlerMapping.getHandlerMethods(); + return ResponseResult.success(JSONUtil.toJsonStr(handlerMethods)); + } + +} diff --git a/application-webadmin/src/main/java/supie/webadmin/app/controller/dynamicRoutingAPI/MyDynamicController.java b/application-webadmin/src/main/java/supie/webadmin/app/controller/dynamicRoutingAPI/MyDynamicController.java new file mode 100644 index 0000000000000000000000000000000000000000..019ff0810a307ea2a41978ca2e9f268dff7dd4de --- /dev/null +++ b/application-webadmin/src/main/java/supie/webadmin/app/controller/dynamicRoutingAPI/MyDynamicController.java @@ -0,0 +1,41 @@ +package supie.webadmin.app.controller.dynamicRoutingAPI; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.json.JSONUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; +import org.springframework.web.bind.annotation.ResponseBody; +import supie.common.core.annotation.MyRequestBody; +import supie.common.core.object.ResponseResult; + +import java.util.Map; + +/** + * 描述: + * + * @author 王立宏 + * @date 2023/11/15 15:17 + * @path SDT-supie.webadmin.app.controller.dynamicRoutingAPI-MyDynamicController + */ +@Slf4j +@Component +public class MyDynamicController { + + private static int sum = 0; + +// @ResponseBody +// public String test(String name) { +// sum++; +// log.error("==============》第[" + sum + "]次调用自定义接口《=============="); +// return DateUtil.now() + "<--[" + sum + "]-->" + name; +// } + + public ResponseResult test(@MyRequestBody Map params) { + sum++; + log.error("==============》第[" + sum + "]次调用自定义接口《=============="); + params.put("nowDate", DateUtil.now()); + params.put("sum", sum); + return ResponseResult.success(JSONUtil.toJsonStr(params)); + } + +} diff --git a/application-webadmin/src/main/java/supie/webadmin/app/controller/dynamicRoutingAPI/RouteManager.java b/application-webadmin/src/main/java/supie/webadmin/app/controller/dynamicRoutingAPI/RouteManager.java new file mode 100644 index 0000000000000000000000000000000000000000..4e00742d72d5e00ee6b9c8b8c0f1f6815f5be592 --- /dev/null +++ b/application-webadmin/src/main/java/supie/webadmin/app/controller/dynamicRoutingAPI/RouteManager.java @@ -0,0 +1,31 @@ +//package supie.webadmin.app.controller.dynamicRoutingAPI; +// +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.stereotype.Component; +//import org.springframework.web.servlet.mvc.method.RequestMappingInfo; +//import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; +// +///** +// * 描述: +// * +// * @author 王立宏 +// * @date 2023/11/15 16:53 +// * @path SDT-supie.webadmin.app.controller.dynamicRoutingAPI-RouteManager +// */ +//@Component +//public class RouteManager { +// +// @Autowired +// private RequestMappingHandlerMapping requestMappingHandlerMapping; +// +// public void addRoute(String path) { +// +// requestMappingHandlerMapping.registerMapping(requestMappingInfo); +// } +// +// public void removeRoute(String path) { +// +// requestMappingHandlerMapping.unregisterMapping(requestMappingInfo); +// } +// +//} diff --git a/application-webadmin/src/main/java/supie/webadmin/app/controller/dynamicRoutingAPI/SpringRouterUtil.java b/application-webadmin/src/main/java/supie/webadmin/app/controller/dynamicRoutingAPI/SpringRouterUtil.java new file mode 100644 index 0000000000000000000000000000000000000000..396f8fc793f07809fd4daaa6dc6b83da9741c46f --- /dev/null +++ b/application-webadmin/src/main/java/supie/webadmin/app/controller/dynamicRoutingAPI/SpringRouterUtil.java @@ -0,0 +1,32 @@ +//package supie.webadmin.app.controller.dynamicRoutingAPI; +// +//import org.springframework.beans.factory.annotation.Autowired; +//import org.springframework.stereotype.Component; +//import org.springframework.web.servlet.mvc.method.RequestMappingInfo; +//import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; +// +//import java.lang.reflect.Method; +// +///** +// * 描述: +// * +// * @author 王立宏 +// * @date 2023/11/15 15:14 +// * @path SDT-supie.webadmin.app.controller.dynamicRoutingAPI-SpringRouterUtil +// */ +//@Component +//public class SpringRouterUtil { +// +// // 这个静态变量用于存储RequestMappingHandlerMapping实例,它是Spring MVC用于管理所有路由(或称为请求映射)的组件 +// @Autowired +// private RequestMappingHandlerMapping requestMappingHandlerMapping; +// +// public void register(RequestMappingInfo requestMappingInfo, Object handler, Method method){ +//// requestMappingHandlerMapping.registerMapping(requestMappingInfo, handler, method); +// } +// +// public void remove(RequestMappingInfo requestMappingInfo){ +//// requestMappingHandlerMapping.unregisterMapping(requestMappingInfo); +// } +// +//} diff --git a/application-webadmin/src/main/java/supie/webadmin/app/liteFlow/QuartzJobCheckCycle.java b/application-webadmin/src/main/java/supie/webadmin/app/liteFlow/QuartzJobCheckCycle.java index 1ada2e674eb04f4dad1b06b1c8e8d5d0a6cb3a0f..9f7b0f07aeb2b7a19c356ee6aae8b4f0a0bbed6d 100644 --- a/application-webadmin/src/main/java/supie/webadmin/app/liteFlow/QuartzJobCheckCycle.java +++ b/application-webadmin/src/main/java/supie/webadmin/app/liteFlow/QuartzJobCheckCycle.java @@ -83,6 +83,7 @@ public class QuartzJobCheckCycle implements Job { if (response.isSuccess()) { Integer successNumber = schedulingTasks.getSuccessNumber(); if (null == successNumber) successNumber = 0; + schedulingTasks.setTaskState("正常"); schedulingTasks.setSuccessNumber(successNumber + 1); liteflowLog.setRunResult("成功"); String successMessage = "任务[" + schedulingTasksId + "]的规则链[" + rulerId + "]执行成功!"; diff --git a/application-webadmin/src/main/java/supie/webadmin/app/liteFlow/node/BaseNode.java b/application-webadmin/src/main/java/supie/webadmin/app/liteFlow/node/BaseNode.java index d5776b83574f71e73fa1f3b43a34bfd89b52f51a..0c2df26d6690a40f8cf756e54679e7e2ba00e535 100644 --- a/application-webadmin/src/main/java/supie/webadmin/app/liteFlow/node/BaseNode.java +++ b/application-webadmin/src/main/java/supie/webadmin/app/liteFlow/node/BaseNode.java @@ -55,7 +55,7 @@ public abstract class BaseNode extends NodeComponent{ nodeLog = this.getContextBean(LinkedList.class); devLiteflowNode = devLiteflowNodeMapper.queryNode(rulerId, nodeId, nodeTag); int status = devLiteflowNode.getStatus(); - nodeLog.add(LiteFlowNodeLogModel.info(nodeId, nodeTag, "节点[" + nodeId + ".tag(" + nodeTag + ")]的启用状态:" + (status == 1))); + nodeLog.add(LiteFlowNodeLogModel.info(nodeId, nodeTag, "节点[" + nodeId + ".tag(" + nodeTag + ")]的启用状态:" + (status == 1))); return status == 1; } diff --git a/application-webadmin/src/main/java/supie/webadmin/app/liteFlow/node/DataTransferNode.java b/application-webadmin/src/main/java/supie/webadmin/app/liteFlow/node/DataTransferNode.java index 8804b33c019f0417f37be57c71b1d101d1e2e925..f1b609035f6ee253292caef076a2cd8166787251 100644 --- a/application-webadmin/src/main/java/supie/webadmin/app/liteFlow/node/DataTransferNode.java +++ b/application-webadmin/src/main/java/supie/webadmin/app/liteFlow/node/DataTransferNode.java @@ -8,7 +8,6 @@ import cn.hutool.http.HttpRequest; import cn.hutool.http.HttpResponse; import cn.hutool.json.JSONUtil; import com.yomahub.liteflow.annotation.LiteflowComponent; -import com.yomahub.liteflow.core.NodeComponent; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -18,19 +17,17 @@ import supie.webadmin.app.liteFlow.model.DataTransferModel; import supie.webadmin.app.liteFlow.model.ErrorMessageModel; import supie.webadmin.app.liteFlow.model.LiteFlowNodeLogModel; import supie.webadmin.app.model.*; -import supie.webadmin.app.util.remoteshell.JschUtil; -import supie.webadmin.app.util.remoteshell.SSHConfig; +import supie.webadmin.app.util.remoteshell.RemoteShell; +import supie.webadmin.app.util.remoteshell.impl.RemoteShellSshjImpl; import java.io.*; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Date; -import java.util.LinkedList; -import java.util.List; /** - * 描述: + * 描述: * * @author 王立宏 * @date 2023/10/22 9:09 @@ -63,12 +60,12 @@ public class DataTransferNode extends BaseNode { public void beforeProcess() { dataTransferModel = JSONUtil.toBean(devLiteflowNode.getFieldJsonData(), DataTransferModel.class); if (dataTransferModel.getSeaTunnelId() == null) { - nodeLog.add(LiteFlowNodeLogModel.error(nodeId, nodeTag, "未配置该节点需要的SeaTunnel!")); + nodeLog.add(LiteFlowNodeLogModel.error(nodeId, nodeTag, "未配置该节点需要的SeaTunnel!")); } seatunnelConfigModel = seatunnelConfigMapper.selectById(dataTransferModel.getSeaTunnelId()); if (seatunnelConfigModel == null) { nodeLog.add(LiteFlowNodeLogModel.error(nodeId, nodeTag, - "未查询到ID为[" + dataTransferModel.getSeaTunnelId() + "]的SeaTunnel配置数据!")); + "未查询到ID为[" + dataTransferModel.getSeaTunnelId() + "]的SeaTunnel配置数据!")); } } @@ -90,7 +87,7 @@ public class DataTransferNode extends BaseNode { if (seatunnelConfigModel.getSubmitJobUrl() == null) { seatunnelConfigModel.setSubmitJobUrl(new SeatunnelConfig().getSubmitJobUrl()); nodeLog.add(LiteFlowNodeLogModel.info(nodeId, nodeTag, - "未配置Seatunnel提交Job的接口地址,使用默认地址:" + seatunnelConfigModel.getSubmitJobUrl())); + "未配置Seatunnel提交Job的接口地址,使用默认地址:" + seatunnelConfigModel.getSubmitJobUrl())); } StringBuilder url = new StringBuilder(seatunnelConfigModel.getLocalhostUri()); // 判断字符串第一个字符是否为"/" @@ -110,56 +107,55 @@ public class DataTransferNode extends BaseNode { if (dataTransferModel.getIsStartWithSavePoint() != null) { url.append("isStartWithSavePoint=").append(dataTransferModel.getIsStartWithSavePoint()); } - nodeLog.add(LiteFlowNodeLogModel.info(nodeId, nodeTag, "提交Job:" + url.toString())); + nodeLog.add(LiteFlowNodeLogModel.info(nodeId, nodeTag, "提交Job:" + url.toString())); HttpResponse execute = null; try { execute = HttpRequest.post(url.toString()) .body(dataTransferModel.getSeaTunnelConfig()) .execute(); } catch (Exception e) { - String errorMessage = "RestApi(" + url.toString() + ")调用报错:" + e.getMessage(); - nodeLog.add(LiteFlowNodeLogModel.error(nodeId, nodeTag, "执行失败:" + errorMessage)); + String errorMessage = "RestApi(" + url.toString() + ")调用报错:" + e.getMessage(); + nodeLog.add(LiteFlowNodeLogModel.error(nodeId, nodeTag, "执行失败:" + errorMessage)); throw new MyLiteFlowException(new ErrorMessageModel(getClass(), errorMessage)); } String body = URLUtil.decode(execute.body()); // 存储执行信息 - if (body == null) body = "无回执结果信息!"; + if (body == null) body = "无回执结果信息!"; devLiteflowNodeMapper.setExecutionMessage(this.rulerId, this.nodeId, this.nodeTag, body); if (!execute.isOk()) { // 失败 - nodeLog.add(LiteFlowNodeLogModel.error(nodeId, nodeTag, "执行失败:" + body)); + nodeLog.add(LiteFlowNodeLogModel.error(nodeId, nodeTag, "执行失败:" + body)); throw new MyLiteFlowException(new ErrorMessageModel(getClass(), body)); } else { - nodeLog.add(LiteFlowNodeLogModel.info(nodeId, nodeTag, "执行成功:" + body)); + nodeLog.add(LiteFlowNodeLogModel.info(nodeId, nodeTag, "执行成功:" + body)); } } private void sshSubmitJob() { RemoteHost remoteHost = remoteHostMapper.selectById(seatunnelConfigModel.getRemoteHostId()); // 根据项目ID 获取到该项目的远程服务器的配置 - SSHConfig sshConfig = new SSHConfig(); - sshConfig.setIp(remoteHost.getHostIp()); - sshConfig.setPort(Integer.parseInt(remoteHost.getHostPort())); - sshConfig.setPassword(remoteHost.getPassword()); - JschUtil jschUtil = new JschUtil(sshConfig); + RemoteShell remoteShell = new RemoteShellSshjImpl( + remoteHost.getHostIp(), remoteHost.getHostPort(), + remoteHost.getLoginName(), remoteHost.getPassword(), null); + tempFilePath = "./tempFolder/" + DateUtil.format(new Date(), "yyyy-MM-dd-HH-mm-ss-SSS-") + RandomUtil.randomString(5) + "-config.json"; contentWriteToFile(tempFilePath, JSONUtil.toJsonStr(dataTransferModel.getSeaTunnelConfig())); // 上传配置文件(v2.batch.config.template)至 seatunnel 的 ./config/ 中 String remoteConfigName = "v2.supie.config.json"; String remoteFilePath = seatunnelConfigModel.getSeatunnelPath() + "/config/" + remoteConfigName; - nodeLog.add(LiteFlowNodeLogModel.info(nodeId, nodeTag, "上传Seatunnel配置文件,remoteFilePath:" + remoteFilePath + "。")); - jschUtil.uploadFile(tempFilePath, remoteFilePath); + nodeLog.add(LiteFlowNodeLogModel.info(nodeId, nodeTag, "上传Seatunnel配置文件,remoteFilePath:" + remoteFilePath + "。")); + remoteShell.uploadFile(tempFilePath, remoteFilePath); // 执行命令 nodeLog.add(LiteFlowNodeLogModel.info(nodeId, nodeTag, - "开始执行Seatunnel命令:[\"cd " + seatunnelConfigModel.getSeatunnelPath() + + "开始执行Seatunnel命令:[\"cd " + seatunnelConfigModel.getSeatunnelPath() + "\", \"sh bin/seatunnel.sh --config config/" + remoteConfigName + " -e local\"]")); - String resultMsg = jschUtil.executeRemoteCommand( - null, + String resultMsg = remoteShell.execCommands( "cd " + seatunnelConfigModel.getSeatunnelPath(), "sh bin/seatunnel.sh --config config/" + remoteConfigName + " -e local"); + remoteShell.close(); // 存储执行结果信息 - if (resultMsg == null) resultMsg = "无回执结果信息!"; + if (resultMsg == null) resultMsg = "无回执结果信息!"; nodeLog.add(LiteFlowNodeLogModel.warn(nodeId, nodeTag, resultMsg)); devLiteflowNodeMapper.setExecutionMessage(this.rulerId, this.nodeId, this.nodeTag, resultMsg); // 删除创建的临时文件 diff --git a/application-webadmin/src/main/java/supie/webadmin/app/liteFlow/node/ShellNode.java b/application-webadmin/src/main/java/supie/webadmin/app/liteFlow/node/ShellNode.java index b1b698e84f39eb3adfa931a6c3fd533e4b8dd159..7a01fedbff62f9671f3d4f1e068412394f09f7fa 100644 --- a/application-webadmin/src/main/java/supie/webadmin/app/liteFlow/node/ShellNode.java +++ b/application-webadmin/src/main/java/supie/webadmin/app/liteFlow/node/ShellNode.java @@ -2,25 +2,17 @@ package supie.webadmin.app.liteFlow.node; import cn.hutool.json.JSONUtil; import com.yomahub.liteflow.annotation.LiteflowComponent; -import com.yomahub.liteflow.core.NodeComponent; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import supie.webadmin.app.dao.DevLiteflowNodeMapper; -import supie.webadmin.app.dao.DevLiteflowRulerMapper; import supie.webadmin.app.dao.RemoteHostMapper; import supie.webadmin.app.liteFlow.exception.MyLiteFlowException; import supie.webadmin.app.liteFlow.model.ErrorMessageModel; import supie.webadmin.app.liteFlow.model.LiteFlowNodeLogModel; -import supie.webadmin.app.liteFlow.model.NodeMessage; import supie.webadmin.app.liteFlow.model.SqlAndShellModel; -import supie.webadmin.app.model.DevLiteflowNode; import supie.webadmin.app.model.RemoteHost; -import supie.webadmin.app.util.remoteshell.JschUtil; -import supie.webadmin.app.util.remoteshell.SSHConfig; - -import java.util.LinkedList; -import java.util.List; +import supie.webadmin.app.util.remoteshell.RemoteShell; +import supie.webadmin.app.util.remoteshell.impl.RemoteShellSshjImpl; /** * 描述: @@ -43,28 +35,25 @@ public class ShellNode extends BaseNode { public void beforeProcess() { sqlAndShellModel = JSONUtil.toBean(devLiteflowNode.getFieldJsonData(), SqlAndShellModel.class); if (sqlAndShellModel.getSourceId() == null) { - nodeLog.add(LiteFlowNodeLogModel.error(nodeId, nodeTag, "未关联远程主机!")); - throw new MyLiteFlowException(new ErrorMessageModel(getClass(), "未关联远程主机!")); + nodeLog.add(LiteFlowNodeLogModel.error(nodeId, nodeTag, "未关联远程主机!")); + throw new MyLiteFlowException(new ErrorMessageModel(getClass(), "未关联远程主机!")); } remoteHost = remoteHostMapper.selectById(sqlAndShellModel.getSourceId()); if (remoteHost == null) { - nodeLog.add(LiteFlowNodeLogModel.error(nodeId, nodeTag, "未找到关联的远程主机!")); - throw new MyLiteFlowException(new ErrorMessageModel(getClass(), "未找到关联的远程主机!")); + nodeLog.add(LiteFlowNodeLogModel.error(nodeId, nodeTag, "未找到关联的远程主机!")); + throw new MyLiteFlowException(new ErrorMessageModel(getClass(), "未找到关联的远程主机!")); } } @Override public void process() { nodeLog.add(LiteFlowNodeLogModel.info(nodeId, nodeTag, "开始执行SSH脚本")); - SSHConfig sshConfig = new SSHConfig(); - sshConfig.setIp(remoteHost.getHostIp()); - sshConfig.setPort(Integer.parseInt(remoteHost.getHostPort())); - sshConfig.setUserName(remoteHost.getLoginName()); - sshConfig.setPassword(remoteHost.getPassword()); - sshConfig.setKey(remoteHost.getHostKeyFilePath()); - JschUtil jschUtil = new JschUtil(sshConfig); try { - String resultData = jschUtil.executeRemoteCommand(sqlAndShellModel.getScript()); + RemoteShell remoteShell = new RemoteShellSshjImpl( + remoteHost.getHostIp(), remoteHost.getHostPort(), + remoteHost.getLoginName(), remoteHost.getPassword(), null); + String resultData = remoteShell.execCommands(sqlAndShellModel.getScript()); + remoteShell.close(); nodeLog.add(LiteFlowNodeLogModel.info(nodeId, nodeTag, resultData)); } catch (Exception e) { nodeLog.add(LiteFlowNodeLogModel.error(nodeId, nodeTag, e.getMessage())); diff --git a/application-webadmin/src/main/java/supie/webadmin/app/liteFlow/node/SqlNode.java b/application-webadmin/src/main/java/supie/webadmin/app/liteFlow/node/SqlNode.java index 1c43dd87097b295ab96b2e019b4dc60c8ac82075..79285f132c668274ae3334d19d896f63921cda5b 100644 --- a/application-webadmin/src/main/java/supie/webadmin/app/liteFlow/node/SqlNode.java +++ b/application-webadmin/src/main/java/supie/webadmin/app/liteFlow/node/SqlNode.java @@ -19,7 +19,7 @@ import java.util.List; import java.util.Map; /** - * 描述:用于执行客户自定义的SQL语句 + * 描述:用于执行客户自定义的SQL语句 * * @author 王立宏 * @date 2023/10/22 14:32 @@ -40,35 +40,35 @@ public class SqlNode extends BaseNode { @Override public void beforeProcess() { - nodeLog.add(LiteFlowNodeLogModel.info(nodeId, nodeTag, "进入SqlNode-beforeProcess!")); + nodeLog.add(LiteFlowNodeLogModel.info(nodeId, nodeTag, "进入SqlNode-beforeProcess!")); sqlAndShellModel = JSONUtil.toBean(devLiteflowNode.getFieldJsonData(), SqlAndShellModel.class); if (sqlAndShellModel.getSourceId() == null) { - nodeLog.add(LiteFlowNodeLogModel.error(nodeId, nodeTag, "未关联数据源!")); - throw new MyLiteFlowException(new ErrorMessageModel(getClass(), "未关联数据源!")); + nodeLog.add(LiteFlowNodeLogModel.error(nodeId, nodeTag, "未关联数据源!")); + throw new MyLiteFlowException(new ErrorMessageModel(getClass(), "未关联数据源!")); } projectDatasource = projectDatasourceMapper.selectById(sqlAndShellModel.getSourceId()); if (projectDatasource == null) { - nodeLog.add(LiteFlowNodeLogModel.error(nodeId, nodeTag, "未找到数据源!")); - throw new MyLiteFlowException(new ErrorMessageModel(getClass(), "未找到数据源!")); + nodeLog.add(LiteFlowNodeLogModel.error(nodeId, nodeTag, "未找到数据源!")); + throw new MyLiteFlowException(new ErrorMessageModel(getClass(), "未找到数据源!")); } datasourceContentModel = JSONUtil.toBean(projectDatasource.getDatasourceContent(), DatasourceContentModel.class); } @Override public void process() throws Exception { - nodeLog.add(LiteFlowNodeLogModel.warn(nodeId, nodeTag, "进入SqlNode-process!")); + nodeLog.add(LiteFlowNodeLogModel.warn(nodeId, nodeTag, "进入SqlNode-process!")); Strategy strategy = null; try { strategy = strategyFactory.getStrategy( datasourceContentModel.getDatabaseType(), datasourceContentModel.getIp(), datasourceContentModel.getPort(), datasourceContentModel.getDatabaseName(), datasourceContentModel.getUsername(), datasourceContentModel.getPassword()); } catch (Exception e) { - nodeLog.add(LiteFlowNodeLogModel.error(nodeId, nodeTag, "获取数据库连接失败!" + e)); - throw new MyLiteFlowException(new ErrorMessageModel(getClass(), "获取数据库连接失败!" + e)); + nodeLog.add(LiteFlowNodeLogModel.error(nodeId, nodeTag, "获取数据库连接失败!" + e)); + throw new MyLiteFlowException(new ErrorMessageModel(getClass(), "获取数据库连接失败!" + e)); } List> resultData = strategy.executeSqlList(sqlAndShellModel.getScript()); strategy.closeAll(); - nodeLog.add(LiteFlowNodeLogModel.info(nodeId, nodeTag, "SQL执行结果为:" + JSONUtil.toJsonStr(resultData))); + nodeLog.add(LiteFlowNodeLogModel.info(nodeId, nodeTag, "SQL执行结果为:" + JSONUtil.toJsonStr(resultData))); devLiteflowNodeMapper.setExecutionMessage(rulerId, nodeId, nodeTag, JSONUtil.toJsonStr(resultData)); } diff --git a/application-webadmin/src/main/java/supie/webadmin/app/service/RemoteHostService.java b/application-webadmin/src/main/java/supie/webadmin/app/service/RemoteHostService.java index a3cbf2a7292223775c5e0474e9d77833bc67cb79..c5176d9b6ad44f5e699830c74de2e3fddc17a5d7 100644 --- a/application-webadmin/src/main/java/supie/webadmin/app/service/RemoteHostService.java +++ b/application-webadmin/src/main/java/supie/webadmin/app/service/RemoteHostService.java @@ -82,5 +82,5 @@ public interface RemoteHostService extends IBaseService { */ List getRemoteHostListWithRelation(RemoteHost filter, String orderBy); - String testConnection(String logFilePath, RemoteHost remoteHost, String commands); + String testConnection(RemoteHost remoteHostFilter, List commandList); } diff --git a/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/QueryTheData.java b/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/QueryTheData.java index 03827d0a809821f2db7e32495d80520e434b1f2c..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/QueryTheData.java +++ b/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/QueryTheData.java @@ -1,119 +0,0 @@ -package supie.webadmin.app.service.databasemanagement; - -import lombok.extern.slf4j.Slf4j; - -import java.sql.*; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * 查询数据库的表操作-----公共类 - * @author zhiwuzhu - */ -@Slf4j -public class QueryTheData { - - /** - * 根据传入的数据源类型,创建Connection连接信息并查询对应的表 - * - * @param jdbcDriver 数据库类型 - * @param jdbcUrl 数据库链接地址 - * @param userName 用户名 - * @param passWord 密码 - * @param targetDatabase 目标数据库 - * @param autoCommit 是否自动提交 - * @author litao - */ - - public static List> queryDatabaseTable(String jdbcDriver, String jdbcUrl, String userName, String passWord,String targetDatabase, boolean autoCommit) throws Exception { - Connection conn = null; - try { - Class.forName(jdbcDriver); - // 连接数据库 - conn = DriverManager.getConnection(jdbcUrl, userName, passWord); - - // 查询表中所有表名和字段相关信息 - List> queryTableNames = queryTables(conn,targetDatabase); - conn.setAutoCommit(autoCommit); - return queryTableNames; - } catch (ClassNotFoundException se) { - // 连接失败 - log.error("找不到驱动程序类", se); - throw new Exception("找不到驱动程序类"); - } catch (SQLException se) { - // 连接失败 - log.error("连接失败", se); - throw new Exception("连接失败"); - } finally { - // 关闭数据库连接 - if (conn != null) { - try { - conn.close(); - } catch (SQLException e) { - e.printStackTrace(); - } - } - } - - } - - /** - * 根据connection查询该数据库连接的所有数据库表 - * - * @param connection 数据库类型 - * @author litao - */ - public static List> queryTables(Connection connection,String targetDatabase ) throws SQLException { - DatabaseMetaData metaData = connection.getMetaData(); - - // 获取数据库的表 - ResultSet resultSet = metaData.getTables(targetDatabase, null, null, new String[]{"TABLE"}); - - ArrayList> tableList = new ArrayList<>(); - // 循环TABLE,将结果记录在Map中 - while (resultSet.next()) { - HashMap tableMap = new HashMap<>(); - // 表名 - String tableName = resultSet.getString("TABLE_NAME"); - // 注释 - String tableComment = resultSet.getString("REMARKS"); - tableMap.put("tableName",tableName); - tableMap.put("remarks",tableComment); - tableList.add(tableMap); - } - resultSet.close(); - return tableList; - } - - /** - * 根据数据表查询数据 - * @param connection 数据库类型 - * @param tableName 表名 - * @throws SQLException - */ - private static void queryTable(Connection connection, String tableName) throws SQLException { - String sql = "SELECT * FROM " + tableName; - Statement statement = connection.createStatement(); - ResultSet resultSet = statement.executeQuery(sql); - ResultSetMetaData metaData = resultSet.getMetaData(); - - int columnCount = metaData.getColumnCount(); - for (int i = 1; i <= columnCount; i++) { - System.out.print(metaData.getColumnName(i) + "\t"); - } - System.out.println(); - - while (resultSet.next()) { - for (int i = 1; i <= columnCount; i++) { - System.out.print(resultSet.getString(i) + "\t"); - } - System.out.println(); - } - - resultSet.close(); - statement.close(); - } - -} diff --git a/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/Strategy.java b/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/Strategy.java index 43bf49b75107962db55becc13041fc73331e330f..835863b59e50ba08191f3740ccf00af20985c574 100644 --- a/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/Strategy.java +++ b/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/Strategy.java @@ -24,15 +24,19 @@ public interface Strategy { void initStrategy(String hostIp, String hostPort, String databaseName, String userName, String password); /** - * 查询数据库数据表名及类型 + * 关闭连接 */ - List> queryDatabaseTable(DatabaseManagement databaseManagement) throws Exception; + void closeAll(); + /** + * 查询数据库数据表名及类型 + */ + List> queryDatabaseTable(String databaseName); /** * 查询数据库数据的字段名及类型 */ - List> queryTableFields(DatabaseManagement databaseManagement) throws Exception; + List> queryTableFields(String databaseName, String tableName); /** * 执行位置数量的SQL @@ -49,6 +53,15 @@ public interface Strategy { */ List> executeSqlList(String sql); + /** + * 查询可操作的所有数据库名称 + * + * @return 该账户可操作的所有数据库集 + * @author 王立宏 + * @date 2023/11/14 03:57 + */ + List queryAllDatabaseName(); + /** * 创建数据库 * @@ -58,11 +71,6 @@ public interface Strategy { */ void createDatabase(String databaseName); - /** - * 关闭连接 - */ - void closeAll(); - /** * 获取表结构 * @param tableName 表名 diff --git a/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/BaseDataSource.java b/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/BaseDataSource.java index 022b3706b47a288731a24aaec0ad2fb93fd5dd4b..923ffbf704f52a65a6b7631b02134d556b9649ed 100644 --- a/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/BaseDataSource.java +++ b/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/BaseDataSource.java @@ -9,7 +9,6 @@ import java.sql.*; import java.util.*; import static cn.hutool.db.DbUtil.close; -import static supie.application.common.constant.DataSource.*; /** * 描述: @@ -58,9 +57,9 @@ public class BaseDataSource { * 数据库连接对象 */ protected Connection connection = null; - protected Statement statement = null; - protected PreparedStatement preparedStatement = null; - protected ResultSet resultSet = null; +// protected Statement statement = null; +// protected PreparedStatement preparedStatement = null; +// protected ResultSet resultSet = null; /** * 连接数据库 @@ -83,7 +82,8 @@ public class BaseDataSource { * @date 2023/10/30 10:58 */ public void closeAll() { - close(resultSet, preparedStatement, statement, connection); +// close(resultSet, preparedStatement, statement, connection); + close(connection); } /** @@ -103,14 +103,14 @@ public class BaseDataSource { List sqlList = StrSplitter.split(sql, ";", 0, true, true); List> resultDataList = new LinkedList<>(); try { - statement = connection.createStatement(); + Statement statement = connection.createStatement(); for (String sqlOne : sqlList) { Map resultMapData = new HashMap<>(); resultMapData.put("sql", sqlOne); try { boolean result = statement.execute(sqlOne); if (result) { - resultSet = statement.getResultSet(); // 查询结果 + ResultSet resultSet = statement.getResultSet(); // 查询结果 ResultSetMetaData metaData = resultSet.getMetaData(); Map queryResultData = new LinkedHashMap<>(); @@ -129,10 +129,13 @@ public class BaseDataSource { for (int i = 1; i <= columnCount; i++) { // 获取字段名 String columnName = metaData.getColumnName(i); + if (StrUtil.isBlankIfStr(columnName)) continue; + if (StrUtil.isBlankIfStr(resultSet)) { + throw new RuntimeException("resultSet为空"); + } // 获取字段值 - Object columnValue = resultSet.getObject(i); + Object columnValue = resultSet.getObject(columnName); // 存入字段名和字段值 - if (StrUtil.isBlankIfStr(columnName)) continue; if (setFieldList) fieldList.add(columnName); queryDataMap.put(columnName, columnValue); } @@ -162,4 +165,144 @@ public class BaseDataSource { return resultDataList; } + /** + * 创建数据库 + * + * @param databaseName 创建的数据库的名称 + * @author 王立宏 + * @date 2023/11/02 04:30 + */ + public void createDatabase(String databaseName) { + String createDatabaseSql = "CREATE DATABASE " + databaseName + ";"; + List> resultDataList = executeSqlList(createDatabaseSql); + Map resultMap = resultDataList.get(0); + if (Boolean.TRUE.equals(resultMap.get("isSuccess")) && ((int) resultMap.get("updateResultData") == 1)) return; + throw new RuntimeException("数据库创建[" + resultMap.get("sql") + "]失败!" + resultMap.get("message").toString()); + } + + /** + * 查询数据库数据表名及类型 + * @param databaseName + * @return + */ + public List> queryDatabaseTable(String databaseName) { + ArrayList> tableList = new ArrayList<>(); + try { + DatabaseMetaData metaData = connection.getMetaData(); + ResultSet resultSet = metaData.getTables(databaseName, null, null, new String[]{"TABLE"}); + + // 循环TABLE,将结果记录在Map中 + while (resultSet.next()) { + HashMap tableMap = new HashMap<>(); + // 表名 + String tableName = resultSet.getString("TABLE_NAME"); + // 注释 + String tableComment = resultSet.getString("REMARKS"); + tableMap.put("tableName",tableName); + tableMap.put("remarks",tableComment); + tableList.add(tableMap); + } + resultSet.close(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + return tableList; + } + + /** + * 查询数据库数据的字段名及类型 + * @param databaseName + * @param tableName + * @return + */ + public List> queryTableFields(String databaseName, String tableName) { + List> resultData = null; + try { + DatabaseMetaData metaData = connection.getMetaData(); + // 字段 + ResultSet resultSet = metaData.getColumns(databaseName, null, tableName, null); + resultData = new ArrayList<>(); + while (resultSet.next()) { + HashMap dataTypeMap = new HashMap<>(); + // 字段名 + String columnName = resultSet.getString("COLUMN_NAME"); + // 字段类型 + String dataType = resultSet.getString("TYPE_NAME"); + // 字段大小 + int columnSize = resultSet.getInt("COLUMN_SIZE"); + // 字段注释 + String columnComment = resultSet.getString("REMARKS"); + // 下面是获取关于列级别的信息 + // 获取列的名称:resultSet.getString("COLUMN_NAME") + // 获取列的标签(别名):resultSet.getString("LABEL") + // 获取列的显示大小:resultSet.getInt("COLUMN_DISPLAY_SIZE") + // 获取列的数据类型的编号:resultSet.getInt("DATA_TYPE") + // 获取列的数据类型的名称:resultSet.getString("TYPE_NAME") + // 获取列的精度:resultSet.getInt("PRECISION") + // 获取列的小数位数:resultSet.getInt("SCALE") + // 获取列是否为只读:resultSet.getBoolean("IS_READONLY") + // 获取列是否自动递增:resultSet.getBoolean("IS_AUTOINCREMENT") + + dataTypeMap.put("fieldName",columnName); + dataTypeMap.put("typeName",dataType); + dataTypeMap.put("columnSize",columnSize); + dataTypeMap.put("remarks",columnComment); + resultData.add(dataTypeMap); + } + resultSet.close(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + return resultData; + } + + public List queryAllDatabaseName() { + List databaseNameList = new ArrayList<>(); + try { + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery("SHOW DATABASES;"); + ResultSetMetaData metaData = resultSet.getMetaData(); + while (resultSet.next()) { + databaseNameList.add(resultSet.getString(1)); + } + resultSet.close(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + return databaseNameList; + } + + /** + * 获取表结构 + * + * @param tableName 表名 + */ + public List> queryTableStructure(String tableName) { + List> resultData = new ArrayList<>(); + try { + DatabaseMetaData metaData = connection.getMetaData(); + ResultSet resultSet = metaData.getColumns(null, null, tableName, null); + // 5. 处理结果集,提取表结构信息 + while (resultSet.next()) { + Map fieldMap = new HashMap<>(); + ResultSetMetaData resultSetMetaData = resultSet.getMetaData(); + // 获取字段数量 + int columnCount = resultSetMetaData.getColumnCount(); + // 遍历每个字段 + for (int i = 1; i <= columnCount; i++) { + // 获取字段名 + String columnName = resultSetMetaData.getColumnName(i); + // 获取字段值 + Object columnValue = resultSet.getObject(i); + fieldMap.put(columnName, columnValue); + } + resultData.add(fieldMap); + } + resultSet.close(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + return resultData; + } + } diff --git a/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceDB2.java b/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceDB2.java index 78434e792f17077ddc621dd642a8c3cd9965ee62..caf4451924bc2feba5a85d5c443a4424f1e0c6d3 100644 --- a/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceDB2.java +++ b/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceDB2.java @@ -1,5 +1,6 @@ package supie.webadmin.app.service.databasemanagement.strategyImpl; +import cn.hutool.core.util.StrUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -33,7 +34,11 @@ public class DataSourceDB2 extends BaseDataSource implements Strategy { public void initStrategy(String hostIp, String hostPort, String databaseName, String userName, String password) { this.databaseType = DataBaseTypeEnum.DATASOURCE_DB2; this.jdbcDriver = "com.ibm.db2.jcc.DB2Driver"; - this.jdbcUrl = "jdbc:db2://" + hostIp + ":" + hostPort + ";DatabaseName=" + databaseName; + if (StrUtil.isBlank(databaseName)) { + this.jdbcUrl = "jdbc:db2://" + hostIp + ":" + hostPort; + } else { + this.jdbcUrl = "jdbc:db2://" + hostIp + ":" + hostPort + "/" + databaseName; + } this.hostIp = hostIp; this.hostPort = hostPort; this.databaseName = databaseName; @@ -43,35 +48,4 @@ public class DataSourceDB2 extends BaseDataSource implements Strategy { initConnection(); } - @Override - public List> queryDatabaseTable(DatabaseManagement databaseManagement) throws Exception { - return null; - } - - @Override - public List> queryTableFields(DatabaseManagement databaseManagement) throws Exception { - return null; - } - - /** - * 创建数据库 - * - * @param databaseName 创建的数据库的名称 - * @author 王立宏 - * @date 2023/11/02 04:30 - */ - @Override - public void createDatabase(String databaseName) { - } - - /** - * 获取表结构 - * - * @param tableName 表名 - */ - @Override - public List> queryTableStructure(String tableName) { - return null; - } - } diff --git a/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceDM.java b/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceDM.java index b2699f043271061053b637f33e322aea9a709153..6495d351c2c44d3f685f53624cee49272afd8b60 100644 --- a/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceDM.java +++ b/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceDM.java @@ -1,5 +1,6 @@ package supie.webadmin.app.service.databasemanagement.strategyImpl; +import cn.hutool.core.util.StrUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -33,7 +34,11 @@ public class DataSourceDM extends BaseDataSource implements Strategy { public void initStrategy(String hostIp, String hostPort, String databaseName, String userName, String password) { this.databaseType = DataBaseTypeEnum.DATASOURCE_DM; this.jdbcDriver = "dm.jdbc.driver.DmDriver"; - this.jdbcUrl = "jdbc:dm://" + hostIp + ":" + hostPort + ";DatabaseName=" + databaseName; + if (StrUtil.isBlank(databaseName)) { + this.jdbcUrl = "jdbc:dm://" + hostIp + ":" + hostPort; + } else { + this.jdbcUrl = "jdbc:dm://" + hostIp + ":" + hostPort + "/" + databaseName; + } this.hostIp = hostIp; this.hostPort = hostPort; this.databaseName = databaseName; @@ -43,36 +48,4 @@ public class DataSourceDM extends BaseDataSource implements Strategy { initConnection(); } - @Override - public List> queryDatabaseTable(DatabaseManagement databaseManagement) throws Exception { - return null; - } - - @Override - public List> queryTableFields(DatabaseManagement databaseManagement) throws Exception { - return null; - } - - /** - * 创建数据库 - * - * @param databaseName 创建的数据库的名称 - * @author 王立宏 - * @date 2023/11/02 04:30 - */ - @Override - public void createDatabase(String databaseName) { - - } - - /** - * 获取表结构 - * - * @param tableName 表名 - */ - @Override - public List> queryTableStructure(String tableName) { - return null; - } - } diff --git a/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceDoris.java b/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceDoris.java index f98ca1fac99b9ab72abc09be15e3274dc39383bd..161a2e999236dd414b8b693370eb2b596af61923 100644 --- a/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceDoris.java +++ b/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceDoris.java @@ -1,5 +1,6 @@ package supie.webadmin.app.service.databasemanagement.strategyImpl; +import cn.hutool.core.util.StrUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -46,7 +47,11 @@ public class DataSourceDoris extends BaseDataSource implements Strategy { public void initStrategy(String hostIp, String hostPort, String databaseName, String userName, String password) { this.databaseType = DataBaseTypeEnum.DATASOURCE_DORIS; this.jdbcDriver = "com.mysql.cj.jdbc.Driver"; - this.jdbcUrl = "jdbc:mysql://" + hostIp + ":" + hostPort + "/" + databaseName; + if (StrUtil.isBlank(databaseName)) { + this.jdbcUrl = "jdbc:mysql://" + hostIp + ":" + hostPort; + } else { + this.jdbcUrl = "jdbc:mysql://" + hostIp + ":" + hostPort + "/" + databaseName; + } this.hostIp = hostIp; this.hostPort = hostPort; this.databaseName = databaseName; @@ -56,49 +61,4 @@ public class DataSourceDoris extends BaseDataSource implements Strategy { initConnection(); } - /** - * 查询数据库数据表名及类型 - * - * @param databaseManagement - */ - @Override - public List> queryDatabaseTable(DatabaseManagement databaseManagement) throws Exception { - return null; - } - - /** - * 查询数据库数据的字段名及类型 - * - * @param databaseManagement - */ - @Override - public List> queryTableFields(DatabaseManagement databaseManagement) throws Exception { - return null; - } - - /** - * 创建数据库 - * - * @param databaseName 创建的数据库的名称 - * @author 王立宏 - * @date 2023/11/02 04:30 - */ - @Override - public void createDatabase(String databaseName) { - String createDatabaseSql = "CREATE DATABASE " + databaseName + ";"; - List> resultDataList = executeSqlList(createDatabaseSql); - Map resultMap = resultDataList.get(0); - if (Boolean.TRUE.equals(resultMap.get("isSuccess")) && ((int) resultMap.get("updateResultData") == 1)) return; - throw new RuntimeException("数据库创建[" + resultMap.get("sql") + "]失败!" + resultMap.get("message").toString()); - } - - /** - * 获取表结构 - * - * @param tableName 表名 - */ - @Override - public List> queryTableStructure(String tableName) { - return null; - } } diff --git a/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceHive.java b/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceHive.java index da7e4da8cac757cc3466b94cb472ae3931800691..04e539290538ea5f0f4d0bcae2c186c02731bc8c 100644 --- a/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceHive.java +++ b/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceHive.java @@ -1,5 +1,6 @@ package supie.webadmin.app.service.databasemanagement.strategyImpl; +import cn.hutool.core.util.StrUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -33,7 +34,11 @@ public class DataSourceHive extends BaseDataSource implements Strategy { public void initStrategy(String hostIp, String hostPort, String databaseName, String userName, String password) { this.databaseType = DataBaseTypeEnum.DATASOURCE_HIVE; this.jdbcDriver = "org.apache.hadoop.hive.jdbc.HiveDriver"; - this.jdbcUrl = "jdbc:hive2://" + hostIp + ":" + hostPort + ";DatabaseName=" + databaseName; + if (StrUtil.isBlank(databaseName)) { + this.jdbcUrl = "jdbc:hive2://" + hostIp + ":" + hostPort; + } else { + this.jdbcUrl = "jdbc:hive2://" + hostIp + ":" + hostPort + "/" + databaseName; + } this.hostIp = hostIp; this.hostPort = hostPort; this.databaseName = databaseName; @@ -43,36 +48,4 @@ public class DataSourceHive extends BaseDataSource implements Strategy { initConnection(); } - @Override - public List> queryDatabaseTable(DatabaseManagement databaseManagement) throws Exception { - return null; - } - - @Override - public List> queryTableFields(DatabaseManagement databaseManagement) throws Exception { - return null; - } - - /** - * 创建数据库 - * - * @param databaseName 创建的数据库的名称 - * @author 王立宏 - * @date 2023/11/02 04:30 - */ - @Override - public void createDatabase(String databaseName) { - - } - - /** - * 获取表结构 - * - * @param tableName 表名 - */ - @Override - public List> queryTableStructure(String tableName) { - return null; - } - } diff --git a/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceMySql.java b/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceMySql.java index c3a0dfe9351f948cd860f963454c258d462a0e81..37374cc1d99367ace28f64c16090daf46e1b03bf 100644 --- a/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceMySql.java +++ b/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceMySql.java @@ -1,13 +1,16 @@ package supie.webadmin.app.service.databasemanagement.strategyImpl; +import cn.hutool.core.util.StrUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import supie.webadmin.app.service.databasemanagement.*; -import supie.webadmin.app.service.databasemanagement.model.DatabaseManagement; +import supie.webadmin.app.service.databasemanagement.DataBaseTypeEnum; +import supie.webadmin.app.service.databasemanagement.Strategy; +import supie.webadmin.app.service.databasemanagement.StrategyFactory; import javax.annotation.PostConstruct; -import java.util.*; +import java.util.List; +import java.util.Map; /** * MySql @@ -32,7 +35,11 @@ public class DataSourceMySql extends BaseDataSource implements Strategy { public void initStrategy(String hostIp, String hostPort, String databaseName, String userName, String password) { this.databaseType = DataBaseTypeEnum.DATASOURCE_MYSQL; this.jdbcDriver = "com.mysql.cj.jdbc.Driver"; - this.jdbcUrl = "jdbc:mysql://" + hostIp + ":" + hostPort + "/" + databaseName + "?useUnicode=true&characterEncoding=utf-8"; + if (StrUtil.isBlank(databaseName)) { + this.jdbcUrl = "jdbc:mysql://" + hostIp + ":" + hostPort + "/?useUnicode=true&characterEncoding=utf-8"; + } else { + this.jdbcUrl = "jdbc:mysql://" + hostIp + ":" + hostPort + "/" + databaseName + "?useUnicode=true&characterEncoding=utf-8"; + } this.hostIp = hostIp; this.hostPort = hostPort; this.databaseName = databaseName; @@ -42,47 +49,6 @@ public class DataSourceMySql extends BaseDataSource implements Strategy { initConnection(); } - @Override - public List> queryDatabaseTable(DatabaseManagement databaseManagement) throws Exception { - String jdbcUrl = "jdbc:mysql://" + databaseManagement.getIp() + ":" + databaseManagement.getPort() + "/" + databaseManagement.getDatabaseName() + "?useUnicode=true&characterEncoding=utf-8"; - List> map; - map = QueryTheData.queryDatabaseTable("com.mysql.cj.jdbc.Driver",jdbcUrl, databaseManagement.getUsername(), databaseManagement.getPassword(),databaseManagement.getDatabaseName(),false); - return map; - } - - @Override - public List> queryTableFields(DatabaseManagement databaseManagement) throws Exception { - String jdbcUrl = "jdbc:mysql://" + databaseManagement.getIp() + ":" + databaseManagement.getPort() + "/" + databaseManagement.getDatabaseName() + "?useUnicode=true&characterEncoding=utf-8"; - List> map; - map = QueryTheFields.queryTableFields("com.mysql.cj.jdbc.Driver",jdbcUrl, databaseManagement.getUsername(), databaseManagement.getPassword(),false,databaseManagement.getTableName(),databaseManagement.getDatabaseName()); - return map; - } - - /** - * 创建数据库 - * - * @param databaseName 创建的数据库的名称 - * @author 王立宏 - * @date 2023/11/02 04:30 - */ - @Override - public void createDatabase(String databaseName) { - String createDatabaseSql = "CREATE DATABASE " + databaseName + " DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;"; - List> resultDataList = executeSqlList(createDatabaseSql); - Map resultMap = resultDataList.get(0); - if (Boolean.TRUE.equals(resultMap.get("isSuccess")) && ((int) resultMap.get("updateResultData") == 1)) return; - throw new RuntimeException("数据库创建[" + resultMap.get("sql") + "]失败!" + resultMap.get("message").toString()); - } - - /** - * TODO 获取表结构 - * - * @param tableName 表名 - */ - @Override - public List> queryTableStructure(String tableName) { - return null; - } } diff --git a/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceOracle.java b/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceOracle.java index 3b4c8600e3f5b19b697c73403be84a297b55bd15..f4c948891cc6201ecfbe6b1a4d00afbd7b078832 100644 --- a/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceOracle.java +++ b/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceOracle.java @@ -1,5 +1,6 @@ package supie.webadmin.app.service.databasemanagement.strategyImpl; +import cn.hutool.core.util.StrUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -33,7 +34,11 @@ public class DataSourceOracle extends BaseDataSource implements Strategy { public void initStrategy(String hostIp, String hostPort, String databaseName, String userName, String password) { this.databaseType = DataBaseTypeEnum.DATASOURCE_ORACLE; this.jdbcDriver = "oracle.jdbc.driver.OracleDriver"; - this.jdbcUrl = "jdbc:oracle:thin:@" + hostIp + ":" + hostPort + ":" + databaseName; + if (StrUtil.isBlank(databaseName)) { + this.jdbcUrl = "jdbc:oracle:thin:@" + hostIp + ":" + hostPort; + } else { + this.jdbcUrl = "jdbc:oracle:thin:@" + hostIp + ":" + hostPort + ":" + databaseName; + } this.hostIp = hostIp; this.hostPort = hostPort; this.databaseName = databaseName; @@ -43,36 +48,4 @@ public class DataSourceOracle extends BaseDataSource implements Strategy { initConnection(); } - @Override - public List> queryDatabaseTable(DatabaseManagement databaseManagement) throws Exception { - return null; - } - - @Override - public List> queryTableFields(DatabaseManagement databaseManagement) throws Exception { - return null; - } - - /** - * 创建数据库 - * - * @param databaseName 创建的数据库的名称 - * @author 王立宏 - * @date 2023/11/02 04:30 - */ - @Override - public void createDatabase(String databaseName) { - //TODO 创建数据库 - } - - /** - * 获取表结构 - * - * @param tableName 表名 - */ - @Override - public List> queryTableStructure(String tableName) { - return null; - } - } diff --git a/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourcePostgreSQL.java b/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourcePostgreSQL.java index ca0044a167d0b27013292242aa839e9a8c213891..75fe25101ae0956e048b00d21a33c3ddec4c95fd 100644 --- a/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourcePostgreSQL.java +++ b/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourcePostgreSQL.java @@ -1,5 +1,6 @@ package supie.webadmin.app.service.databasemanagement.strategyImpl; +import cn.hutool.core.util.StrUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -29,7 +30,11 @@ public class DataSourcePostgreSQL extends BaseDataSource implements Strategy { public void initStrategy(String hostIp, String hostPort, String databaseName, String userName, String password) { this.databaseType = DataBaseTypeEnum.DATASOURCE_PG; this.jdbcDriver = "org.postgresql.Driver"; - this.jdbcUrl = "jdbc:postgresql://" + hostIp + ":" + hostPort + "/" + databaseName; + if (StrUtil.isBlank(databaseName)) { + this.jdbcUrl = "jdbc:postgresql://" + hostIp + ":" + hostPort; + } else { + this.jdbcUrl = "jdbc:postgresql://" + hostIp + ":" + hostPort + "/" + databaseName; + } this.hostIp = hostIp; this.hostPort = hostPort; this.databaseName = databaseName; @@ -39,36 +44,4 @@ public class DataSourcePostgreSQL extends BaseDataSource implements Strategy { initConnection(); } - /** - * 创建数据库 - * - * @param databaseName 创建的数据库的名称 - * @author 王立宏 - * @date 2023/11/02 04:30 - */ - @Override - public void createDatabase(String databaseName) { - //TODO 创建数据库 - } - - /** - * 获取表结构 - * - * @param tableName 表名 - */ - @Override - public List> queryTableStructure(String tableName) { - return null; - } - - @Override - public List> queryDatabaseTable(DatabaseManagement databaseManagement) throws Exception { - return null; - } - - @Override - public List> queryTableFields(DatabaseManagement databaseManagement) throws Exception { - return null; - } - } diff --git a/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceSQLServer.java b/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceSQLServer.java index d43cff919c9400345d07f9b35daee44deab0936e..c74a2b8c0a55aae49b665689304dc308e6299810 100644 --- a/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceSQLServer.java +++ b/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceSQLServer.java @@ -1,5 +1,6 @@ package supie.webadmin.app.service.databasemanagement.strategyImpl; +import cn.hutool.core.util.StrUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -29,7 +30,11 @@ public class DataSourceSQLServer extends BaseDataSource implements Strategy { public void initStrategy(String hostIp, String hostPort, String databaseName, String userName, String password) { this.databaseType = DataBaseTypeEnum.DATASOURCE_SQLSERVER; this.jdbcDriver = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; - this.jdbcUrl = "jdbc:sqlserver://" + hostIp + ":" + hostPort + ";DatabaseName=" + databaseName; + if (StrUtil.isBlank(databaseName)) { + this.jdbcUrl = "jdbc:sqlserver://" + hostIp + ":" + hostPort; + } else { + this.jdbcUrl = "jdbc:sybase://" + hostIp + ":" + hostPort + ";databaseName=" + databaseName; + } this.hostIp = hostIp; this.hostPort = hostPort; this.databaseName = databaseName; @@ -39,35 +44,4 @@ public class DataSourceSQLServer extends BaseDataSource implements Strategy { initConnection(); } - @Override - public List> queryDatabaseTable(DatabaseManagement databaseManagement) throws Exception { - return null; - } - - @Override - public List> queryTableFields(DatabaseManagement databaseManagement) throws Exception { - return null; - } - - /** - * TODO 创建数据库 - * - * @param databaseName 创建的数据库的名称 - * @author 王立宏 - * @date 2023/11/02 04:30 - */ - @Override - public void createDatabase(String databaseName) { - } - - /** - * 获取表结构 - * - * @param tableName 表名 - */ - @Override - public List> queryTableStructure(String tableName) { - return null; - } - } diff --git a/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceSapHana.java b/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceSapHana.java index 08e23f3ab7c634a3e734ffdf71f333c6d6cc1b46..dbb856ebcd97646cf4efbe5a6080deebe35a4905 100644 --- a/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceSapHana.java +++ b/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceSapHana.java @@ -1,5 +1,6 @@ package supie.webadmin.app.service.databasemanagement.strategyImpl; +import cn.hutool.core.util.StrUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -29,7 +30,11 @@ public class DataSourceSapHana extends BaseDataSource implements Strategy { public void initStrategy(String hostIp, String hostPort, String databaseName, String userName, String password) { this.databaseType = DataBaseTypeEnum.DATASOURCE_SAP_HANA; this.jdbcDriver = "com.sap.db.jdbc.Driver"; - this.jdbcUrl = "jdbc:sap://" + hostIp + ":" + hostPort + ";DatabaseName=" + databaseName; + if (StrUtil.isBlank(databaseName)) { + this.jdbcUrl = "jdbc:sap://" + hostIp + ":" + hostPort; + } else { + this.jdbcUrl = "jdbc:sap://" + hostIp + ":" + hostPort + "/" + databaseName; + } this.hostIp = hostIp; this.hostPort = hostPort; this.databaseName = databaseName; @@ -39,53 +44,4 @@ public class DataSourceSapHana extends BaseDataSource implements Strategy { initConnection(); } - @Override - public List> queryDatabaseTable(DatabaseManagement databaseManagement) throws Exception { - return null; - } - - @Override - public List> queryTableFields(DatabaseManagement databaseManagement) throws Exception { - return null; - } - - /** - * 创建数据库 - * - * @param databaseName 创建的数据库的名称 - * @author 王立宏 - * @date 2023/11/02 04:30 - */ - @Override - public void createDatabase(String databaseName) { - - } - - /** - * 获取表结构 - * - * @param tableName 表名 - */ - @Override - public List> queryTableStructure(String tableName) { - return null; - } - -// public static String initSapHana(String jdbcUrl, String userName, String passWord, boolean autoCommit) { -// Connection conn = null; -// try { -// Class.forName("com.sap.db.jdbc.Driver"); -// //连接数据库 -// conn = DriverManager.getConnection(jdbcUrl, userName, passWord); -// conn.setAutoCommit(autoCommit); -// return "SAP HANA连接成功!"; -// } catch (ClassNotFoundException e) { -// System.out.println("找不到驱动程序类"); -// return "找不到驱动程序类!"; -// } catch (SQLException se) { -// //连接失败 -// logger.error("SAP HANA连接失败", se); -// return "SAP HANA连接失败" + se; -// } -// } } diff --git a/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceSyBase.java b/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceSyBase.java index 02215bf4c4060ef1c1c77dfe364c2b27b3b84b48..2862ae8f8c8e7101695de88988537314a16db73a 100644 --- a/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceSyBase.java +++ b/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceSyBase.java @@ -1,5 +1,6 @@ package supie.webadmin.app.service.databasemanagement.strategyImpl; +import cn.hutool.core.util.StrUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -29,7 +30,11 @@ public class DataSourceSyBase extends BaseDataSource implements Strategy { public void initStrategy(String hostIp, String hostPort, String databaseName, String userName, String password) { this.databaseType = DataBaseTypeEnum.DATASOURCE_SY_BASE; this.jdbcDriver = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; - this.jdbcUrl = "jdbc:sybase://" + hostIp + ":" + hostPort + "/" + databaseName + "?useUnicode=true&characterEncoding=utf-8"; + if (StrUtil.isBlank(databaseName)) { + this.jdbcUrl = "jdbc:sybase://" + hostIp + ":" + hostPort; + } else { + this.jdbcUrl = "jdbc:sybase://" + hostIp + ":" + hostPort + "/" + databaseName; + } this.hostIp = hostIp; this.hostPort = hostPort; this.databaseName = databaseName; @@ -39,35 +44,4 @@ public class DataSourceSyBase extends BaseDataSource implements Strategy { initConnection(); } - @Override - public List> queryDatabaseTable(DatabaseManagement databaseManagement) throws Exception { - return null; - } - - @Override - public List> queryTableFields(DatabaseManagement databaseManagement) throws Exception { - return null; - } - - /** - * 创建数据库 - * - * @param databaseName 创建的数据库的名称 - * @author 王立宏 - * @date 2023/11/02 04:30 - */ - @Override - public void createDatabase(String databaseName) { - } - - /** - * 获取表结构 - * - * @param tableName 表名 - */ - @Override - public List> queryTableStructure(String tableName) { - return null; - } - } diff --git a/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceTdSql.java b/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceTdSql.java index 4dff242e60ea6b3403376b04a1bf5111b81b29e7..33d55f4c9c2da01823c72f6bd481cbf02c3df405 100644 --- a/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceTdSql.java +++ b/application-webadmin/src/main/java/supie/webadmin/app/service/databasemanagement/strategyImpl/DataSourceTdSql.java @@ -1,5 +1,6 @@ package supie.webadmin.app.service.databasemanagement.strategyImpl; +import cn.hutool.core.util.StrUtil; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -29,7 +30,11 @@ public class DataSourceTdSql extends BaseDataSource implements Strategy { public void initStrategy(String hostIp, String hostPort, String databaseName, String userName, String password) { this.databaseType = DataBaseTypeEnum.DATASOURCE_SY_BASE; this.jdbcDriver = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; - this.jdbcUrl = "jdbc:sqlserver://" + hostIp + ":" + hostPort + ";DatabaseName=" + databaseName; + if (StrUtil.isBlank(databaseName)) { + this.jdbcUrl = "jdbc:sqlserver://" + hostIp + ":" + hostPort; + } else { + this.jdbcUrl = "jdbc:sqlserver://" + hostIp + ":" + hostPort + "/" + databaseName; + } this.hostIp = hostIp; this.hostPort = hostPort; this.databaseName = databaseName; @@ -39,36 +44,4 @@ public class DataSourceTdSql extends BaseDataSource implements Strategy { initConnection(); } - @Override - public List> queryDatabaseTable(DatabaseManagement databaseManagement) throws Exception { - return null; - } - - @Override - public List> queryTableFields(DatabaseManagement databaseManagement) throws Exception { - return null; - } - - /** - * 创建数据库 - * - * @param databaseName 创建的数据库的名称 - * @author 王立宏 - * @date 2023/11/02 04:30 - */ - @Override - public void createDatabase(String databaseName) { - - } - - /** - * 获取表结构 - * - * @param tableName 表名 - */ - @Override - public List> queryTableStructure(String tableName) { - return null; - } - } diff --git a/application-webadmin/src/main/java/supie/webadmin/app/service/impl/RemoteHostServiceImpl.java b/application-webadmin/src/main/java/supie/webadmin/app/service/impl/RemoteHostServiceImpl.java index 01dbf14e09828e46725d4f4feb5675d70e964928..5c83faa8b9d8a5f9f25469511aa1de54005e5a4a 100644 --- a/application-webadmin/src/main/java/supie/webadmin/app/service/impl/RemoteHostServiceImpl.java +++ b/application-webadmin/src/main/java/supie/webadmin/app/service/impl/RemoteHostServiceImpl.java @@ -6,7 +6,8 @@ import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import supie.webadmin.app.service.*; import supie.webadmin.app.dao.*; import supie.webadmin.app.model.*; -import supie.webadmin.app.util.remoteshell.JschUtil; +import supie.webadmin.app.util.remoteshell.RemoteShell; +import supie.webadmin.app.util.remoteshell.impl.RemoteShellSshjImpl; import supie.webadmin.upms.service.SysUserService; import supie.webadmin.upms.service.SysDeptService; import supie.common.core.base.dao.BaseDaoMapper; @@ -22,7 +23,6 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import javax.annotation.Resource; import java.util.*; /** @@ -209,12 +209,13 @@ public class RemoteHostServiceImpl extends BaseService impleme return remoteHost; } - @Override - public String testConnection(String logFilePath, RemoteHost remoteHost, String commands) { - - JschUtil jschUtil = new JschUtil(); - String data = jschUtil.testConnection(logFilePath,remoteHost, commands); - return data; + public String testConnection(RemoteHost remoteHostFilter, List commandList) { + RemoteShell remoteShell = new RemoteShellSshjImpl( + remoteHostFilter.getHostIp(), remoteHostFilter.getHostPort(), + remoteHostFilter.getLoginName(), remoteHostFilter.getPassword(), null); + String resultMessage = remoteShell.execCommands(commandList.toArray(new String[0])); + remoteShell.close(); + return resultMessage; } } diff --git a/application-webadmin/src/main/java/supie/webadmin/app/util/remoteshell/RemoteShell.java b/application-webadmin/src/main/java/supie/webadmin/app/util/remoteshell/RemoteShell.java new file mode 100644 index 0000000000000000000000000000000000000000..7442c23c6adf5da0cb0a100e772a292e6d4409f4 --- /dev/null +++ b/application-webadmin/src/main/java/supie/webadmin/app/util/remoteshell/RemoteShell.java @@ -0,0 +1,47 @@ +package supie.webadmin.app.util.remoteshell; + +/** + * 描述: + * + * @author 王立宏 + * @date 2023/11/10 14:20 + * @path SDT-supie.webadmin.app.util.remoteshell-RemoteShell + */ +public interface RemoteShell { + + /** + * 关闭SSH连接 + */ + void close(); + + /** + * 执行命令 + * + * @param commands 命令 + * @return 执行命令的结果日志 + * @author 王立宏 + * @date 2023/11/10 02:23 + */ + String execCommands(String... commands); + + /** + * 上传文件 + * + * @param localFilePath 本地文件路径 + * @param remoteFilePath 远程文件路径 + * @author 王立宏 + * @date 2023/11/10 02:29 + */ + void uploadFile(String localFilePath, String remoteFilePath); + + /** + * 下载文件 + * + * @param localFilePath 本地文件路径 + * @param remoteFilePath 远程文件路径 + * @author 王立宏 + * @date 2023/11/10 02:59 + */ + void downloadFile(String localFilePath, String remoteFilePath); + +} diff --git a/application-webadmin/src/main/java/supie/webadmin/app/util/remoteshell/SshConfigModel.java b/application-webadmin/src/main/java/supie/webadmin/app/util/remoteshell/SshConfigModel.java new file mode 100644 index 0000000000000000000000000000000000000000..5defc8d412f17574a91ed0e5eb43127b0d9d1aff --- /dev/null +++ b/application-webadmin/src/main/java/supie/webadmin/app/util/remoteshell/SshConfigModel.java @@ -0,0 +1,24 @@ +package supie.webadmin.app.util.remoteshell; + +import lombok.Data; + +/** + * 描述: + * + * @author 王立宏 + * @date 2023/10/17 15:42 + * @path SDT-supie.webadmin.app.util.remoteshell-SSHJConfig + */ +@Data +public class SshConfigModel { + + protected String ip; + protected String port = "22"; + protected String userName = "root"; + protected String password; + protected String hostKey = "localhost ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPmhSBtMctNa4hsZt8QGlsYSE5/gMkjeand69Vj4ir13"; +// protected String keyPath = separator + "Users" + separator + sysUserName + separator + ".ssh" + separator + "a.pem"; + + protected int timeout = 3000; + +} diff --git a/application-webadmin/src/main/java/supie/webadmin/app/util/remoteshell/impl/RemoteShellSshjImpl.java b/application-webadmin/src/main/java/supie/webadmin/app/util/remoteshell/impl/RemoteShellSshjImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..184c8dde1ed28efe8e05ab1169bf61fac30db424 --- /dev/null +++ b/application-webadmin/src/main/java/supie/webadmin/app/util/remoteshell/impl/RemoteShellSshjImpl.java @@ -0,0 +1,203 @@ +package supie.webadmin.app.util.remoteshell.impl; + +import cn.hutool.core.util.StrUtil; +import lombok.extern.slf4j.Slf4j; +import net.schmizz.sshj.SSHClient; +import net.schmizz.sshj.connection.ConnectionException; +import net.schmizz.sshj.connection.channel.direct.Session; +import net.schmizz.sshj.sftp.SFTPClient; +import net.schmizz.sshj.transport.TransportException; +import net.schmizz.sshj.transport.verification.ConsoleKnownHostsVerifier; +import net.schmizz.sshj.transport.verification.OpenSSHKnownHosts; +import net.schmizz.sshj.transport.verification.PromiscuousVerifier; +import supie.webadmin.app.util.remoteshell.RemoteShell; +import supie.webadmin.app.util.remoteshell.SshConfigModel; + +import java.io.*; +import java.nio.charset.Charset; +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 描述:SSHJ 的 RemoteShell 实现 + * + * @author 王立宏 + * @date 2023/11/10 15:01 + * @path SDT-supie.webadmin.app.util.remoteshell-RemoteShellSshjImpl + */ +@Slf4j +public class RemoteShellSshjImpl extends SshConfigModel implements RemoteShell { + + private SSHClient sshClient = null; + + public RemoteShellSshjImpl(String ip, String port, String userName, String password, String hostKey) { + if (StrUtil.isNotBlank(ip)) { + this.ip = ip; + } else { + throw new RuntimeException("目标主机IP不能为空!"); + } + if (StrUtil.isNotBlank(port)) { + this.port = port; + } + if (StrUtil.isNotBlank(userName)) { + this.userName = userName; + } else { + throw new RuntimeException("登录用户名不能为空!"); + } + if (StrUtil.isBlank(password) && StrUtil.isBlank(hostKey)) { + throw new RuntimeException("密码和ssh-key不能同时为空!"); + } else { + this.password = password; + this.hostKey = hostKey; + } + getSshClient(); + } + + /** + * 获取 SSH 连接 + * + * @author 王立宏 + * @date 2023/11/10 03:37 + */ + private void getSshClient() { + sshClient = new SSHClient(); + try { + if (password != null) { + sshClient.addHostKeyVerifier(new PromiscuousVerifier()); + final File khFile = new File(OpenSSHKnownHosts.detectSSHDir(), "known_hosts"); + sshClient.addHostKeyVerifier(new ConsoleKnownHostsVerifier(khFile, System.console())); + sshClient.connect(this.ip, Integer.parseInt(this.port)); + sshClient.authPassword(this.userName, this.password); + } else { + InputStream entry = new ByteArrayInputStream(this.hostKey.getBytes(Charset.defaultCharset())); + sshClient.addHostKeyVerifier(new OpenSSHKnownHosts(new InputStreamReader(entry, Charset.defaultCharset()))); + sshClient.authPublickey(this.userName); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * 关闭SSH连接 + */ + @Override + public void close() { + try { + sshClient.disconnect(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * 执行命令 + * + * @param commands 命令 + * @return 执行命令的结果日志 + * @author 王立宏 + * @date 2023/11/10 02:23 + */ + @Override + public String execCommands(String... commands) { + StringBuilder resultMessage = new StringBuilder(); + Session session = null; + try { + session = sshClient.startSession(); + session.allocateDefaultPTY(); + Session.Shell shell = session.startShell(); + + // 重定向 OutputStream,并且写入命令 + OutputStream outputStream = shell.getOutputStream(); + for (String command : commands) { + outputStream.write((command + "\r").getBytes()); + outputStream.flush(); + TimeUnit.SECONDS.sleep(2); + } + outputStream.write(("exit\r").getBytes()); + outputStream.flush(); + + // 重定向 InputStream,并且将其添加至回显日志 + InputStream inputStream = shell.getInputStream(); + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); + + String line; + while ((line = reader.readLine()) != null) { + // 用正则表达式过滤掉表示颜色的字符 + String reg = "\\x1B\\[[;\\d]*m"; + Pattern pattern = Pattern.compile(reg); + Matcher matcher = pattern.matcher(line); + line = matcher.replaceAll(""); + + resultMessage.append(line).append("\n"); + } + } catch (InterruptedException | IOException e) { + throw new RuntimeException(e); + } finally { + if (session != null) { + try { + session.close(); + } catch (TransportException | ConnectionException e) { + throw new RuntimeException(e); + } + } + } + return resultMessage.toString(); + } + + /** + * 上传文件 + * + * @param localFilePath 本地文件路径 + * @param remoteFilePath 远程文件路径 + * @author 王立宏 + * @date 2023/11/10 02:29 + */ + @Override + public void uploadFile(String localFilePath, String remoteFilePath) { + SFTPClient sftpClient = null; + try { + sftpClient = sshClient.newSFTPClient(); + sftpClient.put(localFilePath, remoteFilePath); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + if (sftpClient != null) { + try { + sftpClient.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + } + + /** + * 下载文件 + * + * @param localFilePath 本地文件路径 + * @param remoteFilePath 远程文件路径 + * @author 王立宏 + * @date 2023/11/10 02:59 + */ + @Override + public void downloadFile(String localFilePath, String remoteFilePath) { + SFTPClient sftpClient = null; + try { + sftpClient = sshClient.newSFTPClient(); + sftpClient.get(remoteFilePath, localFilePath); + } catch (IOException e) { + throw new RuntimeException(e); + } finally { + if (sftpClient != null) { + try { + sftpClient.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + } + +} diff --git a/pom.xml b/pom.xml index 53955bc66c054743cd59a9bb431a8e634906ce5b..feaf4ed0edb33578f9a753a1b307a3147b692677 100644 --- a/pom.xml +++ b/pom.xml @@ -50,7 +50,6 @@ 1.5.33 0.37.0 - 0.1.55 @@ -189,11 +188,6 @@ sshj ${sshj.version} - - com.jcraft - jsch - ${jsch.version} -