From 91af429f450354898149393c551c1dbaa9bfed14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=A3=E5=9C=A3=E5=8D=8E?= <752718920@qq.com> Date: Fri, 6 Mar 2020 11:11:53 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=8F=92=E4=BB=B6=E6=A8=A1?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 5 + .../jsh/erp/config/ExamplePluginListener.java | 41 ++++ .../com/jsh/erp/config/PluginBeanConfig.java | 30 +++ .../jsh/erp/config/PluginConfiguration.java | 130 ++++++++++++ .../com/jsh/erp/config/PluginListener.java | 28 +++ .../jsh/erp/controller/PluginController.java | 192 ++++++++++++++++++ .../java/com/jsh/erp/plugin/CommonParam.java | 37 ++++ .../java/com/jsh/erp/plugin/CommonReturn.java | 37 ++++ .../java/com/jsh/erp/plugin/ConsoleName.java | 16 ++ .../jsh/erp/plugin/ConsoleNameFactory.java | 19 ++ .../jsh/erp/plugin/DefaultConsoleName.java | 17 ++ src/main/java/com/jsh/erp/plugin/Hello.java | 16 ++ src/main/resources/application.properties | 6 +- 13 files changed, 573 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/jsh/erp/config/ExamplePluginListener.java create mode 100644 src/main/java/com/jsh/erp/config/PluginBeanConfig.java create mode 100644 src/main/java/com/jsh/erp/config/PluginConfiguration.java create mode 100644 src/main/java/com/jsh/erp/config/PluginListener.java create mode 100644 src/main/java/com/jsh/erp/controller/PluginController.java create mode 100644 src/main/java/com/jsh/erp/plugin/CommonParam.java create mode 100644 src/main/java/com/jsh/erp/plugin/CommonReturn.java create mode 100644 src/main/java/com/jsh/erp/plugin/ConsoleName.java create mode 100644 src/main/java/com/jsh/erp/plugin/ConsoleNameFactory.java create mode 100644 src/main/java/com/jsh/erp/plugin/DefaultConsoleName.java create mode 100644 src/main/java/com/jsh/erp/plugin/Hello.java diff --git a/pom.xml b/pom.xml index b1022520..dbeded6b 100644 --- a/pom.xml +++ b/pom.xml @@ -23,6 +23,11 @@ + + com.gitee.starblues + springboot-plugin-framework + 2.2.1-RELEASE + org.mybatis.spring.boot mybatis-spring-boot-starter diff --git a/src/main/java/com/jsh/erp/config/ExamplePluginListener.java b/src/main/java/com/jsh/erp/config/ExamplePluginListener.java new file mode 100644 index 00000000..8825f8b6 --- /dev/null +++ b/src/main/java/com/jsh/erp/config/ExamplePluginListener.java @@ -0,0 +1,41 @@ +package com.jsh.erp.config; + +import com.gitee.starblues.integration.application.PluginApplication; +import com.gitee.starblues.integration.listener.PluginListener; +import com.gitee.starblues.integration.user.PluginUser; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * 插件监听者 + * + * @author jishenghua + * @version 1.0 + */ +public class ExamplePluginListener implements PluginListener { + + private final Logger logger = LoggerFactory.getLogger(this.getClass()); + + private final PluginUser pluginUser; + + public ExamplePluginListener(PluginApplication pluginApplication){ + this.pluginUser = pluginApplication.getPluginUser(); + } + + + @Override + public void registry(String pluginId) { + logger.info("Listener: registry pluginId {}", pluginId); + } + + @Override + public void unRegistry(String pluginId) { + logger.info("Listener: unRegistry pluginId {}", pluginId); + } + + @Override + public void failure(String pluginId, Throwable throwable) { + + } +} diff --git a/src/main/java/com/jsh/erp/config/PluginBeanConfig.java b/src/main/java/com/jsh/erp/config/PluginBeanConfig.java new file mode 100644 index 00000000..946bdc34 --- /dev/null +++ b/src/main/java/com/jsh/erp/config/PluginBeanConfig.java @@ -0,0 +1,30 @@ +package com.jsh.erp.config; + +import com.gitee.starblues.integration.application.AutoPluginApplication; +import com.gitee.starblues.integration.application.PluginApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * 插件集成配置 + * + * @author jishenghua + * @version 1.0 + */ +@Configuration +public class PluginBeanConfig { + + + /** + * 定义插件应用。使用可以注入它操作插件。 + * @return PluginApplication + */ + @Bean + public PluginApplication pluginApplication(PluginListener pluginListener){ + AutoPluginApplication autoPluginApplication = new AutoPluginApplication(); + autoPluginApplication.setPluginInitializerListener(pluginListener); + autoPluginApplication.addListener(ExamplePluginListener.class); + return autoPluginApplication; + } + +} diff --git a/src/main/java/com/jsh/erp/config/PluginConfiguration.java b/src/main/java/com/jsh/erp/config/PluginConfiguration.java new file mode 100644 index 00000000..013b3f98 --- /dev/null +++ b/src/main/java/com/jsh/erp/config/PluginConfiguration.java @@ -0,0 +1,130 @@ +package com.jsh.erp.config; + +import com.gitee.starblues.integration.DefaultIntegrationConfiguration; +import org.pf4j.RuntimeMode; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + + +/** + * 插件集成配置 + * + * @author jishenghua + * @version 1.0 + */ +@Component +@ConfigurationProperties(prefix = "plugin") +public class PluginConfiguration extends DefaultIntegrationConfiguration { + + /** + * 运行模式 + * 开发环境: development、dev + * 生产/部署 环境: deployment、prod + */ + @Value("${runMode:dev}") + private String runMode; + + /** + * 插件的路径 + */ + @Value("${pluginPath:plugins}") + private String pluginPath; + + /** + * 插件文件的路径 + */ + @Value("${pluginConfigFilePath:pluginConfigs}") + private String pluginConfigFilePath; + + + @Override + public RuntimeMode environment() { + return RuntimeMode.byName(runMode); + } + + @Override + public String pluginPath() { + return pluginPath; + } + + @Override + public String pluginConfigFilePath() { + return pluginConfigFilePath; + } + + /** + * 重写上传插件包的临时存储路径。只适用于生产环境 + * @return String + */ + @Override + public String uploadTempPath() { + return "temp"; + } + + /** + * 重写插件备份路径。只适用于生产环境 + * @return String + */ + @Override + public String backupPath() { + return "backupPlugin"; + } + + /** + * 重写插件RestController请求的路径前缀 + * @return String + */ + @Override + public String pluginRestControllerPathPrefix() { + return "/api/plugins"; + } + + /** + * 重写是否启用插件id作为RestController请求的路径前缀。 + * 启动则插件id会作为二级路径前缀。即: /api/plugins/pluginId/** + * @return String + */ + @Override + public boolean enablePluginIdRestControllerPathPrefix() { + return true; + } + + + + + + public String getRunMode() { + return runMode; + } + + public void setRunMode(String runMode) { + this.runMode = runMode; + } + + + public String getPluginPath() { + return pluginPath; + } + + public void setPluginPath(String pluginPath) { + this.pluginPath = pluginPath; + } + + public String getPluginConfigFilePath() { + return pluginConfigFilePath; + } + + public void setPluginConfigFilePath(String pluginConfigFilePath) { + this.pluginConfigFilePath = pluginConfigFilePath; + } + + @Override + public String toString() { + return "PluginArgConfiguration{" + + "runMode='" + runMode + '\'' + + ", pluginPath='" + pluginPath + '\'' + + ", pluginConfigFilePath='" + pluginConfigFilePath + '\'' + + '}'; + } +} diff --git a/src/main/java/com/jsh/erp/config/PluginListener.java b/src/main/java/com/jsh/erp/config/PluginListener.java new file mode 100644 index 00000000..44ebe1df --- /dev/null +++ b/src/main/java/com/jsh/erp/config/PluginListener.java @@ -0,0 +1,28 @@ +package com.jsh.erp.config; + +import com.gitee.starblues.integration.listener.PluginInitializerListener; +import org.springframework.stereotype.Component; + +/** + * 插件监听者 + * + * @author jishenghua + * @version 1.0 + */ +@Component +public class PluginListener implements PluginInitializerListener { + @Override + public void before() { + System.out.println("before"); + } + + @Override + public void complete() { + System.out.println("complete"); + } + + @Override + public void failure(Throwable throwable) { + System.out.println("failure:"+throwable.getMessage()); + } +} diff --git a/src/main/java/com/jsh/erp/controller/PluginController.java b/src/main/java/com/jsh/erp/controller/PluginController.java new file mode 100644 index 00000000..aae54f44 --- /dev/null +++ b/src/main/java/com/jsh/erp/controller/PluginController.java @@ -0,0 +1,192 @@ +package com.jsh.erp.controller; + +import com.gitee.starblues.integration.application.PluginApplication; +import com.gitee.starblues.integration.operator.PluginOperator; +import com.gitee.starblues.integration.operator.module.PluginInfo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.nio.file.Paths; +import java.util.List; +import java.util.Set; + +/** + * 插件jar 包测试功能 + * @author jishenghua + * @version 1.0 + */ +@RestController +@RequestMapping("/plugin") +public class PluginController { + + + private final PluginOperator pluginOperator; + + @Autowired + public PluginController(PluginApplication pluginApplication) { + this.pluginOperator = pluginApplication.getPluginOperator(); + } + /** + * 获取插件信息 + * @return 返回插件信息 + */ + @GetMapping + public List getPluginInfo(){ + return pluginOperator.getPluginInfo(); + } + + /** + * 获取插件jar文件名 + * @return 获取插件文件名。只在生产环境显示 + */ + @GetMapping("/files") + public Set getPluginFilePaths(){ + try { + return pluginOperator.getPluginFilePaths(); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + + /** + * 根据插件id停止插件 + * @param id 插件id + * @return 返回操作结果 + */ + @PostMapping("/stop/{id}") + public String stop(@PathVariable("id") String id){ + try { + if(pluginOperator.stop(id)){ + return "plugin '" + id +"' stop success"; + } else { + return "plugin '" + id +"' stop failure"; + } + } catch (Exception e) { + e.printStackTrace(); + return "plugin '" + id +"' stop failure. " + e.getMessage(); + } + } + + /** + * 根据插件id启动插件 + * @param id 插件id + * @return 返回操作结果 + */ + @PostMapping("/start/{id}") + public String start(@PathVariable("id") String id){ + try { + if(pluginOperator.start(id)){ + return "plugin '" + id +"' start success"; + } else { + return "plugin '" + id +"' start failure"; + } + } catch (Exception e) { + e.printStackTrace(); + return "plugin '" + id +"' start failure. " + e.getMessage(); + } + } + + + /** + * 根据插件id卸载插件 + * @param id 插件id + * @return 返回操作结果 + */ + @PostMapping("/uninstall/{id}") + public String uninstall(@PathVariable("id") String id){ + try { + if(pluginOperator.uninstall(id, true)){ + return "plugin '" + id +"' uninstall success"; + } else { + return "plugin '" + id +"' uninstall failure"; + } + } catch (Exception e) { + e.printStackTrace(); + return "plugin '" + id +"' uninstall failure. " + e.getMessage(); + } + } + + + /** + * 根据插件路径安装插件。该插件jar必须在服务器上存在。注意: 该操作只适用于生产环境 + * @param path 插件路径名称 + * @return 操作结果 + */ + @PostMapping("/installByPath") + public String install(@RequestParam("path") String path){ + try { + if(pluginOperator.install(Paths.get(path))){ + return "installByPath success"; + } else { + return "installByPath failure"; + } + } catch (Exception e) { + e.printStackTrace(); + return "installByPath failure : " + e.getMessage(); + } + } + + + /** + * 上传并安装插件。注意: 该操作只适用于生产环境 + * @param multipartFile 上传文件 multipartFile + * @return 操作结果 + */ + @PostMapping("/uploadInstallPluginJar") + public String install(@RequestParam("jarFile") MultipartFile multipartFile){ + try { + if(pluginOperator.uploadPluginAndStart(multipartFile)){ + return "install success"; + } else { + return "install failure"; + } + } catch (Exception e) { + e.printStackTrace(); + return "install failure : " + e.getMessage(); + } + } + + + /** + * 上传插件的配置文件。注意: 该操作只适用于生产环境 + * @param multipartFile 上传文件 multipartFile + * @return 操作结果 + */ + @PostMapping("/uploadPluginConfigFile") + public String uploadConfig(@RequestParam("configFile") MultipartFile multipartFile){ + try { + if(pluginOperator.uploadConfigFile(multipartFile)){ + return "uploadConfig success"; + } else { + return "uploadConfig failure"; + } + } catch (Exception e) { + e.printStackTrace(); + return "uploadConfig failure : " + e.getMessage(); + } + } + + + /** + * 备份插件。注意: 该操作只适用于生产环境 + * @param pluginId 插件id + * @return 操作结果 + */ + @PostMapping("/back/{pluginId}") + public String backupPlugin(@PathVariable("pluginId") String pluginId){ + try { + if(pluginOperator.backupPlugin(pluginId, "testBack")){ + return "backupPlugin success"; + } else { + return "backupPlugin failure"; + } + } catch (Exception e) { + e.printStackTrace(); + return "backupPlugin failure : " + e.getMessage(); + } + } + +} diff --git a/src/main/java/com/jsh/erp/plugin/CommonParam.java b/src/main/java/com/jsh/erp/plugin/CommonParam.java new file mode 100644 index 00000000..9fb47a9e --- /dev/null +++ b/src/main/java/com/jsh/erp/plugin/CommonParam.java @@ -0,0 +1,37 @@ +package com.jsh.erp.plugin; + +/** + * 插件之间互相调用的类 + * + * @author jishenghua + * @version 1.0 + */ +public class CommonParam { + + private String name; + private Integer age; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } + + @Override + public String toString() { + return "CommonParam{" + + "name='" + name + '\'' + + ", age=" + age + + '}'; + } +} diff --git a/src/main/java/com/jsh/erp/plugin/CommonReturn.java b/src/main/java/com/jsh/erp/plugin/CommonReturn.java new file mode 100644 index 00000000..06d4065c --- /dev/null +++ b/src/main/java/com/jsh/erp/plugin/CommonReturn.java @@ -0,0 +1,37 @@ +package com.jsh.erp.plugin; + +/** + * 插件之间互相调用的类 + * + * @author jishenghua + * @version 1.0 + */ +public class CommonReturn { + + private String returnName; + private Boolean result; + + public String getReturnName() { + return returnName; + } + + public void setReturnName(String returnName) { + this.returnName = returnName; + } + + public Boolean getResult() { + return result; + } + + public void setResult(Boolean result) { + this.result = result; + } + + @Override + public String toString() { + return "CommonReturn{" + + "returnName='" + returnName + '\'' + + ", result=" + result + + '}'; + } +} diff --git a/src/main/java/com/jsh/erp/plugin/ConsoleName.java b/src/main/java/com/jsh/erp/plugin/ConsoleName.java new file mode 100644 index 00000000..502a9d50 --- /dev/null +++ b/src/main/java/com/jsh/erp/plugin/ConsoleName.java @@ -0,0 +1,16 @@ +package com.jsh.erp.plugin; + +/** + * 在主程序定义一个接口。插件中可以实现该接口 + * @author jishenghua + * @version 1.0 + */ +public interface ConsoleName { + + /** + * 返回名称 + * @return 输出名称 + */ + String name(); + +} diff --git a/src/main/java/com/jsh/erp/plugin/ConsoleNameFactory.java b/src/main/java/com/jsh/erp/plugin/ConsoleNameFactory.java new file mode 100644 index 00000000..0a12fb24 --- /dev/null +++ b/src/main/java/com/jsh/erp/plugin/ConsoleNameFactory.java @@ -0,0 +1,19 @@ +package com.jsh.erp.plugin; + +import com.gitee.starblues.integration.application.PluginApplication; +import com.gitee.starblues.integration.refresh.AbstractPluginSpringBeanRefresh; +import org.springframework.stereotype.Component; + +/** + * 输出名称工厂 + * + * @author jishenghua + * @version 1.0 + */ +@Component +public class ConsoleNameFactory extends AbstractPluginSpringBeanRefresh { + public ConsoleNameFactory(PluginApplication pluginApplication) { + super(pluginApplication); + pluginApplication.addListener(this); + } +} diff --git a/src/main/java/com/jsh/erp/plugin/DefaultConsoleName.java b/src/main/java/com/jsh/erp/plugin/DefaultConsoleName.java new file mode 100644 index 00000000..4753527a --- /dev/null +++ b/src/main/java/com/jsh/erp/plugin/DefaultConsoleName.java @@ -0,0 +1,17 @@ +package com.jsh.erp.plugin; + +import org.springframework.stereotype.Component; + +/** + * 默认的主程序输入名称接口实现 + * + * @author jishenghua + * @version 1.0 + */ +@Component +public class DefaultConsoleName implements ConsoleName{ + @Override + public String name() { + return "My name is Main-start-DefaultConsoleName"; + } +} diff --git a/src/main/java/com/jsh/erp/plugin/Hello.java b/src/main/java/com/jsh/erp/plugin/Hello.java new file mode 100644 index 00000000..2aa69e9d --- /dev/null +++ b/src/main/java/com/jsh/erp/plugin/Hello.java @@ -0,0 +1,16 @@ +package com.jsh.erp.plugin; + +import org.pf4j.ExtensionPoint; + +/** + * 测试非Spring管理的bean接口 + * 实现类需要使用 @Extension 注解 + * + * @author jishenghua + * @version 1.0 + */ +public interface Hello extends ExtensionPoint { + + String getName(); + +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index b5f6ef99..565d5c96 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -15,4 +15,8 @@ mybatis.mapper-locations=classpath:./mapper_xml/*.xml #mybatis-plus配置 mybatis-plus.mapper-locations=classpath:./mapper_xml/*.xml #租户对应的角色id -manage.roleId=10 \ No newline at end of file +manage.roleId=10 +#插件配置 +plugin.runMode=prod +plugin.pluginPath=plugins +plugin.pluginConfigFilePath=pluginConfig \ No newline at end of file