整体需求完善

This commit is contained in:
2025-07-30 12:15:30 +08:00
parent c254e2f94c
commit 28ef203b90
4 changed files with 175 additions and 27 deletions

View File

@ -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:/xxxLinux 用 /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<String> 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<String> 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();

View File

@ -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