树列表

This commit is contained in:
ZZX9599
2025-09-28 15:10:29 +08:00
parent c51652000c
commit dea2dbd508
8 changed files with 201 additions and 79 deletions

View File

@ -1,9 +1,12 @@
package com.yj.earth.common.config;
import com.yj.earth.common.util.SdkUtil;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Data
@Component
public class ServerConfig {
@ -13,6 +16,10 @@ public class ServerConfig {
@Value("${server.host}")
private String host;
@Value("${sdk.port}")
private int sdkPort;
@PostConstruct
public void initSdkPort() {
this.sdkPort = SdkUtil.getServerPortFromSdkConfig();
}
}

View File

@ -2,10 +2,10 @@ package com.yj.earth.common.util;
import com.yj.earth.common.constant.GlobalConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import org.yaml.snakeyaml.Yaml;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
@ -18,24 +18,22 @@ import java.util.stream.Collectors;
public class SdkUtil {
// 保存SDK进程引用
private static Process sdkProcess;
// 保存SDK端口号、用于关闭时强制终止
private static Integer sdkPort;
// 对外提供的启动入口
public static void startSdkIfConfigured() throws IOException {
// 读取配置
sdkPort = getSdkPortFromYamlConfig();
// 读取SDK端口
Integer serverPort = getServerPortFromSdkConfig();
// 未配置则不启动
if (sdkPort == null) {
log.info("请先配置SDK端口");
if (serverPort == null) {
log.info("配置SDK端口");
return;
}
// 配置存在时、正常启动SDK
startSdkJar(sdkPort);
startSdkJar(serverPort);
}
// 接收已确认的端口、启动SDK
private static void startSdkJar(int sdkPort) throws IOException {
private static void startSdkJar(int serverPort) throws IOException {
// 获取项目根目录(当前工作目录)
String projectRoot = System.getProperty("user.dir");
// 获取SDK完整路径
@ -44,20 +42,41 @@ public class SdkUtil {
File sdkJarFile = new File(sdkJarPath);
if (!sdkJarFile.exists() || !sdkJarFile.isFile()) {
log.error("SDK不存在或不是有效文件:{}", sdkJarPath);
return;
}
// 获取SDK所在目录sdk目录
File sdkDir = sdkJarFile.getParentFile();
if (sdkDir == null || !sdkDir.exists()) {
log.error("无法获取SDK所在目录:{}", sdkJarPath);
return;
}
// 构建JDK的java可执行文件路径适配新目录结构
String javaExecutablePath = getJavaExecutablePath(sdkDir);
File javaExecutable = new File(javaExecutablePath);
if (!javaExecutable.exists() || !javaExecutable.canExecute()) {
log.error("JDK可执行文件不存在或不可执行:{}", javaExecutablePath);
return;
}
log.info("准备启动SDK: {}", sdkJarPath);
log.info("使用SDK端口: {}", sdkPort);
log.info("使用JDK路径: {}", javaExecutablePath);
log.info("使用SDK端口: {}", serverPort);
// 构建启动命令、添加 -Dserver.port 参数
List<String> command = new ArrayList<>();
command.add("java");
command.add("-Dserver.port=" + sdkPort);
command.add(javaExecutablePath); // 使用指定路径的java
command.add("-Dserver.port=" + serverPort);
command.add("-jar");
command.add(sdkJarPath);
// 构建进程启动器
ProcessBuilder processBuilder = new ProcessBuilder(command);
// 打印执行的命令
String commandStr = command.stream().collect(Collectors.joining(" "));
log.info("执行命令: {}", commandStr);
// 输出SDK的控制台日志到当前应用的日志中
processBuilder.redirectErrorStream(true);
// 日志文件路径建议优化: 避免与项目根目录混淆
@ -67,9 +86,11 @@ public class SdkUtil {
sdkLogFile.getParentFile().mkdirs();
}
processBuilder.redirectOutput(sdkLogFile);
// 启动进程(非阻塞)
sdkProcess = processBuilder.start();
log.info("SDK已在后台启动、进程ID: {}", sdkProcess.pid());
// 注册JVM关闭钩子、在主程序退出时关闭SDK进程
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
if (sdkProcess != null && sdkProcess.isAlive()) {
@ -82,13 +103,13 @@ public class SdkUtil {
if (terminated) {
log.info("SDK进程已成功停止");
} else {
log.warn("SDK进程未能正常停止、尝试通过端口{}强制终止...", sdkPort);
log.warn("SDK进程未能正常停止、尝试通过端口{}强制终止...", serverPort);
// 通过端口强制终止
boolean killSuccess = PortKillUtil.killProcessByPort(sdkPort);
boolean killSuccess = PortKillUtil.killProcessByPort(serverPort);
if (killSuccess) {
log.info("已通过端口{}强制终止SDK进程", sdkPort);
log.info("已通过端口{}强制终止SDK进程", serverPort);
} else {
log.error("通过端口{}强制终止SDK进程失败", sdkPort);
log.error("通过端口{}强制终止SDK进程失败", serverPort);
}
}
} catch (InterruptedException e) {
@ -100,26 +121,61 @@ public class SdkUtil {
}
/**
* 从配置文件读取SDK端口配置
* 根据新目录结构获取JDK的java可执行文件路径
*/
private static Integer getSdkPortFromYamlConfig() {
private static String getJavaExecutablePath(File sdkDir) {
// 从sdk目录向上两级找到根目录sdk -> app -> 根目录)
File appDir = sdkDir.getParentFile();
if (appDir == null || !appDir.exists()) {
log.error("无法获取app目录sdk的父目录");
return null;
}
File rootDir = appDir.getParentFile();
if (rootDir == null || !rootDir.exists()) {
log.error("无法获取根目录app的父目录");
return null;
}
// 判断操作系统类型
boolean isWindows = System.getProperty("os.name").toLowerCase().contains("win");
// 构建JDK路径根目录/jdk/bin/java(或java.exe)
String javaRelativePath = "jdk" + File.separator + "bin" + File.separator +
(isWindows ? "java.exe" : "java");
return new File(rootDir, javaRelativePath).getAbsolutePath();
}
/**
* 从sdk文件夹下的application.yml读取server.port配置
*/
public static Integer getServerPortFromSdkConfig() {
Yaml yaml = new Yaml();
try (InputStream inputStream = new ClassPathResource("application.yml").getInputStream()) {
String projectRoot = System.getProperty("user.dir");
File sdkConfigFile = new File(projectRoot, "sdk/application.yml");
if (!sdkConfigFile.exists() || !sdkConfigFile.isFile()) {
log.error("配置文件不存在: {}", sdkConfigFile.getAbsolutePath());
return null;
}
try (InputStream inputStream = new FileInputStream(sdkConfigFile)) {
// 解析YAML文件为Map
Map<String, Object> yamlMap = yaml.load(inputStream);
// 逐级获取配置
if (yamlMap.containsKey("sdk")) {
Object sdkObj = yamlMap.get("sdk");
if (sdkObj instanceof Map) {
Map<?, ?> sdkMap = (Map<?, ?>) sdkObj;
if (sdkMap.containsKey("port")) {
return ((Number) sdkMap.get("port")).intValue();
// 逐级获取server.port配置
if (yamlMap.containsKey("server")) {
Object serverObj = yamlMap.get("server");
if (serverObj instanceof Map) {
Map<?, ?> serverMap = (Map<?, ?>) serverObj;
if (serverMap.containsKey("port")) {
return ((Number) serverMap.get("port")).intValue();
}
}
}
log.error("未配置SDK端口");
log.error("sdk配置文件中未配置server.port");
} catch (IOException e) {
log.error("读取配置文件失败", e);
log.error("读取sdk配置文件失败", e);
} catch (ClassCastException e) {
log.error("sdk配置文件中server.port格式错误应为数字类型", e);
}
return null;
}