From faeba248340ecdb4755c37060e1c582856be2d86 Mon Sep 17 00:00:00 2001 From: wxg0103 <727495428@qq.com> Date: Thu, 5 Jan 2023 17:45:21 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E7=B3=BB=E7=BB=9F=E8=AE=BE=E7=BD=AE):=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=8E=86=E5=8F=B2jar=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E7=9A=84=E7=BC=BA=E9=99=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://github.com/metersphere/metersphere/issues/21122 --- .../controller/PluginController.java | 13 +--- .../io/metersphere/service/PluginService.java | 12 +-- .../io/metersphere/listener/InitListener.java | 6 ++ .../io/metersphere/service/PluginService.java | 73 ++++++++++++++++++- .../business/system/plugin/PluginConfig.vue | 6 +- 5 files changed, 89 insertions(+), 21 deletions(-) diff --git a/api-test/backend/src/main/java/io/metersphere/controller/PluginController.java b/api-test/backend/src/main/java/io/metersphere/controller/PluginController.java index ec534d9cdb..abde784c13 100644 --- a/api-test/backend/src/main/java/io/metersphere/controller/PluginController.java +++ b/api-test/backend/src/main/java/io/metersphere/controller/PluginController.java @@ -2,14 +2,9 @@ package io.metersphere.controller; import io.metersphere.api.dto.plugin.PluginDTO; import io.metersphere.api.dto.plugin.PluginRequest; -import io.metersphere.service.PluginService; import io.metersphere.base.domain.Plugin; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -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 io.metersphere.service.PluginService; +import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.util.List; @@ -21,8 +16,8 @@ public class PluginController { private PluginService pluginService; @GetMapping("/list") - public List list(String name) { - return pluginService.list(name); + public List list() { + return pluginService.getPluginList(); } @GetMapping("/get/{id}") diff --git a/api-test/backend/src/main/java/io/metersphere/service/PluginService.java b/api-test/backend/src/main/java/io/metersphere/service/PluginService.java index cc05a4f12f..b07f61787a 100644 --- a/api-test/backend/src/main/java/io/metersphere/service/PluginService.java +++ b/api-test/backend/src/main/java/io/metersphere/service/PluginService.java @@ -88,7 +88,7 @@ public class PluginService { public void loadPlugins() { try { PluginExample example = new PluginExample(); - example.createCriteria().andScenarioEqualTo(PluginScenario.api.name()); + example.createCriteria().andScenarioNotEqualTo(PluginScenario.platform.name()); List plugins = pluginMapper.selectByExample(example); if (CollectionUtils.isNotEmpty(plugins)) { plugins = plugins.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() @@ -109,15 +109,11 @@ public class PluginService { } } - public List list(String name) { + public List getPluginList() { List lists = new LinkedList<>(); try { PluginExample example = new PluginExample(); - example.createCriteria().andScenarioEqualTo(PluginScenario.api.name()); - if (StringUtils.isNotBlank(name)) { - name = "%" + name + "%"; - example.createCriteria().andNameLike(name); - } + example.createCriteria().andScenarioNotEqualTo(PluginScenario.platform.name()); List plugins = pluginMapper.selectByExample(example); Map pluginMap = new HashMap<>(); if (CollectionUtils.isNotEmpty(plugins)) { @@ -183,7 +179,7 @@ public class PluginService { public List list() { PluginExample example = new PluginExample(); - example.createCriteria().andScenarioEqualTo(PluginScenario.api.name()); + example.createCriteria().andScenarioNotEqualTo(PluginScenario.platform.name()); List plugins = pluginMapper.selectByExample(example); return plugins; } diff --git a/system-setting/backend/src/main/java/io/metersphere/listener/InitListener.java b/system-setting/backend/src/main/java/io/metersphere/listener/InitListener.java index 1b01cf1f14..c596c741d0 100644 --- a/system-setting/backend/src/main/java/io/metersphere/listener/InitListener.java +++ b/system-setting/backend/src/main/java/io/metersphere/listener/InitListener.java @@ -2,6 +2,7 @@ package io.metersphere.listener; import io.metersphere.commons.utils.LogUtil; import io.metersphere.service.PlatformPluginService; +import io.metersphere.service.PluginService; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component; @@ -13,10 +14,15 @@ public class InitListener implements ApplicationRunner { @Resource private PlatformPluginService platformPluginService; + @Resource + private PluginService pluginService; @Override public void run(ApplicationArguments applicationArguments) { LogUtil.info("================= SYSTEM-SETTING 应用启动 ================="); + pluginService.loadPlugins(); platformPluginService.loadPlatFormPlugins(); } + + } diff --git a/system-setting/backend/src/main/java/io/metersphere/service/PluginService.java b/system-setting/backend/src/main/java/io/metersphere/service/PluginService.java index 94619b768b..51b6911f61 100644 --- a/system-setting/backend/src/main/java/io/metersphere/service/PluginService.java +++ b/system-setting/backend/src/main/java/io/metersphere/service/PluginService.java @@ -20,13 +20,18 @@ import io.metersphere.metadata.vo.FileRequest; import io.metersphere.request.PluginDTO; import io.metersphere.request.PluginRequest; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Resource; +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; import java.util.*; +import java.util.stream.Collectors; @Service @Transactional(rollbackFor = Exception.class) @@ -63,7 +68,7 @@ public class PluginService { plugins.forEach(item -> { PluginDTO dto = new PluginDTO(); BeanUtils.copyBean(dto, item); - if (StringUtils.equals(PluginScenario.api.name(), item.getScenario())) { + if (!StringUtils.equals(PluginScenario.platform.name(), item.getScenario())) { // api 插件调用 if (!pluginMap.containsKey(item.getPluginId())) { dto.setLicense(apiPluginService.isXpack(item)); @@ -154,6 +159,72 @@ public class PluginService { } } + public void loadPlugins() { + try { + PluginExample example = new PluginExample(); + example.createCriteria().andScenarioNotEqualTo(PluginScenario.platform.name()); + List plugins = pluginMapper.selectByExample(example); + if (CollectionUtils.isNotEmpty(plugins)) { + plugins = plugins.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() + -> new TreeSet<>(Comparator.comparing(Plugin::getPluginId))), ArrayList::new)); + if (CollectionUtils.isNotEmpty(plugins)) { + plugins.forEach(item -> { + boolean isLoad = this.loadJar(item.getSourcePath(), item.getPluginId()); + if (!isLoad) { + PluginExample pluginExample = new PluginExample(); + pluginExample.createCriteria().andPluginIdEqualTo(item.getPluginId()); + pluginMapper.deleteByExample(pluginExample); + } + }); + } + } + } catch (Exception e) { + LogUtil.error(e); + } + } + + private boolean loadJar(String jarPath, String pluginId) { + try { + ClassLoader classLoader = ClassLoader.getSystemClassLoader(); + try { + File file = new File(jarPath); + if (!file.exists()) { + // 从MinIO下载 + if (!this.downPluginJar(jarPath, pluginId, jarPath)) { + return false; + } + } + if (!file.exists()) { + return false; + } + Method method = classLoader.getClass().getDeclaredMethod("addURL", URL.class); + method.setAccessible(true); + method.invoke(classLoader, file.toURI().toURL()); + } catch (NoSuchMethodException e) { + Method method = classLoader.getClass() + .getDeclaredMethod("appendToClassPathForInstrumentation", String.class); + method.setAccessible(true); + method.invoke(classLoader, jarPath); + } + return true; + } catch (Exception e) { + LogUtil.error(e); + } + return false; + } + + private boolean downPluginJar(String path, String pluginId, String jarPath) { + FileRequest request = new FileRequest(); + request.setProjectId(StringUtils.join(FileUtils.BODY_FILE_DIR, "/plugin", pluginId)); + request.setFileName(pluginId); + request.setStorage(StorageConstants.MINIO.name()); + byte[] bytes = fileManagerService.downloadFile(request); + if (ArrayUtils.isNotEmpty(bytes)) { + FileUtils.createFile(path, bytes); + } + return new File(jarPath).exists(); + } + public String getLogDetails(String id) { PluginExample example = new PluginExample(); example.createCriteria().andPluginIdEqualTo(id); diff --git a/system-setting/frontend/src/business/system/plugin/PluginConfig.vue b/system-setting/frontend/src/business/system/plugin/PluginConfig.vue index 55b7db84f2..93425a7b84 100644 --- a/system-setting/frontend/src/business/system/plugin/PluginConfig.vue +++ b/system-setting/frontend/src/business/system/plugin/PluginConfig.vue @@ -107,7 +107,7 @@ export default { this.format(res.data); this.dataMap.forEach((values, key) => { let item = values[0]; - if (item.scenario === 'api') { + if (item.scenario !== 'platform') { let obj = {}; Object.assign(obj, item); obj.id = key; @@ -141,9 +141,9 @@ export default { this.$refs.scriptView.open(row.scriptId); }, handleDelete(row) { - let tip = row.scenario === 'api' ? this.$t('api_test.jar_config.delete_tip') : this.$t('api_test.jar_config.delete_confirm'); + let tip = row.scenario !== 'platform' ? this.$t('api_test.jar_config.delete_tip') : this.$t('api_test.jar_config.delete_confirm'); operationConfirm(this, tip, () => { - this.loading = delPluginById(row.scenario, row.id).then(() => { + this.loading = delPluginById(row.scenario || 'api', row.id).then(() => { this.$success(this.$t('commons.delete_success')); this.initPlugins(); });