增加插件模式

This commit is contained in:
季圣华
2020-03-06 11:11:53 +08:00
parent f16c1844b5
commit 91af429f45
13 changed files with 573 additions and 1 deletions

View File

@@ -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) {
}
}

View File

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

View File

@@ -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 + '\'' +
'}';
}
}

View File

@@ -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());
}
}

View File

@@ -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<PluginInfo> getPluginInfo(){
return pluginOperator.getPluginInfo();
}
/**
* 获取插件jar文件名
* @return 获取插件文件名。只在生产环境显示
*/
@GetMapping("/files")
public Set<String> 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();
}
}
}

View File

@@ -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 +
'}';
}
}

View File

@@ -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 +
'}';
}
}

View File

@@ -0,0 +1,16 @@
package com.jsh.erp.plugin;
/**
* 在主程序定义一个接口。插件中可以实现该接口
* @author jishenghua
* @version 1.0
*/
public interface ConsoleName {
/**
* 返回名称
* @return 输出名称
*/
String name();
}

View File

@@ -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<ConsoleName> {
public ConsoleNameFactory(PluginApplication pluginApplication) {
super(pluginApplication);
pluginApplication.addListener(this);
}
}

View File

@@ -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";
}
}

View File

@@ -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();
}