iailab-module-data/iailab-module-data-api/src/main/java/com/iailab/module/data/api/ind/IndItemApi.java
@@ -25,10 +25,10 @@ String PREFIX = ApiConstants.PREFIX + "/ind-item"; @GetMapping(PREFIX + "/query-ind/default-value") @Operation(summary = "查询指标项") @Operation(summary = "查询指标默认值") List<ApiIndItemValueDTO> queryIndItemDefaultValue(@RequestParam String itemNo); @PostMapping(PREFIX + "/query-ind/history-value") @Operation(summary = "查询指标项") @Operation(summary = "查询指标历史值") List<ApiIndItemValueDTO> queryIndItemHistoryValue(@RequestBody ApiIndItemQueryDTO dto); } iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/api/controller/ApiDataController.java
文件名从 iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/api/controller/DataController.java 修改 @@ -22,6 +22,7 @@ import org.springframework.util.CollectionUtils; import org.springframework.web.bind.annotation.*; import javax.annotation.security.PermitAll; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.math.BigDecimal; @@ -39,7 +40,7 @@ @RestController @RequestMapping("/api/data") @Tag(name = "数据") public class DataController { public class ApiDataController { @Resource private DaPointService daPointService; @@ -56,6 +57,7 @@ @Resource private PointCollector pointCollector; @PermitAll @PostMapping("/point/history") @Operation(summary = "point历史数据") public CommonResult<Map<String, List<Map<String, Object>>>> pointHistory(HttpServletResponse response, HttpServletRequest iailab-module-data/iailab-module-data-biz/src/main/java/com/iailab/module/data/api/controller/ApiIndItemController.java
对比新文件 @@ -0,0 +1,53 @@ package com.iailab.module.data.api.controller; import com.iailab.framework.common.pojo.CommonResult; import com.iailab.framework.common.util.object.ConvertUtils; import com.iailab.module.data.api.ind.dto.ApiIndItemQueryDTO; import com.iailab.module.data.api.ind.dto.ApiIndItemValueDTO; import com.iailab.module.data.ind.collection.IndItemCollector; import com.iailab.module.data.ind.item.vo.IndItemValueVO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import javax.annotation.security.PermitAll; import java.util.List; import static com.iailab.framework.common.pojo.CommonResult.success; /** * @author PanZhibao * @Description * @createTime 2024年10月10日 */ @Slf4j @RestController @RequestMapping("/api/data/ind-item") @Tag(name = "指标") public class ApiIndItemController { @Autowired private IndItemCollector indItemCollector; @PermitAll @GetMapping("/query-ind/default-value") @Operation(summary = "查询指标默认值") public CommonResult<List<ApiIndItemValueDTO>> queryIndItemDefaultValue(@RequestParam String itemNo) { List<IndItemValueVO> list = indItemCollector.queryValue(itemNo); return success(ConvertUtils.sourceToTarget(list, ApiIndItemValueDTO.class)); } @PermitAll @GetMapping("/query-ind/history-value") @Operation(summary = "查询指标历史值") public CommonResult<List<ApiIndItemValueDTO>> queryIndItemHistoryValue(@RequestParam ApiIndItemQueryDTO dto) { List<IndItemValueVO> list = indItemCollector.queryValue(dto.getItemNo(), dto.getStart(), dto.getEnd()); return success(ConvertUtils.sourceToTarget(list, ApiIndItemValueDTO.class)); } } iailab-module-data/iailab-module-data-biz/src/main/resources/application-prod.yml
@@ -61,7 +61,7 @@ token: FLkSbhpYgPrMJBNnOdmxuY3YcG8D_roPtdGPEhwXW9JSxJkEPe1sXUkrYgWcV-nOL9Zjm09RoTfMW44NoRYaXA== url: http://192.168.55.180:8086 username: root password: ntt12345678 password: iailab12345678 iems: upload-dir: C:/DLUT/upload/ iailab-module-data/iailab-module-data-biz/src/main/resources/application-test.yaml
@@ -51,8 +51,8 @@ influx-db: org: iailab bucket: iailab_data token: 2_wr57sVbZQx2QHhN3wWNGOCOtPan_NdCu06NsCGcB8G7rjhjK3yHcLf3uTXE9xkjHHSQwo37E1Mxa0367qXgg== bucket: buk_shasteel token: Q2qsriQG3FEfZ35lik1KSkFToma3bsgfQLwJrNQfSK06MC569sZ9mrQ0vLtsVYn70HMfQcC9gf_yUG16JQtm8w== url: http://172.16.8.200:8086 username: root password: iailab12345678 iailab-module-model/iailab-module-model-api/src/main/java/com/iailab/module/model/api/mcs/McsApi.java
@@ -1,10 +1,7 @@ package com.iailab.module.model.api.mcs; import com.iailab.framework.common.pojo.CommonResult; import com.iailab.module.model.api.mcs.dto.AlarmMessageDTO; import com.iailab.module.model.api.mcs.dto.PredictItemInfoDTO; import com.iailab.module.model.api.mcs.dto.PredictItemTreeDTO; import com.iailab.module.model.api.mcs.dto.ScheduleSuggestDTO; import com.iailab.module.model.api.mcs.dto.*; import com.iailab.module.model.enums.ApiConstants; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -23,7 +20,7 @@ * @createTime 2024年08月26日 */ @FeignClient(name = ApiConstants.NAME) @Tag(name = "RPC 服务 - MCS") @Tag(name = "RPC 服务 - 模型配置接口") public interface McsApi { String PREFIX = ApiConstants.PREFIX + "/mcs"; @@ -38,18 +35,25 @@ @PostMapping(PREFIX + "/alarm-message/create") @Operation(summary = "添加预警信息") CommonResult<Boolean> createAlarmMessage(@RequestBody AlarmMessageDTO dto); CommonResult<Boolean> createAlarmMessage(@RequestBody AlarmMessageRespDTO dto); @GetMapping(PREFIX + "/alarm-message/list") @Operation(summary = "获取预警信息") CommonResult<AlarmMessageDTO> listAlarmMessage(@RequestParam Map<String, Object> params); @Operation(summary = "获取预警信息列表") CommonResult<AlarmMessageRespDTO> listAlarmMessage(@RequestParam Map<String, Object> params); @PostMapping(PREFIX + "/schedule-suggest/create") @Operation(summary = "添加调度建议") CommonResult<Boolean> createScheduleSuggest(@RequestBody ScheduleSuggestDTO dto); CommonResult<Boolean> createScheduleSuggest(@RequestBody ScheduleSuggestRespDTO dto); @GetMapping(PREFIX + "/alarm-message/list") @Operation(summary = "获取调度建议") CommonResult<ScheduleSuggestDTO> listScheduleSuggest(@RequestParam Map<String, Object> params); @Operation(summary = "获取调度建议列表") CommonResult<ScheduleSuggestRespDTO> listScheduleSuggest(@RequestParam ScheduleSuggestReqDTO params); @PostMapping(PREFIX + "/predict-model-setting/modify") @Operation(summary = "修改预测模型设置参数") CommonResult<Boolean> modifyPredictModelSetting(@RequestBody List<PredictModelSettingReqDTO> dtos); @PostMapping(PREFIX + "/schedule-model-setting/modify") @Operation(summary = "修改调度模型设置参数") CommonResult<Boolean> modifyScheduleModelSetting(@RequestBody List<ScheduleModelSettingReqDTO> dtos); } iailab-module-model/iailab-module-model-api/src/main/java/com/iailab/module/model/api/mcs/dto/AlarmMessageReqDTO.java
对比新文件 @@ -0,0 +1,36 @@ package com.iailab.module.model.api.mcs.dto; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.io.Serializable; import java.util.Date; /** * @author PanZhibao * @Description * @createTime 2024年10月10日 */ @Schema(description = "RPC 模型 - 预警消息 DTO") @Data public class AlarmMessageReqDTO implements Serializable { private static final long serialVersionUID = 1L; @Schema(description = "监控对象") private String alarmObj; @Schema(description = "监控点位ID") private String pointId; @Schema(description = "预测项ID") private String itemId; @Schema(description = "预警时间") private Date alarmTime; @Schema(description = "开始时间") private Date startTime; @Schema(description = "结束时间") private Date endTime; } iailab-module-model/iailab-module-model-api/src/main/java/com/iailab/module/model/api/mcs/dto/AlarmMessageRespDTO.java
文件名从 iailab-module-model/iailab-module-model-api/src/main/java/com/iailab/module/model/api/mcs/dto/AlarmMessageDTO.java 修改 @@ -20,7 +20,7 @@ */ @Schema(description = "RPC 模型 - 预警消息 DTO") @Data public class AlarmMessageDTO implements Serializable { public class AlarmMessageRespDTO implements Serializable { private static final long serialVersionUID = 1L; iailab-module-model/iailab-module-model-api/src/main/java/com/iailab/module/model/api/mcs/dto/PredictModelSettingReqDTO.java
对比新文件 @@ -0,0 +1,30 @@ package com.iailab.module.model.api.mcs.dto; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import javax.validation.constraints.NotBlank; import java.io.Serializable; /** * @author PanZhibao * @Description * @createTime 2024年10月10日 */ @Schema(description = "RPC 模型 - 调度建议 DTO") @Data public class PredictModelSettingReqDTO implements Serializable { private static final long serialVersionUID = 1L; private String modelid; /** * 键 */ private String key; /** * 值 */ private String value; } iailab-module-model/iailab-module-model-api/src/main/java/com/iailab/module/model/api/mcs/dto/ScheduleModelSettingReqDTO.java
对比新文件 @@ -0,0 +1,24 @@ package com.iailab.module.model.api.mcs.dto; import java.io.Serializable; /** * @author PanZhibao * @Description * @createTime 2024年10月10日 */ public class ScheduleModelSettingReqDTO implements Serializable { private static final long serialVersionUID = 1L; private String modelid; /** * 键 */ private String key; /** * 值 */ private String value; } iailab-module-model/iailab-module-model-api/src/main/java/com/iailab/module/model/api/mcs/dto/ScheduleSuggestReqDTO.java
对比新文件 @@ -0,0 +1,34 @@ package com.iailab.module.model.api.mcs.dto; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.io.Serializable; import java.util.Date; /** * @author PanZhibao * @Description * @createTime 2024年10月10日 */ @Schema(description = "RPC 模型 - 调度建议req DTO") @Data public class ScheduleSuggestReqDTO implements Serializable { private static final long serialVersionUID = 1L; @Schema(description = "预测项ID") private String itemId; @Schema(description = "模型ID") private String modelId; @Schema(description = "调整对象") private String adjustObj; @Schema(description = "开始时间") private Date startTime; @Schema(description = "结束时间") private Date endTime; } iailab-module-model/iailab-module-model-api/src/main/java/com/iailab/module/model/api/mcs/dto/ScheduleSuggestRespDTO.java
文件名从 iailab-module-model/iailab-module-model-api/src/main/java/com/iailab/module/model/api/mcs/dto/ScheduleSuggestDTO.java 修改 @@ -14,7 +14,7 @@ */ @Schema(description = "RPC 模型 - 调度建议 DTO") @Data public class ScheduleSuggestDTO implements Serializable { public class ScheduleSuggestRespDTO implements Serializable { private static final long serialVersionUID = 1L; iailab-module-model/iailab-module-model-api/src/main/java/com/iailab/module/model/api/mdk/MdkApi.java
@@ -2,11 +2,10 @@ import com.iailab.module.model.api.mdk.dto.*; import com.iailab.module.model.enums.ApiConstants; import com.iailab.framework.common.pojo.CommonResult; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import javax.validation.Valid; @@ -17,25 +16,24 @@ * @createTime 2024年08月26日 */ @FeignClient(name = ApiConstants.NAME) @Tag(name = "RPC 服务 - MDK") @Tag(name = "RPC 服务 - 模型调用接口") public interface MdkApi { String PREFIX = ApiConstants.PREFIX + "/mdk"; @GetMapping(PREFIX + "/predict-module") @Operation(summary = "模块预测") CommonResult<MdkPredictModuleRespDTO> predictModule(@Valid @RequestBody MdkPredictReqDTO reqDTO); @PostMapping(PREFIX + "/predict-module") @Operation(summary = "执行模块预测") MdkPredictModuleRespDTO predictModule(@Valid @RequestBody MdkPredictReqDTO reqDTO); @GetMapping(PREFIX + "/predict-item") @Operation(summary = "单独预测") CommonResult<MdkPredictItemRespDTO> predictItem(@Valid @RequestBody MdkPredictReqDTO reqDTO); @PostMapping(PREFIX + "/predict-item") @Operation(summary = "执行单独预测") MdkPredictItemRespDTO predictItem(@Valid @RequestBody MdkPredictReqDTO reqDTO); @GetMapping(PREFIX + "/predict-auto-adjust") @PostMapping(PREFIX + "/predict-adjust") @Operation(summary = "预测自动调整") CommonResult<Boolean> predictAutoAdjust(@Valid @RequestBody MdkPredictReqDTO reqDTO); Boolean predictAutoAdjust(@Valid @RequestBody MdkPredictReqDTO reqDTO); @GetMapping(PREFIX + "/schedule") @Operation(summary = "执行调度") CommonResult<MdkScheduleRespDTO> doSchedule(@Valid @RequestBody MdkScheduleReqDTO reqDTO); @PostMapping(PREFIX + "/schedule-scheme") @Operation(summary = "执行调度方案") MdkScheduleRespDTO doSchedule(@Valid @RequestBody MdkScheduleReqDTO reqDTO); } iailab-module-model/iailab-module-model-api/src/main/java/com/iailab/module/model/api/mdk/dto/MdkPredictReqDTO.java
@@ -3,6 +3,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import javax.validation.constraints.NotNull; import java.util.Date; /** @@ -14,9 +15,13 @@ @Data public class MdkPredictReqDTO { @Schema(description = "预测时间") @NotNull(message="预测时间不能为空") private Date predictTime; @Schema(description = "预测模块") private String moduleType; @Schema(description = "预测项编号") private String itemNo; } iailab-module-model/iailab-module-model-api/src/main/java/com/iailab/module/model/api/mdk/dto/MdkScheduleReqDTO.java
@@ -3,6 +3,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import javax.validation.constraints.NotNull; import java.util.Date; import java.util.Map; @@ -15,8 +16,12 @@ @Data public class MdkScheduleReqDTO { @Schema(description = "调度方案编号") @NotNull(message="调度方案编号不能为空") private String scheduleCode; @Schema(description = "调度方案时间") @NotNull(message="调度方案时间不能为空") private Date scheduleTime; private String modelCode; iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/ModelServiceApplication.java
@@ -1,27 +1,37 @@ package com.iailab; import com.iailab.module.model.mpk.common.MdkConstant; import com.iailab.module.model.mpk.common.utils.DllUtils; import iail.mdk.model.common.Environment; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.scheduling.annotation.EnableAsync; import javax.annotation.PostConstruct; import java.io.File; import java.io.InputStream; import java.util.Properties; @EnableAsync @SpringBootApplication @Slf4j public class ModelServiceApplication implements CommandLineRunner { static { @Value("${mpk.bak-file-path}") private String mpkBakFilePath; @PostConstruct void init() { //加载动态链接库 try { Properties properties = new Properties(); InputStream in = ModelServiceApplication.class.getClassLoader().getResourceAsStream("iailmdk.properties"); properties.load(in); String mdkInitPath = properties.getProperty("mdk-init-path"); System.out.println("mdkInitPath=" + mdkInitPath); log.info("mdkInitPath=" + mdkInitPath); File file = new File(mdkInitPath + File.separator + "IAIL.MDK.Mid.Windows.dll"); if (!file.exists()) { throw new RuntimeException("动态链接库IAIL.MDK.Mid.Windows.dll文件不存在," + file.getAbsolutePath()); @@ -31,9 +41,16 @@ env.init(); } catch (Exception e) { e.printStackTrace(); System.out.println("动态链接库IAIL.MDK.Mid.Windows.dll初始化失败"); log.error("动态链接库IAIL.MDK.Mid.Windows.dll初始化失败"); } //加载项目已发布的dll和jar try { DllUtils.loadProjectPublish(mpkBakFilePath + File.separator + MdkConstant.PROJECT_PUBLISH); } catch (Exception e) { e.printStackTrace(); log.error("加载项目已发布的dll和jar失败"); } } iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/api/MdkApiImpl.java
@@ -22,10 +22,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.CollectionUtils; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import javax.validation.Valid; import java.util.ArrayList; import java.util.HashMap; @@ -74,7 +71,7 @@ * @return */ @Override public CommonResult<MdkPredictModuleRespDTO> predictModule(MdkPredictReqDTO reqDTO) { public MdkPredictModuleRespDTO predictModule(MdkPredictReqDTO reqDTO) { MdkPredictModuleRespDTO resp = new MdkPredictModuleRespDTO(); Map<String, MdkPredictItemRespDTO> predictItemRespMap = new HashMap<>(); try { @@ -112,10 +109,11 @@ } log.info("预测计算结束: " + System.currentTimeMillis()); } catch (Exception ex) { return error(999, ex.getMessage()); ex.printStackTrace(); return resp; } resp.setPredictItemRespMap(predictItemRespMap); return success(resp); return resp; } /** @@ -125,7 +123,7 @@ * @return */ @Override public CommonResult<MdkPredictItemRespDTO> predictItem(@Valid @RequestBody MdkPredictReqDTO reqDTO) { public MdkPredictItemRespDTO predictItem(MdkPredictReqDTO reqDTO) { MdkPredictItemRespDTO resp = new MdkPredictItemRespDTO(); try { @@ -146,10 +144,10 @@ log.info("预测计算结束: " + System.currentTimeMillis()); } catch (Exception ex) { log.info("预测计算异常: " + System.currentTimeMillis()); ex.printStackTrace(); return resp; } return success(resp); return resp; } /** @@ -159,10 +157,10 @@ * @return */ @Override public CommonResult<Boolean> predictAutoAdjust(@Valid @RequestBody MdkPredictReqDTO reqDTO) { public Boolean predictAutoAdjust(MdkPredictReqDTO reqDTO) { return success(true); return true; } /** @@ -172,7 +170,7 @@ * @return */ @Override public CommonResult<MdkScheduleRespDTO> doSchedule(@Valid @RequestBody MdkScheduleReqDTO reqDTO) { public MdkScheduleRespDTO doSchedule(MdkScheduleReqDTO reqDTO) { MdkScheduleRespDTO resp = new MdkScheduleRespDTO(); resp.setScheduleCode(reqDTO.getScheduleCode()); resp.setScheduleTime(reqDTO.getScheduleTime()); @@ -184,7 +182,8 @@ } catch (Exception ex) { log.info("调度计算异常: " + System.currentTimeMillis()); ex.printStackTrace(); return resp; } return success(resp); return resp; } } iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mdk/predict/PredictModuleHandler.java
@@ -62,6 +62,8 @@ Long drtSave = Duration.between(end, endSave).getSeconds(); log.info(MessageFormat.format("预测项:{0},保存时间:{1}秒", predictItem.getItemName(), drtSave)); result.put(predictItem.getItemNo(), predictResult); } catch (Exception e) { e.printStackTrace(); log.error(MessageFormat.format("预测项编号:{0},预测项名称:{1},预测失败:{2} 预测时刻:{3}", iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mpk/common/MdkConstant.java
@@ -34,4 +34,12 @@ * jar */ String JAR = "jar"; /** * 分隔符 dll、jar文件名 */ String SPLIT = "__"; /** * 项目发布dll和jar目录 */ String PROJECT_PUBLISH = "projectPublish"; } iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mpk/common/utils/DllUtils.java
@@ -1,19 +1,23 @@ package com.iailab.module.model.mpk.common.utils; import cn.hutool.core.io.FileUtil; import com.iailab.module.model.mpk.common.MdkConstant; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import sun.misc.URLClassPath; import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.util.HashMap; import java.util.Iterator; import java.util.Vector; @Slf4j public class DllUtils { private static HashMap<String, URLClassLoader> classLoaderCache = new HashMap<>(); /** * @description: 加载dll到指定class下 @@ -22,14 +26,14 @@ **/ public static void loadDll(Class<?> clazz, String dllPath) { try { Method method = Runtime.class.getDeclaredMethod("load0", Class.class,String.class); Method method = Runtime.class.getDeclaredMethod("load0", Class.class, String.class); boolean accessible = method.isAccessible(); method.setAccessible(true); method.invoke(Runtime.getRuntime(), clazz,dllPath); method.invoke(Runtime.getRuntime(), clazz, dllPath); method.setAccessible(accessible); log.info("成功加载dll:"+ dllPath); log.info("成功加载dll:" + dllPath); } catch (Exception e) { throw new RuntimeException("加载dll异常",e); throw new RuntimeException("加载dll异常", e); } } @@ -38,7 +42,7 @@ * @author: dzd * @date: 2024/9/30 14:31 **/ public static synchronized void uploadDll(URLClassLoader classLoader) { public static synchronized void unloadDll(URLClassLoader classLoader) { try { Field field = ClassLoader.class.getDeclaredField("nativeLibraries"); field.setAccessible(true); @@ -60,7 +64,7 @@ log.info("成功卸载dll:" + name); } } catch (Exception e) { throw new RuntimeException("卸载dll异常",e); throw new RuntimeException("卸载dll异常", e); } } @@ -69,7 +73,7 @@ * @author: dzd * @date: 2024/9/30 14:52 **/ public static synchronized void uploadDllName(URLClassLoader classLoader,String dllName) { public static synchronized void unloadDllName(URLClassLoader classLoader, String dllName) { try { Field field = ClassLoader.class.getDeclaredField("nativeLibraries"); field.setAccessible(true); @@ -93,7 +97,7 @@ log.info("成功卸载dll:" + name); } } catch (Exception e) { throw new RuntimeException("卸载dll异常",e); throw new RuntimeException("卸载dll异常", e); } } @@ -105,24 +109,102 @@ public static synchronized URLClassLoader loadJar(String jarPath) { File jarFile = new File(jarPath); if (!jarFile.exists()) { throw new RuntimeException("jar沒有找到!"); throw new RuntimeException("jar沒有找到!"+jarPath); } else { try { URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{jarFile.toURI().toURL()}); log.info("成功加载jar包:"+ jarFile.getAbsolutePath()); // 设置classloader的patent为null,限制使用双亲委派,防止其他classloader找到class,导致dll加载到其他classloader URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{jarFile.toURI().toURL()},null,null); log.info("成功加载jar包:" + jarFile.getAbsolutePath()); return urlClassLoader; } catch (Exception e) { throw new RuntimeException("加载jar异常",e); throw new RuntimeException("加载jar异常", e); } } } public static synchronized void uploadJar(URLClassLoader urlClassLoader) { public static synchronized void unloadJar(URLClassLoader urlClassLoader) { try { urlClassLoader.close(); log.info("成功卸载jar包。"); } catch (Exception e) { throw new RuntimeException("卸载jar异常",e); throw new RuntimeException("卸载jar异常", e); } } public static synchronized void addClassLoaderCache(String projectId, URLClassLoader urlClassLoader) { classLoaderCache.put(projectId, urlClassLoader); } public static synchronized URLClassLoader getClassLoader(String projectId) { return classLoaderCache.get(projectId); } public static synchronized void removeClassLoaderCache(String projectId) { if (classLoaderCache.containsKey(projectId)) { URLClassLoader urlClassLoader = classLoaderCache.get(projectId); unloadDll(urlClassLoader); unloadJar(urlClassLoader); classLoaderCache.remove(projectId); } } public static void removeOldFile(String bakPath,String projectId) { File dir = new File(bakPath); if (dir.exists() && dir.isDirectory()) { File[] files = dir.listFiles(); if (null != files && files.length > 0) { for (File file : files) { if (file.getName().startsWith(projectId)) { file.delete(); } } } } } /** * @description: 项目启动加载已发布的dll和jar * @author: dzd * @date: 2024/10/10 11:58 **/ public static void loadProjectPublish(String bakPath) { File dir = new File(bakPath); if (dir.exists() && dir.isDirectory()) { File[] files = dir.listFiles(); if (null != files && files.length > 0) { for (File file : files) { String fileName = file.getName(); if (fileName.endsWith(".jar")) { String[] split = fileName.substring(0,fileName.length() - 4).split(MdkConstant.SPLIT); String projectId = split[0]; String historyId = split[1]; String jarFilePath = bakPath + File.separator + projectId + MdkConstant.SPLIT + historyId + ".jar"; String dllFilePath = bakPath + File.separator + projectId + MdkConstant.SPLIT + historyId + ".dll"; if (FileUtil.exist(jarFilePath) && FileUtil.exist(dllFilePath)) { URLClassLoader urlClassLoader = null; try { // 加载新的jar urlClassLoader = loadJar(jarFilePath); } catch (Exception e) { throw new RuntimeException("加载jar异常",e); } try { // 加载新的dll loadDll(urlClassLoader.loadClass("iail.mdk.model.common.Environment"),dllFilePath); } catch (Exception e) { unloadJar(urlClassLoader); throw new RuntimeException("加载dll异常",e); } // 都加载成功后加入缓存 addClassLoaderCache(projectId,urlClassLoader); } } } } } } } iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mpk/controller/admin/MdkController.java
@@ -104,8 +104,8 @@ return error(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),"运行异常"); } finally { if (classLoader != null) { DllUtils.uploadDll(classLoader); DllUtils.uploadJar(classLoader); DllUtils.unloadDll(classLoader); DllUtils.unloadJar(classLoader); } System.gc(); } iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mpk/controller/admin/MpkFileController.java
@@ -125,8 +125,13 @@ @PostMapping("/upload") @Operation(summary = "python文件上传") public CommonResult<Map<String,String>> importExcel(@RequestParam("file") MultipartFile file) throws Exception { public CommonResult<Map<String,String>> upload(@RequestParam("file") MultipartFile file) throws Exception { Map<String,String> result = mpkFileService.savePyFile(file); return success(result); } @PostMapping("/publish") public CommonResult<String> publish(@RequestBody Map<String, Object> params) { return mpkFileService.publish(params); } } iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mpk/service/MpkFileService.java
@@ -1,6 +1,7 @@ package com.iailab.module.model.mpk.service; import com.iailab.framework.common.page.PageData; import com.iailab.framework.common.pojo.CommonResult; import com.iailab.framework.common.service.BaseService; import com.iailab.module.model.mpk.dto.MpkFileDTO; import com.iailab.module.model.mpk.entity.MpkFileEntity; @@ -34,4 +35,6 @@ byte[] packageModel(List<String> ids,String projectId,String projectName,String fileName,String log,String version) throws IOException, InterruptedException; Map<String,String> savePyFile(MultipartFile file) throws IOException; CommonResult<String> publish(Map<String, Object> params); } iailab-module-model/iailab-module-model-biz/src/main/java/com/iailab/module/model/mpk/service/impl/MpkFileServiceImpl.java
@@ -8,12 +8,14 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.iailab.framework.common.page.PageData; import com.iailab.framework.common.pojo.CommonResult; import com.iailab.framework.common.service.impl.BaseServiceImpl; import com.iailab.framework.common.util.date.DateUtils; import com.iailab.framework.common.util.object.ConvertUtils; import com.iailab.framework.security.core.util.SecurityFrameworkUtils; import com.iailab.module.infra.api.config.ConfigApi; import com.iailab.module.model.mpk.common.MdkConstant; import com.iailab.module.model.mpk.common.utils.DllUtils; import com.iailab.module.model.mpk.common.utils.GenUtils; import com.iailab.module.model.mpk.dao.MpkFileDao; import com.iailab.module.model.mpk.dto.GeneratorCodeHistoryDTO; @@ -36,6 +38,7 @@ import org.springframework.web.multipart.MultipartFile; import java.io.*; import java.net.URLClassLoader; import java.nio.file.Files; import java.util.*; import java.util.stream.Collectors; @@ -368,6 +371,16 @@ //生成dll文件 String dllSavePath = dirPath.getAbsolutePath() + File.separator + MdkConstant.LIBS + File.separator + "IAIL.MDK.Mid.Jni.dll"; createDllFile(dirPath.getAbsolutePath(),cppFilePaths,dllSavePath); // 打包历史id String historyId = UUID.randomUUID().toString(); //备份dll,发布时使用 File dllFile = new File(dllSavePath); if (dllFile.exists()) { File dllBakFile = new File(mpkBakFilePath + File.separator + projectId + MdkConstant.SPLIT + historyId + ".dll"); FileUtil.copy(dllFile, dllBakFile, true); }else { log.error("dll文件不存在,无法备份。" + dllSavePath); } //utils + env java文件 File utilsJavaFile = new File(dirPath.getAbsolutePath() + File.separator + "IAILMDK" + File.separator + "iail" + File.separator + "mdk" + File.separator + "model" + File.separator + "utils" + File.separator + "AlgsUtils.java"); @@ -383,10 +396,18 @@ // 删除java源文件 deleteJavaFile(javaFilePaths); // 打jar包 pkgJar(dirPath.getAbsolutePath()); String jarSavePath = pkgJar(dirPath.getAbsolutePath()); //备份jar包,发布时使用 File jarFile = new File(jarSavePath); if (jarFile.exists()) { File jarBakFile = new File(mpkBakFilePath + File.separator + projectId + MdkConstant.SPLIT + historyId + ".jar"); FileUtil.copy(jarFile, jarBakFile, true); }else { log.error("jar文件不存在,无法备份。" + jarSavePath); } // 本次更新日志 ProjectPackageHistoryDTO dto = new ProjectPackageHistoryDTO(); String historyId = UUID.randomUUID().toString(); dto.setId(historyId); dto.setProjectId(projectId); dto.setFileName(zipFileName); @@ -470,6 +491,57 @@ return result; } @Override public CommonResult<String> publish(Map<String, Object> params) { String historyId = (String) params.get("historyId"); String projectId = (String) params.get("projectId"); // 判断新的dll和jar文件是否存在 String jarFileBakPath = mpkBakFilePath + File.separator + projectId + MdkConstant.SPLIT + historyId + ".jar"; String dllFileBakPath = mpkBakFilePath + File.separator + projectId + MdkConstant.SPLIT + historyId + ".dll"; if (!FileUtil.exist(jarFileBakPath)) { throw new RuntimeException("jar文件不存在," + jarFileBakPath); } if (!FileUtil.exist(dllFileBakPath)) { throw new RuntimeException("dll文件不存在" + dllFileBakPath); } try { // 卸载之前的dll和jar DllUtils.removeClassLoaderCache(projectId); // 删除之前的dll和jar备份文件 DllUtils.removeOldFile(mpkBakFilePath + File.separator + MdkConstant.PROJECT_PUBLISH,projectId); } catch (Exception e) { throw new RuntimeException("卸载之前的dll和jar异常",e); } // 备份新的dll和jar String jarFilePath = mpkBakFilePath + File.separator + MdkConstant.PROJECT_PUBLISH + File.separator + projectId + MdkConstant.SPLIT + historyId + ".jar"; String dllFilePath = mpkBakFilePath + File.separator + MdkConstant.PROJECT_PUBLISH + File.separator + projectId + MdkConstant.SPLIT + historyId + ".dll"; FileUtil.copy(jarFileBakPath,jarFilePath,true); FileUtil.copy(dllFileBakPath,dllFilePath,true); URLClassLoader urlClassLoader = null; try { // 加载新的jar urlClassLoader = DllUtils.loadJar(jarFilePath); } catch (Exception e) { throw new RuntimeException("加载新的jar异常",e); } try { // 加载新的dll DllUtils.loadDll(urlClassLoader.loadClass("iail.mdk.model.common.Environment"),dllFilePath); } catch (Exception e) { DllUtils.unloadJar(urlClassLoader); throw new RuntimeException("加载新的dll异常",e); } // 都加载成功后加入缓存 DllUtils.addClassLoaderCache(projectId,urlClassLoader); return CommonResult.success(); } private void createLog(String projectId, String projectName, String dirPath, ProjectPackageHistoryDTO dto, String version) throws IOException { Map<String, Object> map = new HashMap<>(); map.put("projectId", projectId);