From 28ef203b909f4f2a23bb4535873b645f017f20ba Mon Sep 17 00:00:00 2001 From: xiaohucoding <2307520758@qq.com> Date: Wed, 30 Jul 2025 12:15:30 +0800 Subject: [PATCH] =?UTF-8?q?=E6=95=B4=E4=BD=93=E9=9C=80=E6=B1=82=E5=AE=8C?= =?UTF-8?q?=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...-b616-449f-a4f1-f5b94bbdb0a4_quick_sort.py | 57 +++++++++++++ ...-c0bf-4be3-a6c3-57e5c49208f4_quick_sort.py | 57 +++++++++++++ .../Impl/AlgorithmInfoServiceImpl.java | 85 +++++++++++++------ src/main/resources/application.properties | 3 + 4 files changed, 175 insertions(+), 27 deletions(-) create mode 100644 algorithm_files/0697dcd7-b616-449f-a4f1-f5b94bbdb0a4_quick_sort.py create mode 100644 algorithm_files/4ec4bfbc-c0bf-4be3-a6c3-57e5c49208f4_quick_sort.py diff --git a/algorithm_files/0697dcd7-b616-449f-a4f1-f5b94bbdb0a4_quick_sort.py b/algorithm_files/0697dcd7-b616-449f-a4f1-f5b94bbdb0a4_quick_sort.py new file mode 100644 index 0000000..5901739 --- /dev/null +++ b/algorithm_files/0697dcd7-b616-449f-a4f1-f5b94bbdb0a4_quick_sort.py @@ -0,0 +1,57 @@ +import random +import sys + +def quick_sort(arr): + """ + 快速排序主函数,支持空数组处理 + """ + if len(arr) <= 1: + return arr + + def partition(low, high): + pivot_index = random.randint(low, high) # 随机选择基准 + arr[pivot_index], arr[high] = arr[high], arr[pivot_index] + pivot = arr[high] + i = low - 1 + + for j in range(low, high): + if arr[j] <= pivot: + i += 1 + arr[i], arr[j] = arr[j], arr[i] + + arr[i+1], arr[high] = arr[high], arr[i+1] + return i + 1 + + def recur_sort(low, high): + if low < high: + pi = partition(low, high) + recur_sort(low, pi - 1) + recur_sort(pi + 1, high) + + recur_sort(0, len(arr) - 1) + return arr + +if __name__ == "__main__": + # 从命令行参数读取数据 + if len(sys.argv) > 1: + try: + # 处理多种输入格式:逗号分隔、空格分隔或混合分隔 + input_str = " ".join(sys.argv[1:]) + input_data = [float(x) if '.' in x else int(x) + for x in input_str.replace(',', ' ').split()] + + print("原始输入:", sys.argv[1:]) + print("解析数据:", input_data) + + sorted_arr = quick_sort(input_data.copy()) + print("排序结果:", sorted_arr) + + except ValueError: + print("错误:输入数据包含非数字字符,请确保只输入数字") + print("用法: python script.py [数字1 数字2 ...]") + print("示例: python script.py 3 0 8 7 2 1 9 4") + else: + print("未提供输入数据,使用默认测试用例") + test_case = [3, 0, 8, 7, 2, 1, 9, 4] + print("测试数据:", test_case) + print("排序结果:", quick_sort(test_case.copy())) \ No newline at end of file diff --git a/algorithm_files/4ec4bfbc-c0bf-4be3-a6c3-57e5c49208f4_quick_sort.py b/algorithm_files/4ec4bfbc-c0bf-4be3-a6c3-57e5c49208f4_quick_sort.py new file mode 100644 index 0000000..5901739 --- /dev/null +++ b/algorithm_files/4ec4bfbc-c0bf-4be3-a6c3-57e5c49208f4_quick_sort.py @@ -0,0 +1,57 @@ +import random +import sys + +def quick_sort(arr): + """ + 快速排序主函数,支持空数组处理 + """ + if len(arr) <= 1: + return arr + + def partition(low, high): + pivot_index = random.randint(low, high) # 随机选择基准 + arr[pivot_index], arr[high] = arr[high], arr[pivot_index] + pivot = arr[high] + i = low - 1 + + for j in range(low, high): + if arr[j] <= pivot: + i += 1 + arr[i], arr[j] = arr[j], arr[i] + + arr[i+1], arr[high] = arr[high], arr[i+1] + return i + 1 + + def recur_sort(low, high): + if low < high: + pi = partition(low, high) + recur_sort(low, pi - 1) + recur_sort(pi + 1, high) + + recur_sort(0, len(arr) - 1) + return arr + +if __name__ == "__main__": + # 从命令行参数读取数据 + if len(sys.argv) > 1: + try: + # 处理多种输入格式:逗号分隔、空格分隔或混合分隔 + input_str = " ".join(sys.argv[1:]) + input_data = [float(x) if '.' in x else int(x) + for x in input_str.replace(',', ' ').split()] + + print("原始输入:", sys.argv[1:]) + print("解析数据:", input_data) + + sorted_arr = quick_sort(input_data.copy()) + print("排序结果:", sorted_arr) + + except ValueError: + print("错误:输入数据包含非数字字符,请确保只输入数字") + print("用法: python script.py [数字1 数字2 ...]") + print("示例: python script.py 3 0 8 7 2 1 9 4") + else: + print("未提供输入数据,使用默认测试用例") + test_case = [3, 0, 8, 7, 2, 1, 9, 4] + print("测试数据:", test_case) + print("排序结果:", quick_sort(test_case.copy())) \ No newline at end of file diff --git a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/Impl/AlgorithmInfoServiceImpl.java b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/Impl/AlgorithmInfoServiceImpl.java index f631492..7c3ce18 100644 --- a/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/Impl/AlgorithmInfoServiceImpl.java +++ b/src/main/java/com/bipt/intelligentapplicationorchestrationservice/service/Impl/AlgorithmInfoServiceImpl.java @@ -3,6 +3,7 @@ package com.bipt.intelligentapplicationorchestrationservice.service.Impl; import com.bipt.intelligentapplicationorchestrationservice.mapper.AlgorithmInfoMapper; import com.bipt.intelligentapplicationorchestrationservice.pojo.AlgorithmInfo; import com.bipt.intelligentapplicationorchestrationservice.service.AlgorithmInfoService; +import jakarta.servlet.ServletContext; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -11,10 +12,7 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; import org.springframework.web.multipart.MultipartFile; -import java.io.BufferedReader; -import java.io.File; -import java.io.IOException; -import java.io.InputStreamReader; +import java.io.*; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; @@ -31,8 +29,10 @@ public class AlgorithmInfoServiceImpl implements AlgorithmInfoService { @Autowired private AlgorithmInfoMapper algorithmInfoMapper; - @Value("${algorithm.upload.dir:/tmp/algorithm-files/}") // 默认上传目录 + // 从配置文件读取上传目录 + @Value("${algorithm.upload.dir:algorithm_files}") private String uploadDir; + @Override public AlgorithmInfo getById(Long id) { return algorithmInfoMapper.selectById(id); @@ -78,6 +78,11 @@ public class AlgorithmInfoServiceImpl implements AlgorithmInfoService { return true; } + /** + * 新增算法 + * @param algorithmInfo + * @param file + */ @Override @Transactional public void save(AlgorithmInfo algorithmInfo, MultipartFile file) { @@ -99,32 +104,31 @@ public class AlgorithmInfoServiceImpl implements AlgorithmInfoService { // 生成唯一文件名,避免冲突 String fileName = UUID.randomUUID().toString() + "_" + originalFilename; - // 关键修改:使用实际存在的绝对路径(替换为你的实际路径,如 D:/algorithm_files) - // 建议在配置文件中配置,而非硬编码 - String uploadDir = "D:/algorithm_files"; // 例如:Windows 路径用 D:/xxx,Linux 用 /home/xxx + // 构建相对路径(相对于项目根目录) + Path relativePath = Paths.get(uploadDir, fileName); - // 构建路径对象(使用 Path 而非 File,更适合跨平台) - Path saveDirPath = Paths.get(uploadDir); + // 获取当前应用的运行目录(兼容开发和部署环境) + Path basePath = Paths.get("").toAbsolutePath(); + Path absolutePath = basePath.resolve(relativePath); - // 确保目录存在(createDirectories 会创建所有不存在的父目录,跨平台兼容) - if (!Files.exists(saveDirPath)) { - Files.createDirectories(saveDirPath); // 关键:创建多级目录 - log.info("已创建存储目录: {}", saveDirPath.toAbsolutePath()); + // 确保目录存在 + Path parentDir = absolutePath.getParent(); + if (!Files.exists(parentDir)) { + Files.createDirectories(parentDir); + log.info("已创建存储目录: {}", parentDir); } - // 完整文件路径 - Path saveFilePath = saveDirPath.resolve(fileName); - // 保存文件到指定路径 - file.transferTo(saveFilePath); // 使用 Path 重载方法,更可靠 + file.transferTo(absolutePath); - // 设置文件路径到实体类(存储绝对路径或可访问的相对路径) - algorithmInfo.setAlgorithmFile(saveFilePath.toString()); + // 存储相对路径到数据库 + algorithmInfo.setAlgorithmFile(relativePath.toString()); // 设置文件大小 - algorithmInfo.setFileSize(Files.size(saveFilePath)); + algorithmInfo.setFileSize(Files.size(absolutePath)); - log.info("文件保存成功: {}", saveFilePath.toAbsolutePath()); + log.info("文件保存成功 - 相对路径: {}, 绝对路径: {}", + relativePath, absolutePath); } catch (Exception e) { log.error("文件保存失败", e); throw new RuntimeException("文件保存失败: " + e.getMessage(), e); @@ -132,7 +136,7 @@ public class AlgorithmInfoServiceImpl implements AlgorithmInfoService { } else { // 文件为空的处理逻辑 algorithmInfo.setAlgorithmFile(null); - algorithmInfo.setFileSize(0L); // 空文件大小设为0 + algorithmInfo.setFileSize(0L); } algorithmInfo.setCreateTime(LocalDateTime.now()); @@ -142,15 +146,33 @@ public class AlgorithmInfoServiceImpl implements AlgorithmInfoService { /** * 执行Python算法脚本并返回结果 - * @param scriptPath Python脚本路径 + * @param scriptPath Python脚本路径(数据库中存储的相对路径) * @param args 命令行参数列表 * @return 脚本执行结果 */ public String run(String scriptPath, List args) throws IOException, InterruptedException { - // 构建命令:python [脚本路径] [参数1] [参数2] ... + if (scriptPath == null || scriptPath.isEmpty()) { + throw new IllegalArgumentException("脚本路径不能为空"); + } + + // 获取当前应用的运行目录(兼容开发和部署环境) + Path basePath = Paths.get("").toAbsolutePath(); + Path absoluteScriptPath = basePath.resolve(scriptPath); + + // 验证文件是否存在 + if (!Files.exists(absoluteScriptPath)) { + throw new FileNotFoundException("脚本文件不存在: " + absoluteScriptPath); + } + + // 验证文件是否可执行(针对Python脚本) + if (!Files.isReadable(absoluteScriptPath)) { + throw new IOException("脚本文件不可读: " + absoluteScriptPath); + } + + // 构建命令:python [脚本绝对路径] [参数1] [参数2] ... List command = new ArrayList<>(); command.add("python"); // Python解释器路径,可配置在application.properties中 - command.add(scriptPath); // 脚本路径 + command.add(absoluteScriptPath.toString()); // 使用绝对路径执行脚本 command.addAll(args); // 添加所有参数 // 打印完整命令(用于调试) @@ -158,6 +180,10 @@ public class AlgorithmInfoServiceImpl implements AlgorithmInfoService { // 创建进程并执行命令 ProcessBuilder processBuilder = new ProcessBuilder(command); + + // 设置工作目录为脚本所在目录 + processBuilder.directory(absoluteScriptPath.getParent().toFile()); + processBuilder.redirectErrorStream(true); // 将错误输出合并到标准输出 Process process = processBuilder.start(); @@ -176,7 +202,12 @@ public class AlgorithmInfoServiceImpl implements AlgorithmInfoService { // 检查脚本是否成功执行 if (exitCode != 0) { - throw new RuntimeException("脚本执行失败,退出码: " + exitCode); + // 捕获详细的错误信息 + String errorMsg = "脚本执行失败,退出码: " + exitCode + + "\n命令: " + String.join(" ", command) + + "\n输出: " + output.toString(); + log.error(errorMsg); + throw new RuntimeException(errorMsg); } return output.toString(); diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index a7ba8c7..e5b7ac8 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -60,3 +60,6 @@ spring.profiles.active=dev #配置IP列表(后续根据需求修改ip数据,以下仅为测试用例) available.ips=192.168.1.100,192.168.1.101,192.168.1.102 +# 算法文件上传目录(相对于项目根目录) +algorithm.upload.dir=algorithm_files +