「SpringBrick快速入门指南」:☀️ 后端领域新兴技术璀璨之星☀️ 基于Spring Boot的高级插件化开发框架

news2025/1/16 3:43:43

文章目录

    • 关于 | About
      • 技术文档 | Document
      • 开源项目 | Project
    • 案例 | Demo
      • 项目结构 | Structure
      • 主程序配置集成 | Settings
        • 引入框架依赖 | Framework
        • 在配置文件加入配置 | Yaml
        • SpringBoot启动类改引导类 | Change
      • 插件配置集成 | Settings
        • 引入依赖 | XML
        • 定义插件引导类 | Class
        • 配置Maven打包插件 | Maven
      • 新增Controller接口API | API
      • 编译打包插件 | JAR
      • 启动测试 | Main
    • Demo案例Git地址 | Gitee

工作项目中用到了这款插件式开发框架,看了一下网上教程不多,所以打算为大家普及一下这个技术框架,写一些入门教程方便大家学习运用。

关于 | About

“Spring-brick”,是一个可以动态扩展系统的框架,最早在2019年开始开发,该框架可以在SpringBoot项目上开发插件功能,开发插件就像开发独立应用一样。

这里的插件我们可以理解成一个独立的SpringBoot应用,微服务等单体项目。

技术文档 | Document

文档如下:https://www.yuque.com/starblues/spring-brick-3.0.0image-20240315154413130

开源项目 | Project

开源项目:https://gitee.com/starblues/springboot-plugin-framework-parent.git

image-20240315154511290

这个框架除了官方介绍的优点之外,也有它的不足之处,后文我会提出来。

该框架可以在spring-boot项目上开发出插件功能,在插件中可以和spring-boot使用方式一模一样。使用了本框架您可以实现如下需求:

  • 在插件中,您可以当成一个微型的spring-boot项目来开发,简单易用。
  • 在插件中扩展出系统各种功能点,用于系统灵活扩展,再也不用使用分支来交付不同需求的项目了。
  • 在插件中可以集成各种框架及其各种spring-boot-xxx-starter
  • 在插件中可以定义独立依赖包了,再也不用在主程序中定义依赖包了。
  • 可以完美解决插件包与插件包、插件包与主程序因为同一框架的不同版本冲突问题了。各个插件可以定义同一依赖的不同版本框架。
  • 无需重启主程序,可以自由实现插件包的动态安装部署,来动态扩展系统的功能。
  • 插件也可以不依赖主程序独立集成微服务模块。
  • 您可以丰富想象该框架给您带来哪些迫切的需求和扩展,以实现系统的低耦合、高内聚、可扩展的优点。

案例 | Demo

本次演示一个入门小案例,让我带大家快速进入这个框架,上手使用它。这个案例是我自己写的一个便于大家快速入门的案例,不容易出现错误,清晰明了的入门教程。

项目结构 | Structure

项目名称: springboot-plugin-framework-example-linghu

├─example-main
│  │  pom.xml
│  │  
│  ├─src
│  │  ├─main
│  │  │  ├─java
│  │  │  │  └─com
│  │  │  │      └─linghu
│  │  │  │              MainApp.java
│  │  │  │              
│  │  │  └─resources
│  │  │          application.yml
│     
└─example-plugins-basic
    │  pom.xml
    │  
    ├─src
    │  ├─main
    │  │  ├─java
    │  │  │  └─com
    │  │  │      └─linghu
    │  │  │          ├─controller
    │  │  │          │      ExampleController.java
    │  │  │          │      ExamplePlugin.java
    │  │  │          │      
    │  │  │          └─plugin
    │  │  └─resources
    │  │          application.yml

这个项目分为两个部分:

  • 主程序-example-main
  • 插件程序-example-plugins-basic

我们的目的是运行主程序,然后执行插件程序里的业务,这样我们就可以专注开发插件程序了,可以不断根据业务的不同接入不同的插件程序,而不用去动主程序的代码,这就是我们说的 高内聚、低耦合、可扩展

分好类以后我们开始接下来的具体工作。

我们的工作分为两个部分:

  • 主程序配置集成 | Settings
  • 插件配置集成 | Settings

主程序配置集成 | Settings

我们说了主程序实际上就是上面 example-main部分。

引入框架依赖 | Framework

引入框架依赖:

<dependency>
            <groupId>com.gitee.starblues</groupId>
            <artifactId>spring-brick</artifactId>
            <version>3.1.0</version>
 </dependency>

具体主程序的pom文件配置如下:

<?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>com.linghu</groupId>
        <artifactId>springboot-plugin-framework-example-linghu</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>example-main</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.gitee.starblues</groupId>
            <artifactId>spring-brick</artifactId>
            <version>3.1.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>


    </dependencies>
</project>
在配置文件加入配置 | Yaml

这里的yaml文件配置主要是让将插件程序接入到主程序中

plugin:
  runMode: dev
  mainPackage: com.linghu
  pluginPath:
#    这里集成了一个插件程序example-plugins-basic模块
    - ~\example-plugins-basic

需要注意的是上面的 mainPackage表示主程序类的路径。pluginPath则是我们插件的相对路径地址。

- ~\example-plugins-basic中的 ~\表示相对路径地址; example-plugins-basic则是我们的插件名称。

完整的yml配置则是:

server:
  port: 8080

plugin:
  runMode: dev
  mainPackage: com.linghu
  pluginPath:
#    这里集成了一个插件程序example-plugins-basic模块
    - ~\example-plugins-basic
spring:
  mvc:
    pathmatch:
      matching-strategy: ant_path_matcher

SpringBoot启动类改引导类 | Change

这个改动发生在主程序的启动类上

package com.linghu;

import com.gitee.starblues.loader.launcher.SpringBootstrap;
import com.gitee.starblues.loader.launcher.SpringMainBootstrap;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author linghu
 * @date ${DATE} ${TIME}
 */
@SpringBootApplication
public class MainApp implements SpringBootstrap {
    public static void main(String[] args) {
        // 该处使用 SpringMainBootstrap 引导启动
        SpringMainBootstrap.launch(MainApp.class, args);
    }

    @Override
    public void run(String[] args) throws Exception {
        // 在该实现方法中, 和 SpringBoot 使用方式一致
        SpringApplication.run(MainApp.class, args);
    }

}

这里为啥要这么改?后续我会出文章解释,剖析源码。

插件配置集成 | Settings

插件程序主要是指:example-plugins-basic部分

引入依赖 | XML
<!-- 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>

上面是个引入模版,大家引入以后还要进行修改,下面是我修改的我的完整依赖:

<?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>com.linghu</groupId>
        <artifactId>springboot-plugin-framework-example-linghu</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>example-plugins-basic</artifactId>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!--        =====================插件配置集成========================-->
        <!-- spring-boot-starter依赖 -->
        <!--建议将spring-boot-starter依赖放到第一个位置, 以防止出现依赖冲突导致无法启动插件-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
            <version>2.7.9</version>
        </dependency>

        <!--解决方案: 确保插件不包含spring-boot-starter-web依赖,而是让主程序来加载这个依赖。这样,主程序就可以管理所有的Spring Boot web依赖,避免了重复。
           如果您使用的是Maven,您可以在插件的pom.xml文件中移除对spring-boot-starter-web的依赖,或者如果您在主程序的pom.xml中已经定义了这个依赖,
           您可以在插件的pom.xml中添加<exclusions>元素来排除这个依赖。-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-starter-web</artifactId>
                </exclusion>
            </exclusions>
        </dependency>


        <!-- spring-brick-bootstrap依赖 -->
        <dependency>
            <groupId>com.gitee.starblues</groupId>
            <artifactId>spring-brick-bootstrap</artifactId>
            <version>3.1.0</version>
        </dependency>

        <!-- 主程序依赖 -->
        <!-- 将主程序以 provided 方式依赖到插件中 -->
        <dependency>
            <groupId>com.linghu</groupId>
            <artifactId>example-main</artifactId>
            <version>1.0-SNAPSHOT</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

<!--    =================插件打包的配置===================-->
    <build>
        <plugins>
            <plugin>
                <groupId>com.gitee.starblues</groupId>
                <artifactId>spring-brick-maven-packager</artifactId>
                <version>3.1.0</version>
                <configuration>
                    <!--当前打包模式为: 开发模式-->
                    <mode>dev</mode>
                    <!--插件信息定义-->
                    <pluginInfo>
                        <!--插件id-->
                        <id>example-plugins-basic</id>
                        <!--插件入口类, 定义说明见: 定义插件入口类-->
                        <bootstrapClass>com.linghu.controller.ExamplePlugin</bootstrapClass>
                        <!--插件版本号-->
                        <version>1.0.0-SNAPSHOT</version>
                    </pluginInfo>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>
定义插件引导类 | Class

这个引导类是加在插件里的主类里的,不要搞错了。

package com.linghu.controller;

import com.gitee.starblues.bootstrap.SpringPluginBootstrap;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author linghu
 * @date 2024/3/15 9:55
 */
@SpringBootApplication
public class ExamplePlugin extends SpringPluginBootstrap {
    public static void main(String[] args) {
        new ExamplePlugin().run(args);
    }

}

定义插件main入口类, 继承SpringPluginBootstrap类, 然后在main函数中实例化当前引导类,并执行run方法即可。

配置Maven打包插件 | Maven

其实这一步工作我已经在上面提到了,也就是在引入依赖部分提供了。

<!--    =================插件打包的配置===================-->
    <build>
        <plugins>
            <plugin>
                <groupId>com.gitee.starblues</groupId>
                <artifactId>spring-brick-maven-packager</artifactId>
                <version>3.1.0</version>
                <configuration>
                    <!--当前打包模式为: 开发模式-->
                    <mode>dev</mode>
                    <!--插件信息定义-->
                    <pluginInfo>
                        <!--插件id-->
                        <id>example-plugins-basic</id>
                        <!--插件入口类, 定义说明见: 定义插件入口类-->
                        <bootstrapClass>com.linghu.controller.ExamplePlugin</bootstrapClass>
                        <!--插件版本号-->
                        <version>1.0.0-SNAPSHOT</version>
                    </pluginInfo>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

新增Controller接口API | API

其实这个接口我们就加在插件程序里就行了

package com.linghu.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author linghu
 * @date 2024/3/15 9:58
 */

@RestController
@RequestMapping("/example")
public class ExampleController {
    @GetMapping
    public String hello(){
        return "hello";
    }
}

注意一下Controller位置,放错了很容易导致后续Controller加载不到主程序的:

image-20240315163409936

编译打包插件 | JAR

这里打包有两种方法:

  • 插件使用maven命令:mvn clean package进行编译
  • 通过Maven插件、先点击clean、在点击package

我用的第二种方法打包,如图:

image-20240315163849557

打包完成以后,观察target文件下会出现jar包:

image-20240315163925679

启动测试 | Main

这个测试是直接启动主程序的

  • 启动主程序main, 日志中出现如下关键内容,说明集成插件成功

image-20240315164322248

image-20240315164443221

如上我们还知道了如下信息,那就是我们请求测试的接口地址为:

http://127.0.0.1:8080/plugins/example-plugins-basic/

打开浏览器,访问: http://127.0.0.1:8080/plugins/example-plugins-basic/example出现下图说明访问接口测试成功。

image-20240315164521738

Demo案例Git地址 | Gitee

这个教程属于入门级别的,没有对源码,原理展开讲解,后续有时间会接着更的,这里主要是教大家快速上手,遇到不懂的,欢迎评论区提出。

完整项目demo:

《SpringBrick-springboot-plugin-framework-example-linghu》

项目下载以后记得要用Maven插件打一下jar包,可以直接运行:

mvn clean package进行编译~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1519278.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从混沌到秩序——90年代中国数据库的激烈角逐

引言 在数字化浪潮的推动下&#xff0c;数据库技术已成为支撑数字经济的坚实基石。腾讯云TVP《技术指针》联合《明说三人行》特别策划的直播系列——【中国数据库前世今生】&#xff0c;我们将通过五期直播&#xff0c;带您穿越五个十年&#xff0c;深入探讨每个时代的数据库演…

Android NDK入门:在应用中加入C和C++的力量

目录 ​编辑 引 NDK的设计目的 与Java/Kotlin的结合 使用场景 开发流程 设置项目以支持NDK 编写本地代码 使用JNI连接本地代码和Java/Kotlin代码 编译和运行你的应用 附 引 自诩方向是android方向的移动端开发工程师&#xff0c;却从来没有真正仔细了解过NDK&#…

【LeetCode热题100】24. 两两交换链表中的节点(链表)

一.题目要求 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09;。 二.题目难度 中等 三.输入样例 示例 1&#xff1a; 输入&am…

AI视频批量混剪系统|罐头鱼AI视频矩阵获客

AI视频批量混剪系统助您轻松管理和编辑视频素材 如今&#xff0c;视频营销已成为企业推广的重要方式。为了满足用户对视频管理、发布和编辑的需求&#xff0c;《罐头鱼AI视频批量混剪系统》应运而生。这款智能化系统集成了多种功能&#xff0c;助您轻松管理和发布精彩视频内容…

JavaScript 之 获取当前日期的周日期范围、月日期范围

前言 实际开发中&#xff0c;有的时候产品要求需要用到日期筛选&#xff0c;日期筛选又需要用的当前日期的周日期范围&#xff0c;也有可能上一周&#xff0c;下一周这样的&#xff0c;相对应的也就又可能是当前日期的月日期范围&#xff0c;上一个月、下一个月的这样的&#x…

[NSSRound#18 Basic]web解析

文章目录 门酱想玩什么呢&#xff1f;Becomeroot 门酱想玩什么呢&#xff1f; 打开题目&#xff0c;加载完视频后要求我们给个游戏链接 点开评论区不难发现应该是想玩元梦之星&#xff0c;这里有个评论功能可以上传图片 我们随便输入点东西发现是插入并赋值到content元素里面 …

识别恶意IP地址的有效方法

在互联网的环境中&#xff0c;恶意IP地址可能会对网络安全造成严重威胁&#xff0c;例如发起网络攻击、传播恶意软件等。因此&#xff0c;识别恶意IP地址是保护网络安全的重要一环。IP数据云将探讨一些有效的方法来识别恶意IP地址。 IP地址查询&#xff1a;https://www.ipdata…

计算机毕业设计项目基于大数据和ALS算法实现的房源智能推荐系统

概要 目前&#xff0c;现有的房源信息不够透明化大多中介混淆市场&#xff0c;内含不为人知的商业链。有经验的租客们会通过周边房价走势和走访周边房源对比调研、筛选适合自己的房源。 同时&#xff0c;对于用户工作地点需求和各种人群类型如大学生群体&#xff0c;年轻小资&a…

单⽬相机成像过程_看这一篇就够了

单⽬相机成像过程:看这一篇就够了 附赠宝贵的全套自动驾驶学习资料&#xff1a; 资料链接 附赠宝贵的全套自动驾驶学习资料&#xff1a; 资料链接

【LeetCode热题100】54. 螺旋矩阵

一.题目要求 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 二.题目难度 中等 三.输入样例 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[1,2,3,6,9,8,7,4,5] 示例…

04-java基础--流程控制语句

一、switch语句 二、循环的三种结构 流程控制语句分为三种结构&#xff1a; 顺序结构&#xff08;按代码的书写顺序执行&#xff0c;从上到下依次执行&#xff09;分支结构&#xff08;if语句、if–else语句、switch语句&#xff09;循环结构&#xff08;while、for循环、do–…

Java 设计模式系列:行为型-观察者模式

简介 观察者模式是一种行为型设计模式&#xff0c;又被称为发布-订阅&#xff08;Publish/Subscribe&#xff09;模式&#xff0c;它定义了对象之间的一对多依赖关系&#xff0c;当一个对象的状态发生改变时&#xff0c;所有依赖于它的对象都会得到通知并被自动更新。 观察者…

七月论文审稿GPT第3.2版和第3.5版:通过paper-review数据集分别微调Mistral、gemma

前言 我司第二项目组一直在迭代论文审稿GPT(对应的第二项目组成员除我之外&#xff0c;包括&#xff1a;阿荀、阿李、鸿飞、文弱等人)&#xff0c;比如 七月论文审稿GPT第1版&#xff1a;通过3万多篇paper和10多万的review数据微调RWKV七月论文审稿GPT第2版&#xff1a;用一万…

wps珠海市政府版本

功能 无广告&#xff0c;安装直接使用&#xff0c;word,excel,ppt功能齐全 步骤 双击exe文件&#xff0c;更改安装步骤即可&#xff0c;任意选择一个部门就可以了 获取资源 链接&#xff1a;https://pan.baidu.com/s/1IVfNVgLwsp5QBT2uX-yROQ?pwdme6f 提取码&#xff1a;me…

上传图片时系统提示尺寸太大无法上传?证件照怎么改kb大小?

大家好&#xff0c;相信大家网上因为各式各样的原因上传证件照的时候&#xff0c;总是会提示尺寸过大或尺寸不符合等情况&#xff0c;例如教师资格证的照片要求是&#xff1b;格式为jpg/jpeg&#xff0c;不大于200K&#xff0c;宽高为150*200像素&#xff0c;比例约为3:4。怎么…

Android 监听卫星导航系统状态及卫星测量数据变化

源码 package com.android.circlescalebar;import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; import android.Manifest; import android.conte…

利用数据驱动的MEG分析方法提取fMRI静息态网络

摘要 静息态网络(RSN)的电生理基础仍存在争议。特别是&#xff0c;尚未确定一个能够同样有效解释所有静息态网络的原理性机制。虽然脑磁图(MEG)和脑电图(EEG)是确定RSN电生理基础的首选方法&#xff0c;但目前没有标准的RSN分析流程。本文比较了从MEG数据中提取RSNs的两种现有…

跨境热点!TikTok直播网络要求是什么?

TikTok直播作为一种互动性强、实时性要求高的社交媒体形式&#xff0c;对网络环境有着一系列特定的需求。了解并满足这些需求&#xff0c;对于确保用户体验、提高直播质量至关重要。本文将深入探讨TikTok直播对网络环境的要求以及如何优化网络设置以满足这些要求。 TikTok直播的…

git小白入门

git是什么 Git是一种流行的版本控制系统&#xff0c;被广泛用于软件开发中来跟踪和管理代码的变化。它是由Linus Torvalds在2005年创建的&#xff0c;最初的目的是为了更高效地管理Linux内核的开发。Git使得多人在同一个项目上工作变得更加简单&#xff0c;可以轻松合并不同开…

跨域问题经典解决方法

这里写目录标题 背景步骤m3u8文件是什么&#xff1f;&#xff1f;本地播放m3u8文件在浏览器上播放m3u8视频跨域问题什么是跨域问题&#xff1f;为什么有跨域问题&#xff1f;如何解决跨域问题&#xff1f;使用代理服务器CORS&#xff08;跨域资源共享&#xff09; 总结 背景 同…