Wujies 无界平台
参考

常见问题(FAQ)

本文是 1.x 的归档文档(冻结于 1.x)。该分支只接收勘误修正, 内容基本不再变动;文中的源码路径、配置项与版本号均以 1.x 为准,不建议用于新项目。

新项目请查看 5.x 最新文档。已在 1.x 上运行的项目,本文仍是可靠依据。

概念类

这个项目和 RuoYi-Vue-Plus 是什么关系?

它是后者的「平台 + 应用」形态:底座能力(多租户、鉴权、代码生成、工作流、监控) 完全保留,业务模块改成可以后装、不重启的应用。见 这个项目是什么。

我没有多客户 / 不停机的需求,该用这个项目吗?

不该。插件化带来的类加载器隔离、上下文管理、包签名对你是纯粹的额外成本。 直接用上游 RuoYi-Vue-Plus 更省事。

「应用」和「插件」是一回事吗?

代码里叫插件(plugin),产品上叫应用(app)。 应用有三种类型:module(平台内置模块)、plugin(插件)、deploy(部署型,预留)。

目录 / 安装实例 / 迁移记录为什么要分开?

因为它们的归属范围不同:目录是平台级全局一份,后两者是每个部署各一份。 混在一起就没法把目录集中到一台服务器。见 核心概念。

使用类

装应用要重启吗?

不用。部署 / 安装 / 升级 / 停用 / 启用 / 卸载全部是运行期的。 但带着残留的旧插件 jar 重启会起不来 —— 见下一条。

为什么重启前必须清理旧的插件 jar?

loader.path 在 JVM 启动瞬间不选版本,把插件目录下所有 jar 都挂上去。 同一个应用两个版本的 jar 会带两份同样的 mapper XML → MyBatis 抛 Result Maps collection already contains value → 服务直接起不来。

用 scripts/start-host.ps1(会先清理)或 scripts/prune-plugins.ps1。

卸载应用会删数据吗?

默认不删。弹窗只有两个选项,默认落在可恢复的那条路上。 「彻底删除」需要把应用名完整敲一遍才放行,且它只删应用包迁移脚本声明过的表。

为什么「彻底删除」有时不删表、只写日志?

因为有别的租户还装着同一个应用。菜单行与数据表在一个部署内是所有租户共享的, 平台不能替别的租户做不可恢复的决定。

应用显示"已启用",但一个菜单都没有?

历史上是残留的"死映射"导致(映射指向已删除的菜单 ID 被复用)。 现在菜单同步会自愈。见 菜单归属与保护。

菜单能改吗?能删吗?

  • 改 path / component / perms / 菜单类型 / 父级 → 拒绝;
  • 改名称 / 图标 / 排序 / 显隐 → 放行;
  • 删除 → 拒绝(想隐藏请用「停用」)。

理由:前三者与插件代码、前端路由、权限标识绑死。

开发类

插件里为什么所有依赖都要 provided?

因为这些类由宿主类加载器提供。打进插件会出现"同一个接口两个 Class 对象", 注入与类型判断全部失效。

Mapper XML 放哪?

放在插件自己的 src/main/resources/mapper/<name>/*.xml。

它随插件 jar 走,由 PluginMapperRegistrar 在插件加载时动态注册进宿主的 SqlSessionFactory —— 不是靠 mapperLocations 扫出来的。宿主那套 classpath*:mapper/**/*Mapper.xml 用的是宿主类加载器,扫不到插件里的 XML。

(2026-09-30 前的老答案是"放 *-api 契约模块里"。那个模块现在不存在了, 而且它依赖的"靠配置扫描"这个前提本身也是错的 —— 注册是代码做的。)

插件需要写 @ComponentScan / @MapperScan 吗?

不需要。遵守两条命名约定(包名在 cn.wujies.<app>.*、 XML 在 mapper/<app>/)宿主就会自动发现。

宿主怎么调插件里的服务?

走服务定位器代理。不要在宿主上下文里注册同类型的 bean(哪怕是转发代理), 否则插件的控制器启动就报 expected single matching bean but found 2。

前端页面为什么会 ReferenceError?

三类原因,都是"构建期不报错、一装载就炸":

  1. 产物里残留 process.env → 需要在 vite.config.ts 里 define;
  2. 自动导入少一项(产物里混着宿主源码)→ 需要与宿主 imports 逐项一致;
  3. 组件没进白名单 → 不报错,只是只剩插槽里的文字。

守门脚本:npm run check:remote / check:globals。

打包签名类

一定要签名吗?

当前配置是 enforce —— 未签名的包在上传时就会被拒。 唯一要记住的习惯是:发布时统一带 -SigningKey。

忘了签名怎么办?

打包脚本会明确警告,并在本机存在私钥时把该敲的命令打出来。 已经打好的包可以就地重签(内容一个字节都不动,只加 signature.txt)。

换了密钥要注意什么?

三件事缺一不可:① 重新生成;② 把新公钥填进 public-key;③ 重建宿主并重启。

第 3 件最常被漏 —— 公钥是启动期读入的,不重启则 enforce 会拒掉你刚签的包。 另外,旧钥签过的包全部作废。

没配公钥就把模式改成 enforce 会怎样?

会拒绝所有包,包括你自己签的。报错里会明说原因。 先用签名就绪度自检接口确认再切。

打包能过,上架却报版本号格式错误?

因为版本号有两套正则:打包脚本宽松(接受 1、1.0、1.0.0.0、带 +build), 后端清单校验严格(只接受 x.y.z 或 x.y.z-后缀)。 打包能过不代表上架能过。 建议统一用 x.y.z。

运维类

升级平台表结构会自动做吗?

不会。应用不会自动升级平台表 —— 库归你管。 按发布说明执行 script/sql/update/ 下对应的脚本。

升级应用会自动升级表结构吗?

会。迁移脚本随包走,在 install / upgrade 时按文件名顺序自动执行。

改过迁移脚本之后存量部署升级被挡住了?

这是刻意的保护(摘要不一致会拒绝执行)。正确做法是: 先跑对应的修复脚本删掉账本记录,再升级。

能回滚表结构吗?

不能。 迁移只做 up。要回退请自己写一个"反向"的新迁移脚本。

日志在哪?

按级别分三个文件(控制台 / INFO / ERROR),带滚动与压缩保留。 容器里挂在 /app/logs。详见 任务中心与日志。

具体故障怎么排查?

看 故障排查 的「现象 → 原因 → 处理」表。 第一站永远是「我的应用 → 应用任务」。

相关阅读

目录