天天看點

spring-brick 為動态擴充系統而生的插件開發架構

作者:stonevV9S

背景

在當下後端市場,還是以spring-boot為核心架構進行系統開發,本架構可以在spring-boot系統上進行插件式的開發,将插件當做一個mini版本的spring-boot進行系統擴充開發,可以解決如下痛點:

  1. 在To-B系統場景中,不同甲方會有不同的需求,在不打分支和改動系統核心代碼的前提下,可以在插件中進行擴充開發特定功能,不同甲方使用不同插件,完美解決非核心系統的擴充功能開發,例如擴充中台系統的不同需求。
  2. 在To-C系統場景中,可以在主程式通過定義java-interface,在插件中做不同實作,來達到動态擴充系統功能。
  3. 在開發中,由于引入了不同版本的依賴,導緻系統無法運作,本架構可以完美解決在不同插件中定義不同版本的依賴,從底層進行隔離,以解決引入不同版本依賴沖突的問題。比如可以完美解決系統同時連接配接資料庫mysql-5和mysql-8版本。
  4. 在開發中,不同插件依賴不同架構的功能,可以按需引入。比如在插件A引入連接配接mysql、在插件B引入連接配接elasticsearch、在插件C引入連接配接oracle。
  5. 在插件中,可以任意內建不同的非web類型的springboot-xx-starter,然後将不同插件功能組裝起來,以達到一個統一對外提供服務的完整系統,實作系統組裝化、插拔化開發。
  6. 在不重新開機主程式的前提下,對插件進行動态的安裝、解除安裝、啟動、停止。

介紹

該架構可以在spring-boot項目上開發出插件功能,在插件中可以和spring-boot使用方式一模一樣。使用了本架構您可以實作如下需求:

  • 在插件中,您可以當成一個微型的spring-boot項目來開發,簡單易用。
  • 在插件中擴充出系統各種功能點,用于系統靈活擴充,再也不用使用分支來傳遞不同需求的項目了。
  • 在插件中可以內建各種架構及其各種spring-boot-xxx-starter。
  • 在插件中可以定義獨立依賴包了,再也不用在主程式中定義依賴包了。
  • 可以完美解決插件包與插件包、插件包與主程式因為同一架構的不同版本沖突問題了。各個插件可以定義同一依賴的不同版本架構。
  • 無需重新開機主程式,可以自由實作插件包的動态安裝部署,來動态擴充系統的功能。
  • 插件也可以不依賴主程式獨立內建微服務子產品。
  • ~~~等等,您可以豐富想象該架構給您帶來哪些迫切的需求和擴充,以實作系統的低耦合、高内聚、可擴充的優點。

特性

  1. 簡化了架構的內建步驟,更容易上手。
  2. 插件開發更加貼近spring-boot原生開發。
  3. 支援兩種模式開發: 隔離模式、共享模式, 可自主根據需要靈活選擇使用。
  4. 使用Maven打包插件,支援對插件的自主打包編譯。目前支援:
  • 開發打包:将插件打包成開發環境下的插件(僅需打包一次)。
  • 生産打包:将插件打包成一個jar、zip、檔案夾等。
  1. 自主的開發的類加載器,支援插件定義各種的依賴jar包。
  2. 在插件中可以內建各種架構及其各種spring-boot-xxx-starter,比如內建mybatis、mybatis-plus、spring-jpa等。
  3. 動态安裝、解除安裝、啟動、停止插件。
  4. 主程式和插件類隔離, 有效避免主程式與插件、插件與插件之間的類沖突。

架構

spring-brick 為動态擴充系統而生的插件開發架構

主程式配置內建

1. 引入架構依賴

<dependency>
  <groupId>com.gitee.starblues</groupId>
  <artifactId>spring-brick</artifactId>
  <version>${latest.version}</version>
</dependency>           

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. 引入依賴

<!-- spring-boot-starter依賴 -->
<!--建議将spring-boot-starter依賴放到第一個位置, 以防止出現依賴沖突導緻無法啟動插件-->
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter</artifactId>
  <version>${和主程式一緻的springboot版本}</version>
</dependency>

<!-- spring-brick-bootstrap依賴 -->
<dependency>
  <groupId>com.gitee.starblues</groupId>
  <artifactId>spring-brick-bootstrap</artifactId>
  <version>${latest.version}</version>
</dependency>

<!-- 主程式依賴 -->
<!-- 将主程式以 provided 方式依賴到插件中 -->
<dependency>
  <groupId>主程式的 groupId</groupId>
  <artifactId>主程式的 artifactId</artifactId>
  <version>主程式 version</version>
  <scope>provided</scope>
</dependency>           

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 中
<build>
  <plugins>
    <plugin>
      <groupId>com.gitee.starblues</groupId>
      <artifactId>spring-brick-maven-packager</artifactId>
      <version>${latest.version}</version>
      <configuration>
        <!--目前打包模式為: 開發模式-->
        <mode>dev</mode>
        <!--插件資訊定義-->
        <pluginInfo>
          <!--插件id-->
          <id>plugin-example</id>
          <!--插件入口類, 定義說明見: 定義插件入口類-->
          <bootstrapClass>com.gitee.starblues.example.ExamplePlugin</bootstrapClass>
          <!--插件版本号-->
          <version>1.0.0-SNAPSHOT</version>
        </pluginInfo>
      </configuration>
      <executions>
        <execution>
          <goals>
            <goal>repackage</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>           
  • 詳細打包插件說明見: 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         : 插件[[email protected]]加載成功
c.g.s.b.p.web.PluginControllerProcessor  : 插件[plugin-example]注冊接口: {GET [/plugins/module1/example]}
c.g.s.core.PluginLauncherManager         : 插件[[email protected]]啟動成功
c.g.s.i.operator.DefaultPluginOperator   : 插件初始化完成           
  • 打開浏覽器,通路接口: http://127.0.0.1:8080/plugins/plugin-example/example 進行測試是否能通路成功。