背景
在当下后端市场,还是以spring-boot为核心框架进行系统开发,本框架可以在spring-boot系统上进行插件式的开发,将插件当做一个mini版本的spring-boot进行系统扩展开发,可以解决如下痛点:
- 在To-B系统场景中,不同甲方会有不同的需求,在不打分支和改动系统核心代码的前提下,可以在插件中进行扩展开发特定功能,不同甲方使用不同插件,完美解决非核心系统的扩展功能开发,例如扩展中台系统的不同需求。
- 在To-C系统场景中,可以在主程序通过定义java-interface,在插件中做不同实现,来达到动态扩展系统功能。
- 在开发中,由于引入了不同版本的依赖,导致系统无法运行,本框架可以完美解决在不同插件中定义不同版本的依赖,从底层进行隔离,以解决引入不同版本依赖冲突的问题。比如可以完美解决系统同时连接数据库mysql-5和mysql-8版本。
- 在开发中,不同插件依赖不同框架的功能,可以按需引入。比如在插件A引入连接mysql、在插件B引入连接elasticsearch、在插件C引入连接oracle。
- 在插件中,可以任意集成不同的非web类型的springboot-xx-starter,然后将不同插件功能组装起来,以达到一个统一对外提供服务的完整系统,实现系统组装化、插拔化开发。
- 在不重启主程序的前提下,对插件进行动态的安装、卸载、启动、停止。
介绍
该框架可以在spring-boot项目上开发出插件功能,在插件中可以和spring-boot使用方式一模一样。使用了本框架您可以实现如下需求:
- 在插件中,您可以当成一个微型的spring-boot项目来开发,简单易用。
- 在插件中扩展出系统各种功能点,用于系统灵活扩展,再也不用使用分支来交付不同需求的项目了。
- 在插件中可以集成各种框架及其各种spring-boot-xxx-starter。
- 在插件中可以定义独立依赖包了,再也不用在主程序中定义依赖包了。
- 可以完美解决插件包与插件包、插件包与主程序因为同一框架的不同版本冲突问题了。各个插件可以定义同一依赖的不同版本框架。
- 无需重启主程序,可以自由实现插件包的动态安装部署,来动态扩展系统的功能。
- 插件也可以不依赖主程序独立集成微服务模块。
- ~~~等等,您可以丰富想象该框架给您带来哪些迫切的需求和扩展,以实现系统的低耦合、高内聚、可扩展的优点。
特性
- 简化了框架的集成步骤,更容易上手。
- 插件开发更加贴近spring-boot原生开发。
- 支持两种模式开发: 隔离模式、共享模式, 可自主根据需要灵活选择使用。
- 使用Maven打包插件,支持对插件的自主打包编译。目前支持:
- 开发打包:将插件打包成开发环境下的插件(仅需打包一次)。
- 生产打包:将插件打包成一个jar、zip、文件夹等。
- 自主的开发的类加载器,支持插件定义各种的依赖jar包。
- 在插件中可以集成各种框架及其各种spring-boot-xxx-starter,比如集成mybatis、mybatis-plus、spring-jpa等。
- 动态安装、卸载、启动、停止插件。
- 主程序和插件类隔离, 有效避免主程序与插件、插件与插件之间的类冲突。
架构
主程序配置集成
1. 引入框架依赖
com.gitee.starblues
spring-brick
${latest.version}
2. 在配置文件加入配置
plugin:
runMode: dev
mainPackage: com.gitee.starblues.example
pluginPath:
- D://project//plugins(替换为自己环境下插件目录)
- 配置说明:
runMode: 运行模式, 开发环境: dev; 生产环境: prod。dev环境下,只适用于在idea环境下开发调试,prod环境只能加载打包的插件,比如jar、zip等,插件打包详见: 插件打包详细说明
mainPackage: 主程序扫描的包名。
pluginPath: 插件目录或者插件上级目录,可配置多个。
- 详细配置见:https://www.yuque.com/starblues/iuyk4y/pm8x4g
3. 改造 Spring-Boot 启动类
- 在main类中实现框架引导类SpringBootstrap,在run方法中使用和SpringBoot启动方式一致的实现。
- 在main方法中使用SpringMainBootstrap进行引导启动。具体实现如下:
import com.gitee.starblues.loader.launcher.SpringMainBootstrap;
import com.gitee.starblues.loader.launcher.SpringBootstrap;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application implements SpringBootstrap {
public static void main(String[] args) {
// 该处使用 SpringMainBootstrap 引导启动
SpringMainBootstrap.launch(Application.class, args);
}
@Override
public void run(String[] args) throws Exception {
// 在该实现方法中, 和 SpringBoot 使用方式一致
SpringApplication.run(Application.class, args);
}
}
4. 打包主程序
- 主程序使用maven命令:mvn clean install进行打包
插件配置集成
1. 引入依赖
org.springframework.boot
spring-boot-starter
${和主程序一致的springboot版本}
com.gitee.starblues
spring-brick-bootstrap
${latest.version}
主程序的 groupId
主程序的 artifactId
主程序 version
provided
2. 定义插件引导类
注意:插件包名不能和主程序包名一致,如需一致,需遵循:插件包名范围小于等于主程序包名。
详细规则可见:
https://www.yuque.com/starblues/spring-brick-3.0.0/siet7b
- 定义插件main入口类, 继承SpringPluginBootstrap类, 然后在main函数中实例化当前引导类,并执行run方法即可。实现如下:
import com.gitee.starblues.bootstrap.SpringPluginBootstrap;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ExamplePlugin extends SpringPluginBootstrap {
public static void main(String[] args) {
new ExamplePlugin().run(args);
}
}
3. 配置Maven打包插件
- 使用框架自带的打包插件,对插件包进打包。
- 将如下配置加入到插件的maven的 pom.xml 中
com.gitee.starblues
spring-brick-maven-packager
${latest.version}
dev
plugin-example
com.gitee.starblues.example.ExamplePlugin
1.0.0-SNAPSHOT
repackage
- 详细打包插件说明见: https://www.yuque.com/starblues/iuyk4y/tfxx2b
4. 新增 Controller 接口
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/example")
public class ExampleController {
@GetMapping
public String hello(){
return "hello";
}
}
5. 编译插件
- 插件使用maven命令:mvn clean package进行编译
启动测试
- 启动主程序main, 日志中出现如下关键内容,说明集成插件成功
c.g.s.i.operator.DefaultPluginOperator : 插件加载环境: dev
c.g.s.core.PluginLauncherManager : 插件[plugin-example@1.0.0-SNAPSHOT]加载成功
c.g.s.b.p.web.PluginControllerProcessor : 插件[plugin-example]注册接口: {GET [/plugins/module1/example]}
c.g.s.core.PluginLauncherManager : 插件[plugin-example@1.0.0-SNAPSHOT]启动成功
c.g.s.i.operator.DefaultPluginOperator : 插件初始化完成
- 打开浏览器,访问接口: http://127.0.0.1:8080/plugins/plugin-example/example 进行测试是否能访问成功。