From 3c8d1b833b5204703234e848ef22ce705657c284 Mon Sep 17 00:00:00 2001
From: chenhao <852066789@qq.com>
Date: Mon, 8 Sep 2025 09:51:52 +0800
Subject: [PATCH] =?UTF-8?q?feat(image):=20=E6=B7=BB=E5=8A=A0=E8=8E=B7?=
=?UTF-8?q?=E5=8F=96=20VNC=E4=BF=A1=E6=81=AF=E5=8A=9F=E8=83=BD=E5=B9=B6?=
=?UTF-8?q?=E4=BC=98=E5=8C=96=E9=95=9C=E5=83=8F=E7=9B=B8=E5=85=B3=E6=9C=8D?=
=?UTF-8?q?=E5=8A=A1?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 在 DeviceImageMappingRes 中添加父镜像名称和创建时间字段
- 优化 DeviceImageMappingService 中镜像信息查询逻辑- 在 ExternalApiClient 中添加获取VNC 信息的接口
- 在 ImageVirtualMachinesController 中添加获取 VNC 信息的控制器方法- 在 ImageVirtualMachinesService接口中添加获取 VNC 信息的方法
- 实现 ImageVirtualMachinesServiceImpl 中获取 VNC 信息的逻辑
- 新增 VncData 类用于存储 VNC 信息
---
.../ImageVirtualMachinesController.java | 12 ++++---
.../entity/res/DeviceImageMappingRes.java | 14 ++++++++
.../project/entity/res/VncData.java | 33 +++++++++++++++++++
.../project/feign/ExternalApiClient.java | 3 ++
.../ClientNotificationServiceImpl.java | 19 ++++-------
.../service/ImageVirtualMachinesService.java | 2 ++
.../impl/DeviceImageMappingServiceImpl.java | 23 ++++++++-----
.../impl/ImageVirtualMachinesServiceImpl.java | 14 ++++++--
8 files changed, 93 insertions(+), 27 deletions(-)
create mode 100644 nex-be/src/main/java/com/unisinsight/project/entity/res/VncData.java
diff --git a/nex-be/src/main/java/com/unisinsight/project/controller/ImageVirtualMachinesController.java b/nex-be/src/main/java/com/unisinsight/project/controller/ImageVirtualMachinesController.java
index 997cc74..e0f6d5a 100644
--- a/nex-be/src/main/java/com/unisinsight/project/controller/ImageVirtualMachinesController.java
+++ b/nex-be/src/main/java/com/unisinsight/project/controller/ImageVirtualMachinesController.java
@@ -13,10 +13,7 @@ import com.unisinsight.project.service.ImageVirtualMachinesService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.Objects;
@@ -154,6 +151,13 @@ public class ImageVirtualMachinesController {
log.info("终端卸载文件请求参数为:{}", JSONUtil.toJsonStr(req));
return service.removeIso(req);
}
+ @ApiOperation(value = "获取VNC信息")
+ @GetMapping("/vnc")
+ public Result> getVncData(@RequestParam("vmName") String vmName) {
+
+ log.info("获取VNC信息请求参数为:{}", vmName);
+ return service.getVncData(vmName);
+ }
}
diff --git a/nex-be/src/main/java/com/unisinsight/project/entity/res/DeviceImageMappingRes.java b/nex-be/src/main/java/com/unisinsight/project/entity/res/DeviceImageMappingRes.java
index b4d3d33..e2de209 100644
--- a/nex-be/src/main/java/com/unisinsight/project/entity/res/DeviceImageMappingRes.java
+++ b/nex-be/src/main/java/com/unisinsight/project/entity/res/DeviceImageMappingRes.java
@@ -5,6 +5,7 @@ import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
+import java.util.Date;
/**
* @TableName device_image_mapping
@@ -59,6 +60,19 @@ public class DeviceImageMappingRes implements Serializable {
@JsonProperty(value = "image_file_name")
@ApiModelProperty("镜像源文件名称")
private String imageFileName;
+
+ /**
+ * 父镜像名称
+ */
+ @JsonProperty(value = "parent_image_name")
+ @ApiModelProperty("父镜像名称")
+ private String parentImageName;
+ /**
+ * 父镜像名称
+ */
+ @JsonProperty(value = "create_time")
+ @ApiModelProperty("创建时间")
+ private Date createTime;
/**
* 还原方式
diff --git a/nex-be/src/main/java/com/unisinsight/project/entity/res/VncData.java b/nex-be/src/main/java/com/unisinsight/project/entity/res/VncData.java
new file mode 100644
index 0000000..4c8053e
--- /dev/null
+++ b/nex-be/src/main/java/com/unisinsight/project/entity/res/VncData.java
@@ -0,0 +1,33 @@
+package com.unisinsight.project.entity.res;
+
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author : ch
+ * @version : 1.0
+ * @ClassName : VncData
+ * @Description :
+ * @DATE : Created in 9:41 2025/9/8
+ *
Copyright: Copyright(c) 2025
+ * Company : 紫光汇智信息技术有限公司
+ * Modification History:
+ * Date Author Version Discription
+ * --------------------------------------------------------------------------
+ * 2025/09/08 ch 1.0 Why & What is modified: <修改原因描述> *
+ */
+@NoArgsConstructor
+@Data
+public class VncData {
+
+ @JsonProperty("host")
+ private String host;
+ @JsonProperty("port")
+ private Integer port;
+ @JsonProperty("url")
+ private String url;
+ @JsonProperty("websocket_url")
+ private String websocketUrl;
+}
diff --git a/nex-be/src/main/java/com/unisinsight/project/feign/ExternalApiClient.java b/nex-be/src/main/java/com/unisinsight/project/feign/ExternalApiClient.java
index e92251e..ca889bb 100644
--- a/nex-be/src/main/java/com/unisinsight/project/feign/ExternalApiClient.java
+++ b/nex-be/src/main/java/com/unisinsight/project/feign/ExternalApiClient.java
@@ -4,6 +4,7 @@ import com.unisinsight.project.config.FeignConfig;
import com.unisinsight.project.entity.dto.*;
import com.unisinsight.project.entity.req.*;
import com.unisinsight.project.entity.res.ImageStatusRes;
+import com.unisinsight.project.entity.res.VncData;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;
@@ -90,5 +91,7 @@ public interface ExternalApiClient {
@GetMapping("/api/v1/network/bridge-interfaces")
ApiResponse> getBridgeInterfaces();
+ @GetMapping("/api/v1/vm/{vmName}/vnc")
+ ApiResponse getVncData(@PathVariable("vmName") String vmName);
}
diff --git a/nex-be/src/main/java/com/unisinsight/project/grpc/service/ClientNotificationServiceImpl.java b/nex-be/src/main/java/com/unisinsight/project/grpc/service/ClientNotificationServiceImpl.java
index bcc8fec..b57401f 100644
--- a/nex-be/src/main/java/com/unisinsight/project/grpc/service/ClientNotificationServiceImpl.java
+++ b/nex-be/src/main/java/com/unisinsight/project/grpc/service/ClientNotificationServiceImpl.java
@@ -41,7 +41,7 @@ public class ClientNotificationServiceImpl extends NotificationServiceGrpc.Notif
private final ConcurrentHashMap> clientStreamMap =
new ConcurrentHashMap<>();
private final static int MAX_CLIENT_COUNT = 1000;
-
+ public static final String DEFAULT_USER = "NexOS";
// 生成客户端连接key的工具方法
private String generateClientKey(String clientId, String clientUser) {
return clientId + "#" + clientUser;
@@ -70,15 +70,7 @@ public class ClientNotificationServiceImpl extends NotificationServiceGrpc.Notif
return; // 避免继续执行后续逻辑
}
- if (StringUtil.isEmpty(clientUser)) {
- NotificationMessage errMsg = NotificationMessage.newBuilder()
- .setCode(HttpStatus.BAD_REQUEST.value())
- .setMsg("client_user不能为空")
- .build();
- responseObserver.onNext(errMsg);
- responseObserver.onCompleted();
- return; // 避免继续执行后续逻辑
- }
+ clientUser= StringUtil.isEmpty(clientUser) ? DEFAULT_USER : clientUser;
log.info("客户端连接:client_sn:[{}],client_user: [{}]", clientSn, clientUser);
@@ -93,11 +85,12 @@ public class ClientNotificationServiceImpl extends NotificationServiceGrpc.Notif
final io.grpc.Context context = io.grpc.Context.current();
// 注册一个取消监听器来监听客户端断开连接
+ String finalClientUser = clientUser;
context.addListener(context1 -> {
// 客户端断开连接时的处理逻辑
- log.info("通过Context监听到客户端断开连接: {}, 用户: {}", clientSn, clientUser);
- removeClientConnection(clientSn, clientUser);
- log.info("清理客户端连接: {}#{}, 剩余客户端数: {}", clientSn, clientUser, clientStreamMap.size());
+ log.info("通过Context监听到客户端断开连接: {}, 用户: {}", clientSn, finalClientUser);
+ removeClientConnection(clientSn, finalClientUser);
+ log.info("清理客户端连接: {}#{}, 剩余客户端数: {}", clientSn, finalClientUser, clientStreamMap.size());
}, executorService);
}
diff --git a/nex-be/src/main/java/com/unisinsight/project/service/ImageVirtualMachinesService.java b/nex-be/src/main/java/com/unisinsight/project/service/ImageVirtualMachinesService.java
index 8767b0b..641e958 100644
--- a/nex-be/src/main/java/com/unisinsight/project/service/ImageVirtualMachinesService.java
+++ b/nex-be/src/main/java/com/unisinsight/project/service/ImageVirtualMachinesService.java
@@ -61,5 +61,7 @@ public interface ImageVirtualMachinesService extends IService removeIso(ImageVirtualMachinesReq req);
Result> attachIso(ImageVirtualMachinesReq req);
+
+ Result> getVncData(String vmName);
}
diff --git a/nex-be/src/main/java/com/unisinsight/project/service/impl/DeviceImageMappingServiceImpl.java b/nex-be/src/main/java/com/unisinsight/project/service/impl/DeviceImageMappingServiceImpl.java
index 1670d0a..e3b0d66 100644
--- a/nex-be/src/main/java/com/unisinsight/project/service/impl/DeviceImageMappingServiceImpl.java
+++ b/nex-be/src/main/java/com/unisinsight/project/service/impl/DeviceImageMappingServiceImpl.java
@@ -7,23 +7,18 @@ import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.unisinsight.project.entity.dao.DeviceImageMapping;
-import com.unisinsight.project.entity.dao.Image;
-import com.unisinsight.project.entity.dao.ImageDesktop;
-import com.unisinsight.project.entity.dao.UserDeviceGroup;
+import com.unisinsight.project.entity.dao.*;
import com.unisinsight.project.entity.req.DeviceImageMappingReq;
import com.unisinsight.project.entity.res.DeviceImageMappingRes;
import com.unisinsight.project.exception.Result;
-import com.unisinsight.project.mapper.DeviceImageMappingMapper;
-import com.unisinsight.project.mapper.ImageDesktopMapper;
-import com.unisinsight.project.mapper.ImageMapper;
-import com.unisinsight.project.mapper.UserDeviceGroupMapper;
+import com.unisinsight.project.mapper.*;
import com.unisinsight.project.service.DeviceImageMappingService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
@@ -43,6 +38,8 @@ public class DeviceImageMappingServiceImpl extends ServiceImpl imageLambdaQueryWrapper = new LambdaQueryWrapper().in(ImageDesktop::getId, imageIds);
List images = imageDesktopMapper.selectList(imageLambdaQueryWrapper);
+ List imageVirtualIdList = images.stream().map(ImageDesktop::getImageVirtualId).filter(Objects::nonNull).collect(Collectors.toList());
+ LambdaQueryWrapper imageVirtualMachinesLambdaQueryWrapper = new LambdaQueryWrapper().in(ImageVirtualMachines::getId, imageVirtualIdList);
+ List imageVirtualMachines = imageVirtualMachinesMapper.selectList(imageVirtualMachinesLambdaQueryWrapper);
+ Map imageVirtualMachinesMap = imageVirtualMachines.stream().collect(Collectors.toMap(ImageVirtualMachines::getId, ImageVirtualMachines::getImageName));
+
if (CollectionUtil.isNotEmpty(images)) {
deviceImageMappingRes.forEach(deviceImage -> images.forEach(image -> {
if (ObjectUtil.isNotEmpty(deviceImage.getImageId()) && image.getId().equals(deviceImage.getImageId())) {
deviceImage.setImageName(image.getDesktopName());
deviceImage.setImageFileName(image.getDesktopName()+"."+image.getDesktopType());
+ deviceImage.setCreateTime(image.getCreateTime());
+ // 设置父镜像名称
+ if (image.getImageVirtualId() != null) {
+ deviceImage.setParentImageName(imageVirtualMachinesMap.get(image.getImageVirtualId().longValue()));
+ }
}
}));
}
diff --git a/nex-be/src/main/java/com/unisinsight/project/service/impl/ImageVirtualMachinesServiceImpl.java b/nex-be/src/main/java/com/unisinsight/project/service/impl/ImageVirtualMachinesServiceImpl.java
index a1033fc..7130459 100644
--- a/nex-be/src/main/java/com/unisinsight/project/service/impl/ImageVirtualMachinesServiceImpl.java
+++ b/nex-be/src/main/java/com/unisinsight/project/service/impl/ImageVirtualMachinesServiceImpl.java
@@ -17,6 +17,7 @@ import com.unisinsight.project.entity.req.*;
import com.unisinsight.project.entity.res.ImageStatusRes;
import com.unisinsight.project.entity.res.ImageVirtualMachinesRes;
import com.unisinsight.project.entity.res.PageResult;
+import com.unisinsight.project.entity.res.VncData;
import com.unisinsight.project.exception.BaseErrorCode;
import com.unisinsight.project.exception.Result;
import com.unisinsight.project.feign.ExternalApiClient;
@@ -323,7 +324,7 @@ public class ImageVirtualMachinesServiceImpl extends ServiceImpl getVncData(String vmName) {
+ ApiResponse vncData = externalApiClient.getVncData(vmName);
+ if ("200".equals(vncData.getCode())){
+ return Result.successResult(vncData.getData());
+ }
+ return Result.errorResultMessage(BaseErrorCode.HTTP_ERROR_CODE_500, vncData.getMessage());
+ }
+
}