Wujies 无界平台
平台功能(自研)应用生态

示例应用

hello 是平台唯一的示例应用,在 wujies/wujies-plugins/wujies-hello/。 它的用途不是提供业务功能,而是一次安装就看完整条链路: 后端接口、开放接口、定时任务、跨应用依赖、前端远程产物、共享 Vue / Element Plus 单例。

早期的示例是一个纯前端远程应用 demo-app。它已经从应用目录里去掉 —— 生成器(deploy/tools/gen-app-catalog-sql.mjs 的 EXCLUDED_APPS)不再分发它, 存量部署跑 script/sql/update/app_market_demo_app_remove.sql 清理, 示例应用的位置由 hello 独占。

它为什么存在

在把真实业务模块抽成插件之前,先用最小的一份产物验证:

  • @RestController 路由是否被注册(PluginHandlerMapping);
  • Mapper 能否从插件里加载(含无 XML、只用内置方法的 Mapper);
  • @Scheduled 与 SnailJob 两类定时任务是否注册;
  • 前端远程产物能不能被运行期 import() 起来;
  • 共享依赖(Vue / Element Plus)是不是同一份实例;
  • 应用之间的依赖怎么声明、没装时怎么被拦住。

仓库里还有两个同类的对照物:后端探针模块(不得被启动模块依赖)与图床、财务等真实应用。 hello 与它们的分工见 跟着 hello 读源码。

它长什么样

wujies/wujies-plugins/
├── wujies-hello/                 后端插件(自包含:实体 / Mapper / Service 都在这里)
│   ├── app.json                  ★ 清单:唯一真相来源(编码 / 菜单树 / 产物路径 / dependencies)
│   ├── pom.xml                   平台依赖一律 provided
│   ├── migrations/               建表 + 种子数据 + 站点配置,随包执行
│   └── src/main/java/cn/wujies/hello/
│       ├── controller/           探针、宿主调用、跨插件调用(import 了 member)
│       ├── open/                 /open 开放接口
│       └── task/                 @Scheduled 与 SnailJob 两种定时任务
└── frontend/hello-app/           前端工程(与插件模块只差一个 `-app` 后缀)
    ├── app.json                  清单的近重复副本:改清单时**两份一起改**
    ├── vite.config.ts            defineRemoteApp({ appCode: 'hello' })
    └── src/
        ├── index.ts              install(runtime) + 视图键
        ├── runtime.ts            宿主运行时持有者
        └── views/                DemoHome / DemoPluginDev / DemoAbout

四个可以对照学习的点

1. 它是"全栈"形态的样本

清单里 assets 同时写了 backend 与 frontend:

"assets": {
  "backend": "backend/wujies-hello-plugin-1.0.0.jar",
  "frontend": "frontend/index.js"
}

⚠️ 两条路径都是包内相对路径,前端那条必须带 frontend/ 前缀。 写成裸文件名(index.js)不会报错,但落位时整棵前端树都不会被释放 (后端 jar 照常落位,所以任务仍然"成功"),表现为菜单点开是"远程视图不可用"。

2. 视图键用 demo/ 前缀是刻意的

app.json 里三个页面菜单的 component 是 remote:hello/demo/home、 remote:hello/demo/plugin-dev、remote:hello/demo/about, 前端 src/index.ts 的 views 键就是 demo/home / demo/plugin-dev / demo/about。

demo 在这里只是视图键的命名空间(不是应用编码),与已去掉的 demo-app 无关。 前缀本身可以随便取,唯一硬要求是:remote:<appCode>/<视图键> 里的 <appCode> 必须等于清单 code、<视图键> 必须在前端真实注册过 —— 不一致就是悬空菜单,而且由清单声明,全新安装也会照建。

3. 它是声明了 dependencies 的样本

hello 的代码 import 了 member 的 IMemberService / MemberMapper, 所以清单必须声明:

"dependencies": [
  { "code": "member" }
]

字段自洽性由打包/安装两道闸兜底:没装或没启用 member 时,安装与升级会被拦住并明确告诉你缺谁, 而不是等运行期抛 No qualifying bean。装机顺序因此是硬约束:被依赖的先装。

4. 「示例应用可以删除」

上架端对删除有白名单保护(后端的 AppConsoleController.DELETABLE_APP_CODES): 只有白名单里的编码能删,内置模块与已上架应用一律拒绝。 这是刻意的:真实应用删掉之后恢复成本很高,而示例应用本来就该能清掉。

自己写一个最小应用

想从零验证一遍链路,见 插件开发,特别是:

相关阅读

目录