插件开发
本文是 1.x 的归档文档(冻结于 1.x)。该分支只接收勘误修正, 内容基本不再变动;文中的源码路径、配置项与版本号均以 1.x 为准,不建议用于新项目。
新项目请查看 5.x 最新文档。已在 1.x 上运行的项目,本文仍是可靠依据。
在 Wujies 无界平台上,一个业务应用就是一个插件。 平台本身不包含业务代码,只负责把插件装进来、跑起来、卸下去。
这一章从「新建一个插件」讲到「打出一个能安装的包」。读完之后,你应该能独立完成: 新建骨架 → 写后端 → 写页面 → 热加载调试 → 打包发布。
为什么是插件
- 平台极小,应用外置。 新增业务模块不需要改平台一行 Java 代码,也不需要在平台里新建
*-api契约模块。 - 一个应用就是一个自包含工程。 实体、Mapper、Service、Controller、建表脚本、
app.json、前端页面, 全在插件仓库自己的目录里。 - 运行期装载。 宿主用独立的
PluginClassLoader和子 Spring 上下文加载插件,支持热加载与卸载; 装卸全程不重启宿主。
一个插件由四部分组成
wujies/wujies-plugins/
├── wujies-demo/ ① 后端工程(Maven 模块)
│ ├── app.json ② 应用清单:编码、版本、产物、菜单
│ ├── migrations/ ③ 数据库迁移:建表 / 种子数据
│ │ └── 01-create-demo-item.sql
│ └── src/main/java/cn/wujies/demo/
│ ├── controller/ HTTP 接口,挂在 /demo/**
│ ├── domain/ + bo/ + vo/ 实体与出入参
│ ├── mapper/ Mapper 接口(XML 随 jar 走)
│ └── service/ + impl/ 业务逻辑
└── frontend/demo-app/ ④ 前端远程应用(pnpm 工程)
├── vite.config.ts defineRemoteApp({ appCode: 'demo' })
├── app.json 前端侧清单(构建用;菜单以 ② 为准)
└── src/
├── index.ts 入口契约:install(runtime) → { manifest, views }
└── views/ 页面组件| 部分 | 事实来源 | 说明 |
|---|---|---|
| 后端 | wujies-<code>/pom.xml | 依赖平台构件时一律 provided,不要打进 jar |
| 清单 | wujies-<code>/app.json | 版本、产物路径、菜单与权限的唯一权威描述 |
| 迁移 | wujies-<code>/migrations/*.sql | 文件名排序即执行顺序,已执行的脚本不要修改 |
| 前端 | frontend/<code>-app/src/index.ts | 构建成 ESM,由宿主在运行期 import() |
命名只有一条规则:目录名、app.json.code、vite.config.ts 的 appCode、菜单里的
remote:<code>/<viewKey>,四处必须是同一个 <code>。
从零到可安装:五步
| # | 做什么 | 从哪开始 |
|---|---|---|
| 1 | 新建插件骨架(后端 + 前端 + 清单 + 迁移) | 可视化开发台 或 new-plugin.ps1 |
| 2 | 补业务:改实体、接口、迁移脚本 | 后端工程 · 数据库迁移 |
| 3 | 写页面:在 views/ 下加 Vue 页面,登记视图键 | 前端远程应用 |
| 4 | 联调:后端热加载、前端重建产物 | 快速开始 · 本地联调 |
| 5 | 打包:开发包用于联调,正式包用于上架 | 打包应用 |
POST /app/dev/reload 只替换后端代码。它不建表、不同步菜单、不部署前端产物。
新插件的表、菜单、权限和前端入口,第一次仍需走一次安装(安装 会执行 migrations/ 并写入
app.json 里的菜单)。装过一次之后,日常迭代就只剩「构建 → 热加载 → 刷新」。
详见开发与安装的边界。
三种创建方式
方式一:可视化开发台(推荐)
宿主后台 「应用上架 → 插件开发」 里点「新建插件」,填编码、名称、版本即可。
服务端会调用插件仓库的 scripts/new-plugin.mjs,自动完成:复制模板、改包名 / 类名 / 表名 /
权限前缀、写 app.json、把模块登记进仓库根 pom.xml。
适合第一次接触、或者不想记命令的人。见可视化开发台。
方式二:命令行
在插件仓库根执行:
# 生成前后端完整骨架
powershell -File new-plugin.ps1 -Code demo -Name "演示应用"
# 只要后端
powershell -File new-plugin.ps1 -Code demo -Name "演示应用" -NoFrontend生成后的下一步、构建命令和目录说明会直接打印在终端里。
方式三:复制 hello 模板
想照着现成代码改,就把 wujies-hello 复制成 wujies-<code>,再改四处:
pom.xml 的 artifactId、app.json 的 code/name/version/menus、Java 包名、表名前缀。
这条路的对照索引见跟着 hello 读源码。
三种方式产物结构一致。不要从业务插件(mall / im / exam)复制——它们带了很多历史包袱, 新应用用
hello或生成器即可。
日常开发循环
| 改了什么 | 怎么做 | 怎么生效 | 耗时 |
|---|---|---|---|
| 后端 Java | mvn -pl wujies-<code> -am package -DskipTests | 开发台「热加载」或 POST /app/dev/reload | 秒级 |
| 前端 Vue | 构建到宿主 app-market-dist/remote-apps/<code>/ | 刷新浏览器 | 秒级 |
| 表结构 | 新增 migrations/NN-*.sql | 安装 / 升级时执行;开发期可手动执行一次 | 分钟级 |
| 菜单 / 权限 | 改 app.json 的 menus | 安装 / 升级时同步;热加载不碰菜单 | 分钟级 |
| 版本 / 产物路径 | 改 app.json | 重新打包 | 分钟级 |
热加载只对开了 dev-mode 的宿主可用,并且绕过签名与包校验。它解决的是「改一行代码不想重新上架」,
不是「第一次怎么装」。完整的四条联调路径见本地开发与联调方案。
先记住四条
- 平台依赖一律
provided。 Spring、MyBatis、wujies-common-*、兄弟插件构件都不要打进插件 jar, 否则会出现同一个接口两个 Class 对象。 - 菜单只能写在
app.json里。 不要手写INSERT INTO sys_menu;type: "F"的按钮也必须声明。 见菜单与权限。 - 迁移脚本只增不改。 文件名排序即执行顺序,必须幂等;执行过的脚本内容再改会被摘要校验拒绝。 见数据库迁移。
- 宿主看不到插件。 插件能注入宿主,宿主不能注入插件;宿主侧要用插件能力只能走 SPI 或服务定位器。
其余不能违反的细节,见必须遵守的不变量。
本章地图
| 我想… | 看这里 |
|---|---|
| 10 分钟做出第一个插件 | 快速开始 |
| 用后台页面新建、热加载、打开发包 | 可视化开发台 |
搞清 app.json 每个字段 | 应用清单 app.json |
| 写后端工程 | 后端工程 |
| 写前端页面并构建成 ESM | 前端远程应用 |
| 声明菜单与按钮权限 | 菜单与权限 |
| 加表 / 改表 / 种子数据 | 数据库迁移 · 种子数据与站点配置 |
| 本地跑起来、打断点 | 本地联调 |
| 不想每次改一行就打包上传 | 本地开发与联调方案 |
| 照着真实源码写 | 跟着 hello 读源码 |
| 查某个能力怎么调 | 插件能力速查 |
| 把宿主模块抽成插件 | 从宿主模块抽成应用 |
| 打包、签名、上架 | 打包应用 · 密钥与签名 |