springboot插件式开发框架

介绍

该框架主要是集成于springboot项目,用于开发插件式应用的集成框架。

核心功能

插件配置式插拔于springboot项目。

在springboot上可以进行插件式开发, 扩展性极强, 可以针对不同项目开发不同插件, 进行不同插件jar包的部署。

可通过配置文件指定要启用或者禁用插件。

支持上传插件和插件配置文件到服务器, 并且无需重启主程序, 动态部署插件、更新插件。

支持查看插件运行状态, 查看插件安装位置。

无需重启主程序, 动态的安装插件、卸载插件、启用插件、停止插件、备份插件、删除插件。

在插件应用模块上可以使用Spring注解定义组件, 进行依赖注入。

支持在插件中开发Rest接口。

支持在插件中单独定义持久层访问等需求。

可以遵循主程序提供的插件接口开发任意扩展功能。

插件可以自定义配置文件。目前只支持yml文件。

支持自定义扩展开发接口, 使用者可以在预留接口上扩展额外功能。

利用扩展机制, 定制了SpringBoot-Mybatis扩展包。使用该扩展包, 使用者可以在插件中自定义Mapper接口、Mapper xml 以及对应的实体bean。

运行环境

jdk1.8+

apache maven 3.6

mavne 仓库地址

com.gitee.starblues " springboot-plugin-framework

快速入门

新建项目。

Maven目录结构下所示

-example- example-runner- pom.xml- example-main- pom.xml- example-plugin-parent- pom.xml- plugins- example-plugin1- pom.xml- plugin.properties- example-plugin2- pom.xml- plugin.properties- pom.xml- pom.xml

结构说明:

pom.xml 代表maven的pom.xml

plugin.properties 为开发环境下, 插件的元信息配置文件, 配置内容详见下文。

example 为项目的总Maven目录。

example-runner 在运行环境下启动的模块。主要依赖example-main模块和插件中使用到的依赖包。

example-main 该模块为项目的主程序模块。

example-plugin-parent 该模块为插件的父级maven pom 模块, 主要定义插件中公共用到的依赖, 以及插件的打包配置。

plugins 该文件夹下主要存储插件模块。上述模块中主要包括example-plugin1、example-plugin2 两个插件。

example-plugin1、example-plugin2 分别为两个插件Maven包。

主程序集成步骤

主程序为上述目录结构中的 example-main 模块。

在主程序中新增maven依赖包

<dependency><groupId>com.gitee.starblues</groupId><artifactId>springboot-plugin-framework</artifactId><version>${springboot-plugin-framework.version}</version>
</dependency>

实现并定义配置

实现 com.plugin.development.integration.IntegrationConfiguration 接口。

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;@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;@Overridepublic RuntimeMode environment() {return RuntimeMode.byName(runMode);}@Overridepublic String pluginPath() {return pluginPath;}@Overridepublic String pluginConfigFilePath() {return pluginConfigFilePath;}/*** 重写上传插件包的临时存储路径。只适用于生产环境* @return String*/@Overridepublic String uploadTempPath() {return "temp";}/*** 重写插件备份路径。只适用于生产环境* @return String*/@Overridepublic String backupPath() {return "backupPlugin";}/*** 重写插件RestController请求的路径前缀* @return String*/@Overridepublic String pluginRestControllerPathPrefix() {return "/api/plugins";}/*** 重写是否启用插件id作为RestController请求的路径前缀。* 启动则插件id会作为二级路径前缀。即: /api/plugins/pluginId/*** @return String*/@Overridepublic 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;}@Overridepublic String toString() {return "PluginArgConfiguration{" +"runMode='" + runMode + ''' +", pluginPath='" + pluginPath + ''' +", pluginConfigFilePath='" + pluginConfigFilePath + ''' +'}';}
}

配置说明:

runMode:运行项目时的模式。分为开发环境(dev)、生产环境(prod)

pluginPath: 插件的路径。开发环境建议直接配置为插件模块的父级目录。例如: plugins。如果启动主程序时, 插件为加载, 请检查该配置是否正确。

pluginConfigFilePath: 在生产环境下, 插件的配置文件路径。在生产环境下, 请将所有插件使用到的配置文件统一放到该路径下管理。如果启动主程序时, 报插件的配置文件加载错误, 有可能是该该配置不合适导致的。

uploadTempPath: 上传插件包时使用。上传插件包存储的临时路径。默认 temp(相对于主程序jar路径)

backupPath: 备份插件包时使用。备份插件包的路径。默认: backupPlugin(相对于主程序jar路径)

pluginRestControllerPathPrefix: 插件RestController请求的路径前缀

enablePluginIdRestControllerPathPrefix: 是否启用插件id作为RestController请求的路径前缀。启动则插件id会作为二级路径前缀。即: /api/plugins/pluginId/**

配置bean

import com.gitee.starblues.integration.*;
import com.gitee.starblues.integration.initialize.AutoPluginInitializer;
import com.gitee.starblues.integration.initialize.PluginInitializer;
import org.pf4j.PluginException;
import org.pf4j.PluginManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class PluginBeanConfig {/*** 通过默认的集成工厂返回 PluginManager* @param integrationConfiguration 集成的配置文件* @return* @throws PluginException*/@Beanpublic PluginManager pluginManager(IntegrationConfiguration integrationConfiguration) throws PluginException {IntegrationFactory integrationFactory = new DefaultIntegrationFactory();return integrationFactory.getPluginManager(integrationConfiguration);}/*** 定义默认的插件应用。使用可以注入它操作插件。* @return*/@Beanpublic PluginApplication pluginApplication(){return new DefaultPluginApplication();}/*** 初始化插件。此处定义可以在系统启动时自动加载插件。*  如果想手动加载插件, 则可以使用 com.plugin.development.integration.initialize.ManualPluginInitializer 来初始化插件。* @param pluginApplication* @return*/@Beanpublic PluginInitializer pluginInitializer(PluginApplication pluginApplication){AutoPluginInitializer autoPluginInitializer = new AutoPluginInitializer(pluginApplication);return autoPluginInitializer;}}

插件包集成步骤

插件包pom.xml配置说明

以 <scope>provided</scope> 方式引入springboot-plugin-framework包

<dependency><groupId>com.gitee.starblues</groupId><artifactId>springboot-plugin-framework</artifactId><version>${springboot-plugin-framework.version}</version><scope>provided</scope>
</dependency>

定义打包配置.主要用途是将 Plugin-Id、Plugin-Version、Plugin-Provider、Plugin-Class、Plugin-Dependencies的配置值定义到META-INFMANIFEST.MF文件中

<properties>

<plugin.id - 这个网站可出售。 - 最佳的plugin 来源和相关信息。>springboot-plugin-example-plugin1</plugin.id>

    <plugin.class>com.plugin.example.plugin1.DefinePlugin</plugin.class><plugin.version>${project.version}</plugin.version><plugin.provider>StarBlues</plugin.provider><plugin.dependencies></plugin.dependencies><java.version>1.8</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><maven-compiler-plugin.version>3.7.0</maven-compiler-plugin.version><maven-assembly-plugin.version>3.1.1</maven-assembly-plugin.version>
</properties>
<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>${maven-compiler-plugin.version}</version><configuration><source>${java.version}</source><target>${java.version}</target><encoding>${project.build.sourceEncoding}</encoding></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-assembly-plugin</artifactId><version>${maven-assembly-plugin.version}</version><configuration><descriptorRefs><descriptorRef>jar-with-dependencies</descriptorRef></descriptorRefs><archive><manifest><addDefaultImplementationEntries>true</addDefaultImplementationEntries><addDefaultSpecificationEntries>true</addDefaultSpecificationEntries></manifest><manifestEntries><Plugin-Id>${plugin.id - 这个网站可出售。 - 最佳的plugin 来源和相关信息。}</Plugin-Id><Plugin-Version>${plugin.version}</Plugin-Version><Plugin-Provider>${plugin.provider}</Plugin-Provider><Plugin-Class>${plugin.class}</Plugin-Class></manifestEntries></archive></configuration><executions><execution><id>make-assembly</id><phase>package</phase><goals><goal>single</goal></goals></execution></executions></plugin></plugins>
</build>

在插件包的一级目录下新建plugin.properties文件(用于开发环境)

新增如下内容(属性值同步骤1中pom.xml定义的manifestEntries属性一致):

plugin.id=springboot-plugin-example-plugin1
plugin.class=com.plugin.example.plugin1.DefinePlugin
plugin.version=2.0-SNAPSHOT
plugin.provider=StarBlues

配置说明:

plugin.id - 这个网站可出售。 - 最佳的plugin 来源和相关信息。: 插件id

plugin.class: 插件实现类。见步骤3说明

plugin.version: 插件版本

plugin.provider: 插件作者

继承 com.gitee.starblues.realize.BasePlugin 包

import com.gitee.starblues.realize.BasePlugin;
import org.pf4j.PluginException;
import org.pf4j.PluginWrapper;public class DefinePlugin extends BasePlugin {public DefinePlugin(PluginWrapper wrapper) {super(wrapper);}@Overrideprotected void startEvent() throws PluginException {}@Overrideprotected void deleteEvent() throws PluginException {}@Overrideprotected void stopEvent() {}
}

并且将该类的包路径(com.plugin.example.plugin1.DefinePlugin)配置在步骤1和2的plugin.class属性中。

新增HelloPlugin1 controller

此步骤主要验证环境是否加载插件成功。

@RestController
@RequestMapping(path = "plugin1")
public class HelloPlugin1 {@GetMapping()public String getConfig(){return "hello plugin1"}}

运行配置

配置模块 example-runner 的pom.xml

将主程序的依赖新增到pom.xml 下

将插件中的依赖以 <scope>provided</scope> 方式引入到 pom.xml 下

如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.3.RELEASE</version><relativePath/></parent><groupId>com.gitee.starblues</groupId><artifactId>plugin-example-runner</artifactId><version>2.0-RELEASE</version><packaging>pom</packaging><properties><gson.version>2.8.2</gson.version></properties><dependencies><dependency><groupId>com.gitee.starblues</groupId><artifactId>plugin-example-start</artifactId><version>${project.version}</version></dependency><!-- 此处依赖用于解决在开发环境下, 插件包找不到对应依赖包 --><dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>${gson.version}</version><scope>provided</scope></dependency></dependencies></project>

设置idea的启动

Working directory : D:xxxxspringboot-plugin-framework-parentplugin-exampleUse classpath of module: plugin-exampe-runner勾选: Include dependencies with “Provided” scope

启动2步骤的配置。

观察日志出现如下说明加载插件成功。

 Plugin 'springboot-plugin-example-plugin1@2.0-RELEASE' resolvedStart plugin 'springboot-plugin-example-plugin1@2.0-RELEASE'Init Plugins <springboot-plugin-example-plugin1> Success

访问插件中的Controller 验证。

浏览器输入:http://ip:port/api/plugins/springboot-plugin-example-plugin1/plugin1

响应并显示: hello plugin1

说明集成成功!

使用说明

插件中定义配置文件

在插件包的 resources 目录下定义配置文件 plugin1.yml

name: plugin1
plugin: examplePlugin1
setString:- set1- set2
listInteger:- 1- 2- 3
subConfig:subName: subConfigName

在代码中定义对应的bean

import com.gitee.starblues.annotation.ConfigDefinition;
import java.util.List;
import java.util.Set;@ConfigDefinition("plugin1.yml")
public class PluginConfig1 {private String name;private String plugin;private Set<String> setString;private List<Integer> listInteger;private String defaultValue = "defaultValue";private SubConfig subConfig;// 自行提供get set 方法}public class SubConfig {private String subName;public String getSubName() {return subName;}// 自行提供get set 方法
}

该bean必须加上 @ConfigDefinition(“plugin1.yml”) 注解。其中值为插件文件的名称。

其他地方使用时, 可以通过注入方式使用。

例如:

@Component("plugin2HelloService")
public class HelloService {private final PluginConfig1 pluginConfig1;private final Service2 service2;@Autowiredpublic HelloService(PluginConfig1 pluginConfig1, Service2 service2) {this.pluginConfig1 = pluginConfig1;this.service2 = service2;}public PluginConfig1 getPluginConfig1(){return pluginConfig1;}public String sayService2(){return service2.getName();}}

注意事项

在开发环境:配置文件必须放在resources目录下。并且@ConfigDefinition(“plugin1.yml”)中定义的文件名和resources下配置的文件名一致。

在生产环境: 该文件存放在pluginConfigFilePath配置的目录下。

集成扩展

SpringBoot Mybatis 扩展

文档见: springboot-plugin-framework-extension-mybatis

案例部署

普通例子运行见:package/example

windows环境下运行: package.bat

linux、mac 环境下运行: package.sh

mybatis 案例部署

普通例子运行见:package/example-persistence

windows环境下运行: package.bat

linux、mac 环境下运行: package.sh

sql在 plugin-example-persistence/sql 文件夹下。

生产环境目录

-main.jar-main.yml-plugins-plugin1.jar-plugin2.jar-pluginFile-plugin1.yml-plugin2.yml

案例说明

plugin-example:插件基础功能案例。

plugin-example-persistence: 针对Mybatis集成的案例。

生产环境配置禁用启用功能

启用、禁用功能

1.在插件目录下新建 enabled.txt 文件

2.enabled.txt的内容为:

########################################
# - 启用的插件
########################################
example-plugin1

将需要启用的插件id配置到文件中。

所有注释行(以#字符开头的行)都将被忽略。

禁用功能

1.在插件目录下新建 disabled.txt 文件

2.disabled.txt的内容为:

########################################
# - 禁用的插件
########################################
example-plugin1

将需要启用的插件id配置到文件中。

所有注释行(以#字符开头的行)都将被忽略。

注意事项

插件中代码编写完后, 请保证在class文件下的类都是最新编译的, 再运行主程序, 否则会导致运行的插件代码不是最新的。

如果启动时插件没有加载。请检查配置文件中的 pluginPath

如果pluginPath 配置为相当路径,请检查是否是相对于当前工作环境的目录。

如果pluginPath配置为绝对路径,请检查路径是否正确。

小技巧

idea 启动主程序时, 自动编译插件包的配置

选择

File->Project Structure->Project Settings->Artifacts->点击+号->JAR->From modules whith dependencies->选择对应的插件包->确认OK

启动配置:

在Before launch 下-> 点击小+号 -> Build ->Artifacts -> 选择上一步新增的>Artifacts

版本更新

1.1 版本

新增插件注册、卸载监听器。

新增可通过 PluginUser 获取插件中实现主程序中定义的接口的实现类。

新增插件注册、卸载时监听器。

2.0 版本(重大版本更新)

重构代码。

新增扩展机制。

简化依赖注入注解, 保持与SpringBoot依赖注入方式一致。

新增插件工厂监听器、新增插件初始化监听器(适用于第一次启动)。

新增插件包Mybatis的集成, 可在插件包中独立定义Mapper接口、Mapper xml、实体bean。

文章最后喜欢的小伙伴可以关注下我的或者关注我的专栏,以后给大家带来更多精彩的技术分享

程序员学习之路​zhuanlan.zhihu.com

springboot 前缀_springboot插件式开发框架相关推荐

  1. P3-weixin-2.0.0版本发布(微信插件式开发框架)

    P3-weixin-2.0.0版本发布(微信插件式开发框架) 1.P3-weixin为何诞生 现在微信越来越火,基于微信的公众号和服务号越来越丰富,单一的微信管家系统已经满足不了微信的需求.Jeecg ...

  2. springboot 前缀_SpringBoot配置文件的注入

    需要了解更多java知识的朋友关注我的专栏,持续更新java知识. Java架构杂货铺​zhuanlan.zhihu.com 1. 使用@PropertySource 使用 @PropertySour ...

  3. springboot 前缀_Springboot Redis设置key 前缀

    springboot 连接redis 并设置key前缀 properties中配置 #redis redis.masterClusterNodes=10.40.57.197:7000;10.40.57 ...

  4. springboot 前缀_SpringBoot + 指定包下所有控制器 + 添加统一前缀

    SpringBoot + 指定包下所有控制器 + 添加统一前缀 自定义版本控制器接口定义 提供两个方法,一个方法是需要添加url前缀的控制器所属的包名称,一个是需要添加的url前缀. /** * 版本 ...

  5. springboot 前缀_springboot搭配thymeleaf访问html页面的时候,什么时候需要自定义前缀和后缀呢...

    为什么我全部使用默认配置会报错,必须自己定义前缀和后缀 解析器配置如下:@Configuration public class WebMvcConfig extends WebMvcConfigure ...

  6. springboot 前缀_SpringBoot自动加载路由前缀

    @RequestMapping() 将controller注册到容器中时需要加入路由地址,如果项目层数较深,地址会非常的长,并且有很多一样的路由前缀,每写一个controller都要重复一遍非常的麻烦 ...

  7. 企业信息化解决方案——插件式平台开发框架

    0.三板斧 作为职业Programmer或是优秀Team,拥有一套成熟.稳定的开发框架,无疑是行走IT江湖.纵横IT市场的必备功底. 无图无真相,作为一个讲究实效的ITer,先来几道的甜点凉菜,后续会 ...

  8. 基于插件式的开发框架

    转载地址:http://guojun2sq.blog.163.com/blog/static/64330861201002010314694/ http://www.cnblogs.com/mix-u ...

  9. 插件式编程SBP框架极简教程(基于SpringBoot)

    插件式编程SBP框架极简教程(基于SpringBoot 一.前言 二.背景 三.项目简介 四 .看效果 4.1 测试主程序接口 4.2 测试A插件程序接口 4.3 测试B插件程序接口 五 .展望 一. ...

最新文章

  1. java基础编程题(1)
  2. 浅析综合布线系统中检测双绞线的几种方式
  3. Java一个对象的内存运行流程图
  4. python scikit learn 封装_python的scikit-learn的主要模块和基本使用
  5. 您的光纤电缆和测试仪是否准备好用于400G以太网?
  6. ubuntu安装zsh、oh-my-zsh及常用配置
  7. php多应用,thinkphp6开启多应用模式
  8. 10个必知的网页设计术语计算机与网络,入学测试计算机与网络应用基础知识题库(公开题)教学文稿(10页)-原创力文档...
  9. UVA10450 POJ1953 World Cup Noise【斐波那契数列】
  10. PhotoShop的10大误区
  11. [SV]SystemVerilog Structured Procedures --- always_comb、always_ff、always_latch
  12. 原生实现点击li变颜色
  13. 常用显示器,硬盘都有哪几种接口
  14. APP 的开发费用标准是什么?
  15. testflight测试的直播软件,TestFlight - Apple
  16. 安卓Android修改车机版系统的导航栏和状态栏高度
  17. 代理模式相关简单论述
  18. 2022年03月05日:宜未雨而绸缪,毋临渴而掘井
  19. linux 升级root,linux系统内核升级实例
  20. 网口压线顺序_家里网线的接法和顺序

热门文章

  1. UE3 贴图支持及设置
  2. android Activity runOnUiThread() 方法的使用
  3. 转 从20秒到0.5秒:一个使用Rust语言来优化Python性能的案例
  4. MySQL 高可用架构在业务层面细化分析研究
  5. [Unity3d]Unity Mathf 数学运算(C#)
  6. 如何解决uchome自带编辑器无法获取uchome编辑器里面的值问题?(uchome二次开发)...
  7. MySQL安装叫重启_MySQL重启命令和MySQL数据库安装目录的操作过程
  8. python编程胡牌将是什么意思_python麻将和牌算法
  9. 怎么让网页中的文字两边留出空白_横线、方格、点阵、空白本,谁才是笔记本中的C位?...
  10. 简述一下索引的匹配原则_Mysql联合索引最左匹配原则