From 2f3a2ae28fd2fe42998c3bbccfc77e3b019afda3 Mon Sep 17 00:00:00 2001
From: zyj <2660555181@qq.com>
Date: Tue, 24 Jun 2025 16:20:09 +0800
Subject: [PATCH] =?UTF-8?q?=E8=BF=9C=E7=A8=8B=E8=BF=9E=E6=8E=A5=E4=BB=A3?=
=?UTF-8?q?=E7=A0=81=E9=80=BB=E8=BE=91=E4=BF=AE=E6=94=B9=EF=BC=8C=E6=94=B9?=
=?UTF-8?q?=E7=94=A8websocket(=E8=81=94=E8=B0=83=E4=BB=BB=E5=AD=98?=
=?UTF-8?q?=E5=9C=A8=E9=97=AE=E9=A2=98)=EF=BC=8C=E6=96=B0=E5=A2=9E?=
=?UTF-8?q?=E8=BF=9C=E7=A8=8B=E6=9C=BA=E5=99=A8=E5=AF=B9=E6=96=87=E4=BB=B6?=
=?UTF-8?q?=E6=A0=91=E7=9A=84=E6=93=8D=E4=BD=9C=EF=BC=8C=E4=BB=A3=E7=A0=81?=
=?UTF-8?q?=E5=B7=A5=E6=95=B4=E6=A0=BC=E5=BC=8F=E5=8C=96?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
modules/module-ci-machine/pom.xml | 17 +-
.../WebSocketHandshakeInterceptor.java | 85 +++
.../machine/component/FileTreeComponent.java | 214 ++++++
.../component/WebSocketConnection.java | 230 +++++++
.../component/WebSocketSessionManager.java | 114 ++++
.../configuration/AliYunOssConfig.java | 2 +-
.../configuration/WebSocketConfig.java | 40 ++
.../contants/MachineErrorCodeConstants.java | 32 +-
.../controller/MachineInfoController.java | 78 +--
.../controller/SecretKeyController.java | 27 +-
.../machine/controller/vo/SecretKeyVO.java | 2 +
.../machine/convert/MachineEnvConvert.java | 25 -
.../module/machine/dal/model/FileNode.java | 56 ++
.../machine/dal/mysql/MachineInfoMapper.java | 5 +
.../machine/dal/mysql/SecretKeyMapper.java | 1 -
.../machine/enums/ConnectionStatus.java | 29 +-
.../module/machine/enums/SSHChanelType.java | 35 +
.../machine/handler/ConnectionSession.java | 642 ------------------
.../handler/MachineWebSocketHandler.java | 67 ++
.../machine/service/MachineInfoService.java | 88 +--
.../machine/service/SecretKeyService.java | 11 +
.../service/impl/MachineInfoServiceImpl.java | 243 ++-----
.../service/impl/MachineProxyServiceImpl.java | 2 -
.../service/impl/SecretKeyServiceImpl.java | 83 ++-
.../module/machine/utils/AliYunOssClient.java | 3 +-
.../module/machine/utils/PropertyUtils.java | 35 -
26 files changed, 1175 insertions(+), 991 deletions(-)
create mode 100644 modules/module-ci-machine/src/main/java/cd/casic/module/machine/Interceptor/WebSocketHandshakeInterceptor.java
create mode 100644 modules/module-ci-machine/src/main/java/cd/casic/module/machine/component/FileTreeComponent.java
create mode 100644 modules/module-ci-machine/src/main/java/cd/casic/module/machine/component/WebSocketConnection.java
create mode 100644 modules/module-ci-machine/src/main/java/cd/casic/module/machine/component/WebSocketSessionManager.java
create mode 100644 modules/module-ci-machine/src/main/java/cd/casic/module/machine/configuration/WebSocketConfig.java
delete mode 100644 modules/module-ci-machine/src/main/java/cd/casic/module/machine/convert/MachineEnvConvert.java
create mode 100644 modules/module-ci-machine/src/main/java/cd/casic/module/machine/dal/model/FileNode.java
create mode 100644 modules/module-ci-machine/src/main/java/cd/casic/module/machine/enums/SSHChanelType.java
delete mode 100644 modules/module-ci-machine/src/main/java/cd/casic/module/machine/handler/ConnectionSession.java
create mode 100644 modules/module-ci-machine/src/main/java/cd/casic/module/machine/handler/MachineWebSocketHandler.java
delete mode 100644 modules/module-ci-machine/src/main/java/cd/casic/module/machine/utils/PropertyUtils.java
diff --git a/modules/module-ci-machine/pom.xml b/modules/module-ci-machine/pom.xml
index ce137127..6f221741 100644
--- a/modules/module-ci-machine/pom.xml
+++ b/modules/module-ci-machine/pom.xml
@@ -28,6 +28,12 @@
3.15.1
+
+
+ org.springframework.boot
+ spring-boot-starter-websocket
+
+
com.jcraft
@@ -63,7 +69,14 @@
module-infra-biz
${revision}
-
-
+
+
+
+ org.apache.httpcomponents
+ httpclient
+ 4.5.13
+
+
+
diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/Interceptor/WebSocketHandshakeInterceptor.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/Interceptor/WebSocketHandshakeInterceptor.java
new file mode 100644
index 00000000..a0a6f890
--- /dev/null
+++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/Interceptor/WebSocketHandshakeInterceptor.java
@@ -0,0 +1,85 @@
+package cd.casic.module.machine.Interceptor;
+
+import lombok.extern.slf4j.Slf4j;
+import org.jetbrains.annotations.NotNull;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.server.ServerHttpRequest;
+import org.springframework.http.server.ServerHttpResponse;
+import org.springframework.stereotype.Component;
+import org.springframework.web.socket.WebSocketHandler;
+import org.springframework.web.socket.server.HandshakeInterceptor;
+
+import java.net.URI;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+
+import static cd.casic.framework.commons.exception.util.ServiceExceptionUtil.exception;
+import static cd.casic.module.machine.contants.MachineErrorCodeConstants.*;
+
+@Component
+@Slf4j
+public class WebSocketHandshakeInterceptor implements HandshakeInterceptor {
+ @Override
+ public boolean beforeHandshake(
+ @NotNull ServerHttpRequest request,
+ @NotNull ServerHttpResponse response,
+ @NotNull WebSocketHandler wsHandler,
+ @NotNull Map attributes
+ ) {
+ log.info("WebSocket握手请求: {}", request.getURI());
+
+ // 从URL参数中获取id
+ String id = extractIdFromUrl(request.getURI());
+
+ System.out.println("-----------------------------------------");
+ if (id != null) {
+ attributes.put("machineId", id); // 将id存入attributes
+ log.info("握手验证成功 - ID: {}", id);
+ return true;
+ } else {
+ response.setStatusCode(HttpStatus.BAD_REQUEST);
+ log.warn("握手验证失败 - 缺少 id URL 参数");
+ return false;
+ }
+ }
+
+ @Override
+ public void afterHandshake(
+ @NotNull ServerHttpRequest request,
+ @NotNull ServerHttpResponse response,
+ @NotNull WebSocketHandler wsHandler,
+ Exception exception
+ ) {
+ if (exception == null) {
+ log.info("WebSocket握手完成 - URI: {}",
+ request.getURI());
+ } else {
+ log.error("WebSocket握手异常 - URI: {}, 异常信息: {}",
+ request.getURI(),
+ exception.getMessage(),
+ exception);
+ }
+ }
+
+ // 从URI中提取id参数的辅助方法
+ private String extractIdFromUrl(URI uri) {
+ try {
+ String query = uri.getQuery();
+ if (query != null) {
+ String[] params = query.split("&");
+ for (String param : params) {
+ String[] keyValue = param.split("=");
+ if (keyValue.length == 2 && "id".equalsIgnoreCase(keyValue[0])) { // 修改为匹配id
+ return URLDecoder.decode(keyValue[1], StandardCharsets.UTF_8);
+ }
+ }
+ }
+ } catch (Exception e) {
+ log.error("解析URL参数失败", e);
+ throw exception(FAILED_TO_PARSE_URL_PARAMETERS);
+ }
+ return null;
+ }
+
+}
diff --git a/modules/module-ci-machine/src/main/java/cd/casic/module/machine/component/FileTreeComponent.java b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/component/FileTreeComponent.java
new file mode 100644
index 00000000..d42fa416
--- /dev/null
+++ b/modules/module-ci-machine/src/main/java/cd/casic/module/machine/component/FileTreeComponent.java
@@ -0,0 +1,214 @@
+package cd.casic.module.machine.component;
+
+import cd.casic.module.machine.dal.model.FileNode;
+import com.jcraft.jsch.Channel;
+import com.jcraft.jsch.ChannelSftp;
+import com.jcraft.jsch.JSchException;
+import com.jcraft.jsch.Session;
+import com.jcraft.jsch.SftpATTRS;
+import com.jcraft.jsch.SftpException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
+
+import static cd.casic.framework.commons.exception.util.ServiceExceptionUtil.exception;
+import static cd.casic.module.machine.contants.MachineErrorCodeConstants.*;
+
+@Slf4j
+@Component
+public class FileTreeComponent {
+
+ private ChannelSftp sftp;
+ //todo缓存过期还未设置
+ private final Map directoryCache = new ConcurrentHashMap<>();
+ private static final long CACHE_EXPIRE_TIME = 60 * 1000; // 缓存过期时间:1分钟
+ private final Map cacheTimeStamp = new ConcurrentHashMap<>();
+
+ // 将文件树转换为JSON友好的Map结构(仅一级目录)
+ public static Map convertToMap(FileNode node) {
+ Map map = new HashMap<>();
+ map.put("name", node.getName());
+ map.put("isDirectory", node.isDirectory());
+ map.put("size", node.getSize());
+ map.put("permissions", node.getPermissions());
+ map.put("modifiedTime", node.getModifiedTime());
+ // 仅添加直接子项,不递归
+ if (node.isDirectory() && !node.getChildren().isEmpty()) {
+ List