EasyPostman 插件开发、更新与发布指南
June 1, 2026 · View on GitHub
这份文档面向两类人:
- 想看懂当前插件机制是怎么工作的维护者
- 正在开发、更新、发布插件的开发者
如果你只关心一句话,可以先记住这 4 点:
- 插件是单独的 JAR,不和宿主一起绑死发版
- 插件元数据的单一真源是各插件自己的
pom.xml - GitHub Actions 只负责读取产物、校验一致性、发布和回写 catalog
- 本地验证优先走“构建插件 JAR -> 插件管理安装 -> 重启验证”这条路径
如果你当前更想看 runtime 内核实现,而不是开发/发布流程,可以直接先读:
1. 组件分层和原理
当前插件体系分成 7 层:
easy-postman-parent
├── easy-postman-plugin-api
├── easy-postman-foundation
├── easy-postman-platform
├── easy-postman-ui
├── easy-postman-plugin-runtime
├── easy-postman-app
└── easy-postman-plugins
├── plugin-manager
├── plugin-client-cert
├── plugin-capture
├── plugin-redis
├── plugin-kafka
└── plugin-decompiler
1.1 每层负责什么
easy-postman-plugin-api- 插件对宿主暴露的稳定 SPI
- 包含
EasyPostmanPlugin、PluginContext、PluginDescriptor - 插件服务契约也放在这里,例如
GitPluginService、ClientCertificatePluginService、RequestCollectionImportService - 新插件的入口类必须实现这里的接口
easy-postman-foundation- 宿主和插件共享的基础工具、消息 key、公共模型
- 插件需要和宿主共享非 UI DTO、enum、常量、路径、JSON、系统、设置工具或通用解析/格式化工具时,优先放这里
easy-postman-platform- 宿主平台框架能力,例如 IOC 和更新发现核心
- 不是普通插件 SPI;插件需要扩展宿主时仍应优先依赖
easy-postman-plugin-api
easy-postman-ui- 插件和宿主公用的 UI 基础组件和视觉常量
- 插件面板如果需要复用统一 UI 风格、按钮、搜索框、表格或基础输入控件,优先依赖这一层
easy-postman-plugin-runtime- 负责扫描、读取 descriptor、版本兼容校验、类加载、生命周期调用、扩展点注册和 registry
- 可以把它理解成插件运行时内核
easy-postman-app- 宿主应用本身
- 从 runtime 和 registry 里消费插件注册出来的能力
easy-postman-plugins- 通常是官方插件 JAR 集合
plugin-client-cert、plugin-capture、plugin-redis、plugin-kafka、plugin-decompiler这类plugin-*是普通运行时插件plugin-manager是例外:它是宿主 app 直接依赖的宿主侧插件管理辅助模块,负责 catalog 解析、在线/离线安装门面和安装来源记录,不是 runtime 扫描加载的普通插件
1.2 插件是怎么被宿主加载的
真实运行链路大致是:
本地 JAR / 远程 catalog
-> plugin-manager 负责安装和下载
-> 安装版插件 JAR 进入数据目录下的 plugins/installed 和 plugins/packages
-> 便携版默认写入程序根目录下的 plugins 和 plugins/packages,方便离线拷贝
-> runtime 扫描插件目录
-> 读取 META-INF/easy-postman/*.properties
-> 解析 PluginDescriptor
-> 校验 app 版本 + platform 版本兼容性
-> 为每个插件创建独立 URLClassLoader
-> 反射创建 entryClass
-> 调用 onLoad(context)
-> 插件向 registry 注册脚本 API / Toolbox / 补全 / Snippet / Service
-> 宿主消费这些能力
关键点:
- 插件不是直接依赖宿主内部实现,而是通过
PluginContext声明能力 - 插件之间不共享类加载器,避免依赖冲突污染宿主
easy-postman-plugin-runtime负责插件扫描、加载、生命周期和 registry;plugin-manager只负责安装/catalog 侧的宿主辅助能力- 普通插件不得依赖
easy-postman-app;宿主 app 可以依赖easy-postman-plugins/plugin-manager这个目录特例 - 同一
plugin.id存在多个版本时,运行时只会选择最高版本加载 - 安装阶段就会做兼容性拦截,避免出现“安装成功但运行时跳过”的假成功状态
1.3 插件能扩展哪些能力
当前 PluginContext 支持这几类扩展点:
registerScriptApi- 给脚本环境暴露
pm.plugin("xxx")
- 给脚本环境暴露
registerService- 给宿主侧访问层按类型取服务
registerToolboxContribution- 往 Toolbox 增加面板
registerScriptCompletionContributor- 给脚本编辑器增加自动补全
registerSnippet- 增加脚本片段
以 plugin-kafka 为例,KafkaPlugin 在 onLoad 里一次性注册了:
pm.plugin("kafka")- Kafka Toolbox 面板
- Kafka 相关脚本补全
- Kafka 示例片段
也就是说,插件入口类的职责不是“自己跑业务逻辑”,而是“在加载时把能力挂到宿主上”。
2. 版本模型和兼容性
2.1 为什么要区分 app 和 platform
当前体系里有两种版本边界:
app version- 宿主 EasyPostman 的发行版版本
- 例如
5.3.16
plugin platform version- 插件 SPI / 运行时装配边界版本
- 当前由根
pom.xml里的plugin.platform.version管理
简单理解:
platform管“这套插件接口还能不能接上”app管“当前宿主有没有插件依赖的具体功能”
再细一点说:
- 根
pom.xml里的revision- 是宿主发行版版本
- 会随着宿主正常发版、补丁、非插件改动持续递增
- 插件
pom.xml里的host.version- 默认跟随
${revision} - 作用只是“编译时依赖哪一版宿主平台包”
- 默认跟随
- 根
pom.xml里的plugin.platform.version- 是运行时插件平台版本
- 作用是表达“当前 runtime / SPI 装配边界有没有发生不兼容变化”
为什么 plugin.min/maxPlatformVersion 不能直接写 ${revision}:
revision变化太频繁,很多变化和插件 SPI 无关- 如果把 platform 兼容范围直接绑到
revision,会把很多其实还能加载的老插件误判成“不兼容” - 所以必须把“宿主发版节奏”和“插件平台兼容边界”拆成两个版本概念分别维护
2.2 什么时候改 platform version
只有插件机制本身发生不兼容变化时,才应该提升 plugin.platform.version,例如:
PluginContext有不兼容修改PluginDescriptor语义发生破坏性变化- runtime 的装配方式变了,老插件会失效
- 某类扩展点契约被替换
如果只是:
- 宿主修了一个普通 bug
- 宿主发了一个补丁版本
- 某个插件自己新增功能
通常都不应该 bump plugin.platform.version。
2.3 什么时候加 min/maxAppVersion
只有插件确实依赖某个宿主能力时,才建议加:
- 宿主新增了一个插件要调用的 API/service
- 宿主某个 UI 容器、入口或事件只在新版本存在
- 插件明确不支持某个老宿主版本
如果插件只是普通扩展,通常只写 min/maxPlatformVersion 就够了。
2.4 当前 descriptor 和 catalog 的关系
当前规则是:
- 插件自己的
pom.xml维护元数据 - Maven 过滤生成
META-INF/easy-postman/*.properties - GitHub Actions 从构建好的 JAR 里读取 descriptor
- workflow 再把 descriptor 内容同步回
catalog.json
所以真正的顺序是:
pom.xml -> descriptor -> release asset -> catalog
不是:
workflow 手写字段 -> catalog -> 再反推插件
这能避免多处手填导致漂移。
3. 开发一个新插件应该怎么做
下面按当前仓库的真实做法给出最短路径。
3.1 新建模块
普通官方插件建议在 easy-postman-plugins/ 下新建:
easy-postman-plugins/plugin-xxx
├── pom.xml
├── src/main/java
└── src/main/resources/META-INF/easy-postman/plugin-xxx.properties
然后把模块加入聚合构建。
不要把 easy-postman-plugins/plugin-manager 当作普通插件模板。它留在 easy-postman-plugins 下是历史路径和发布组织选择;新的宿主侧插件管理库不应默认继续放到 easy-postman-plugins/*,后续可迁到更清晰的模块名或目录。
3.2 写插件 pom.xml
推荐直接参考现有官方插件,例如:
easy-postman-plugins/plugin-capture/pom.xmleasy-postman-plugins/plugin-kafka/pom.xmleasy-postman-plugins/plugin-redis/pom.xml
至少要有这些字段:
<version>5.3.16</version>
<artifactId>easy-postman-plugin-xxx</artifactId>
<properties>
<host.version>${revision}</host.version>
<plugin.id>plugin-xxx</plugin.id>
<plugin.name>XXX Plugin</plugin.name>
<plugin.entryClass>com.laker.postman.plugin.xxx.XxxPlugin</plugin.entryClass>
<plugin.description>...</plugin.description>
<plugin.minPlatformVersion>${plugin.platform.version}</plugin.minPlatformVersion>
<plugin.maxPlatformVersion>${plugin.platform.version}</plugin.maxPlatformVersion>
</properties>
说明:
host.version- 编译时依赖哪一版宿主平台包
- 官方插件默认跟随
${revision},这样能直接对齐当前api / foundation / ui的编译输入 - 如果只是宿主正常发版,这里跟随即可;它不负责表达运行兼容范围
plugin.id- 插件唯一 ID
- 发布、安装、升级都靠它识别
plugin.entryClass- 插件入口类
plugin.min/maxPlatformVersion- 当前官方插件默认都绑定到根
pom.xml的plugin.platform.version - 它表达的是运行时插件平台兼容范围,不是宿主发行版号
- 只有插件机制本身发生破坏性变化时才应该调整
- 当前官方插件默认都绑定到根
如果你发现“版本不合适”,按下面判断:
- 编译不过,因为插件要依赖新的宿主
api / foundation / ui- 调整或跟随
host.version
- 调整或跟随
- 运行时老宿主缺少插件依赖的新功能
- 增加或调整
plugin.minAppVersion
- 增加或调整
- runtime / SPI 契约变了,老插件会装配失败
- 先提升根
pom.xml的plugin.platform.version - 再调整插件的
plugin.min/maxPlatformVersion
- 先提升根
- 只是插件自己改了功能或修了 bug
- 通常只改插件自己的
<version>
- 通常只改插件自己的
如果插件确实依赖宿主特定功能,可以额外加:
<plugin.minAppVersion>5.3.16</plugin.minAppVersion>
<plugin.maxAppVersion>5.4.0</plugin.maxAppVersion>
但要注意,当前官方 descriptor 模板默认没有把这两个字段写进去;你需要同时更新 descriptor 模板。
3.3 写 descriptor 模板
示例:
plugin.id=${plugin.id}
plugin.name=${plugin.name}
plugin.version=${project.version}
plugin.entryClass=${plugin.entryClass}
plugin.description=${plugin.description}
plugin.homepage=${plugin.homepage}
plugin.minPlatformVersion=${plugin.minPlatformVersion}
plugin.maxPlatformVersion=${plugin.maxPlatformVersion}
如果你要使用 minAppVersion / maxAppVersion,记得把它们也加进模板。
当前设计原则是:
- descriptor 是构建产物的一部分
- descriptor 的真实值来自
pom.xml - 不要在 descriptor 里手工写死版本和兼容范围
3.4 写入口类
入口类必须实现 EasyPostmanPlugin:
public class XxxPlugin implements EasyPostmanPlugin {
@Override
public void onLoad(PluginContext context) {
// 注册扩展点
}
}
常见模式:
context.registerScriptApi("xxx", ScriptXxxApi::new);
context.registerToolboxContribution(...);
context.registerScriptCompletionContributor(...);
context.registerSnippet(...);
建议:
onLoad- 只做注册,不做重量级初始化
onStart- 放真正需要启动时执行的逻辑
onStop- 做资源释放
3.5 依赖应该怎么选
优先规则:
- 插件契约依赖
easy-postman-plugin-api - 共享非 UI 基础类型和工具依赖
easy-postman-foundation - 共享 Swing 组件、字体、图标、颜色和通知 UI 依赖
easy-postman-ui - 不要直接反向依赖
easy-postman-app内部类 - 第三方库如果插件自身需要,跟随插件一起打进插件 JAR
- 宿主已经提供、且插件只需要编译期引用的依赖,优先用
provided
3.6 新插件开发 checklist
建议按这个清单走:
- 新建
plugin-xxx模块 - 配好
pom.xml - 写 descriptor 模板
- 写入口类并实现
EasyPostmanPlugin - 注册需要的扩展点
- 本地打包生成 JAR
- 本地安装验证
- 补测试
- 再走 GitHub 发布
4. 更新一个已有插件应该怎么做
更新已有插件,优先回答这 3 个问题:
- 这次是插件自己的功能更新,还是平台兼容边界变化
- 需要不需要提升插件版本
- 需不需要调整 app/platform 兼容范围
4.1 最常见的更新:插件功能更新
如果只是:
- 新增一个脚本 API 方法
- 新增一个 Toolbox 功能
- 修插件自己的 bug
- 调整插件自己的 UI
通常只需要:
- 修改
plugin-xxx代码 - 提升该插件自己的
<version> - 重新构建和验证
一般不需要改:
- 宿主
revision plugin.platform.version
4.2 需要调整兼容范围的更新
如果插件依赖了新的宿主能力:
- 在插件
pom.xml里新增或调整plugin.minAppVersion - 在 descriptor 模板里同步加上
plugin.minAppVersion - 本地验证老版本宿主确实不再适配
如果是插件平台 SPI 变了:
- 先提升根
pom.xml里的plugin.platform.version - 再更新受影响插件的
plugin.min/maxPlatformVersion - 验证旧插件被正确判为不兼容
不要因为下面这些情况去改 plugin.platform.version:
- 宿主
revision从5.3.16升到5.3.17 - 宿主修了普通 bug,但插件 SPI 没变
- 某个插件自己新增了一个工具面板或脚本 API
4.3 更新已有插件的推荐顺序
改代码
-> 决定是否 bump 插件版本
-> 决定是否修改 min/maxAppVersion
-> 决定是否修改 min/maxPlatformVersion
-> 本地构建
-> 本地安装验证
-> dry run 发布
-> 正式发布
5. 在 GitHub 发布插件应该怎么做
当前官方插件独立发版走:
.github/workflows/plugin-release.yml
5.1 正式发布前你要先改什么
至少确认下面几件事:
- 目标插件的
pom.xml版本已经提升 - descriptor 模板字段齐全
- 本地构建通过
- 本地验证通过
- 如果涉及兼容性变化,
min/maxAppVersion或min/maxPlatformVersion已正确更新
5.2 workflow 会做什么
这个 workflow 当前会做:
- 只构建你选中的插件模块
- 产出单插件 JAR
- 计算 JAR 的
sha256 - 从 JAR 内的 descriptor 读取插件元数据
- 校验
plugin id / version / tag一致性 - 发布 GitHub Release
- 可选发布 Gitee Release
- 可选更新 GitHub / Gitee catalog
5.3 workflow 的关键约束
当前正式发版有这几个规则:
- 正式发版只能从默认分支触发
- 非
dry_run情况下,官方 GitHub catalog 必须一起更新 - workflow 不再自己维护兼容字段,而是从 JAR descriptor 读取
5.4 推荐发布步骤
建议每次都按这个顺序:
- 本地改完代码和版本
- 本地构建并验证
- 在 GitHub Actions 手动触发
plugin-release.yml - 先跑一次
dry_run=true - 确认产物、descriptor、版本都对
- 再跑正式发布
5.5 workflow_dispatch 参数怎么选
你通常只需要关心这些输入:
plugin- 选择要发布的插件,例如
capture、kafka
- 选择要发布的插件,例如
dry_run- 建议先
true
- 建议先
publish_gitee_release- 是否同步 Gitee Release
update_github_catalog- 是否回写 GitHub catalog
update_gitee_catalog- 是否回写 Gitee catalog
release_notes- 可选
5.6 发布后会得到什么
正式发布后,通常会得到:
- 一个单插件 JAR 附件
- 一个
.sha256.txt文件 - 一条 GitHub Release
- 更新后的
plugin-catalog/catalog-github.json - 如开启 Gitee,同步得到对应 Gitee Release 和 catalog 更新
6. 本地怎么验证
本地验证建议分成 4 层,不要只做编译通过。
6.1 第一层:构建通过
构建单个插件:
mvn -pl easy-postman-plugins/plugin-kafka -am clean package -DskipTests
构建多个插件:
mvn -pl easy-postman-plugins/plugin-kafka,easy-postman-plugins/plugin-redis -am clean package -DskipTests
6.2 第二层:检查 descriptor 是否正确
至少检查两处:
- 构建输出目录
easy-postman-plugins/plugin-kafka/target/classes/META-INF/easy-postman/plugin-kafka.properties
- 最终 JAR 内的 descriptor
你需要确认:
plugin.idplugin.versionplugin.entryClassplugin.descriptionplugin.min/maxPlatformVersion- 如有需要,
plugin.min/maxAppVersion
这一层的目标是确认:
pom.xml-> descriptor 模板 -> 构建产物 没有漂移
6.3 第三层:安装验证
最推荐的本地验证方式:
- 打开 EasyPostman
- 进入插件管理
- 选择“安装本地 JAR”
- 选中刚打出来的插件 JAR
- 重启应用
- 验证插件能力是否真的出现
按插件类型,至少要检查:
- Toolbox 面板是否出现
pm.xxx是否可用- 脚本补全是否出现
- Snippet 是否出现
- 禁用 / 启用 / 卸载后状态是否正确
6.4 第四层:兼容性验证
如果这次改动涉及兼容范围,建议专门验证:
- 不兼容插件在安装阶段是否被拦截
- 兼容插件是否能正常安装和加载
- 插件管理界面的兼容文案是否符合预期
- 市场列表里的安装按钮是否被正确禁用或允许
6.5 可选:开发期扫描目录
当前还支持一个开发期附加扫描目录:
-DeasyPostman.plugins.dir=/your/path
它适合:
- 调试额外插件目录
- 企业预置插件目录验证
但对单插件开发来说,最稳定的验证路径仍然是“构建 JAR 后通过插件管理安装”。
7. 用户安装和分发方式
虽然这份文档更偏开发者,但用户安装方式最好也统一理解。
当前对用户只保留 2 条路径:
- 本地安装
- 直接安装单个插件 JAR
- 在线安装
- 通过远程
catalog.json加载并安装
- 通过远程
当前官方 catalog:
- GitHub
https://raw.githubusercontent.com/lakernote/easy-postman/master/plugin-catalog/catalog-github.json
- Gitee
https://gitee.com/lakernote/easy-postman/raw/master/plugin-catalog/catalog-gitee.json
7.1 为什么本地和在线都保留
因为两者解决的是不同问题:
- 本地 JAR
- 适合开发联调、手工分发、最低心智成本安装
- 在线 catalog
- 适合长期维护、官方分发、团队内网插件源
7.2 当前目录结构的意义
用户机器上默认会看到两个目录:
EasyPostman/plugins/installed/EasyPostman/plugins/packages/
含义:
installed/- 当前用于实际加载的副本
packages/- 保留包副本
- 为重装、升级和某些文件锁场景做缓冲
8. 常见问题
Q1:开发一个插件,最少要写哪些文件
至少这些:
plugin-xxx/pom.xmlsrc/main/java/.../XxxPlugin.javasrc/main/resources/META-INF/easy-postman/plugin-xxx.properties
如果插件有 UI 或脚本 API,再加对应类。
Q2:更新插件一定要改宿主版本吗
不一定,通常不用。
大多数情况下:
- 只改插件代码
- 只提升插件自己的
<version>
只有插件机制本身发生不兼容变化时,才需要改 plugin.platform.version。
Q3:为什么 GitHub Actions 不直接维护兼容性字段
因为兼容性定义应该属于插件自己,而不是 workflow。
当前正确的数据流是:
- 插件
pom.xml定义元数据 - Maven 生成 descriptor
- workflow 从 JAR descriptor 读取并校验
- workflow 更新 catalog
这样不容易出现多处手填漂移。
Q4:本地验证为什么不推荐直接手拷文件
因为插件管理这条路径会顺带验证:
- JAR 是否有效
- descriptor 是否可读
- 兼容性是否满足
- 安装来源是否被记录
这比手工复制更接近真实用户路径。
Q5:我应该如何描述这套插件体系
推荐统一成一句话:
EasyPostman 的插件以单 JAR 为交付单元,通过稳定的插件 API、独立的插件运行时和远程 catalog 机制,实现独立开发、独立升级和独立发布。