Skip to content

插件开发

一个应用由什么组成

<你的应用>/
├── app.json                      清单:编码、版本、产物路径、菜单树
├── pom.xml                       后端工程(不在平台 reactor 里)
├── migrations/                   数据库脚本(随包走,安装时自动执行)
│   ├── 01-create-xxx-tables.sql
│   └── 0N-create-xxx-seed-data.sql
└── src/main/java/...             controller / service.impl / listener

前端在另一个仓库:

plus-ui/app-market-poc/<code>-app/
├── vite.config.ts                唯一的工程配置文件
└── src/
    ├── index.ts                  入口契约:导出 install(runtime)
    └── views/                    页面

对应的契约模块在平台里:

RuoYi-Vue-Plus/ruoyi-modules/ruoyi-<name>-api/
├── src/main/java/.../domain/      实体、BO、VO
│   ├── mapper/                    Mapper 接口
│   └── service/                   Service 接口
└── src/main/resources/mapper/     ★ Mapper XML 也在这里

五个必须记住的约定

1. 契约与实现分家

  • 实体 / BO / VO / Mapper 接口 与 Mapper XML / Service 接口 → *-api(在 reactor 内)
  • controller / service.impl / listener → plugins/ruoyi-<name>不在任何 <modules>

Mapper XML 放在 *-api 这条尤其重要:宿主的 mapperLocations 是用宿主类加载器扫描的, XML 留在插件 jar 里就永远扫不到 → 所有 SQL 静默失效

2. 平台依赖一律 provided

xml
<dependency>
    <groupId>org.dromara</groupId>
    <artifactId>ruoyi-common-core</artifactId>
    <scope>provided</scope>
</dependency>

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

3. 菜单只能通过清单声明

不要手写 INSERT INTO sys_menu。菜单走 app.jsonmenus,安装/升级时由平台 幂等 upsert,按 menu_key 复用既有 menu_id —— 这样租户已分配的权限不会失效

type: "F"按钮也必须写进清单,否则全新部署装完没有按钮、 "彻底删除"时也删不掉它们。

4. 表结构随包走

不要手写 SQL、也不要让插件代码自己建表。把脚本放进 migrations/, 打包时自动进包,安装/升级时按文件名排序执行。

5. 平台依赖只能从父上下文取

插件能注入宿主,宿主不能注入插件。宿主侧要拿插件服务,走服务定位器代理。

不要在宿主上下文里注册与插件实现同类型的 bean(哪怕是个转发代理)—— 那会让插件的控制器启动时报 expected single matching bean but found 2

快速导航

我想…看这里
搞清 app.json 每个字段应用清单 app.json
写后端工程后端工程
写前端远程应用前端远程应用
声明菜单与权限菜单与权限
加表 / 改表数据库迁移
让应用装完就有字典和配置种子数据与站点配置
本地调试本地联调
把一个宿主模块抽成应用抽取 SOP
改平台代码(贡献者)开发指南 / 必须遵守的不变量

从零做一个应用:最小步骤

powershell
# 1) 建契约模块 ruoyi-modules/ruoyi-<name>-api(进 reactor)
#    放 domain / mapper 接口 + XML / service 接口

# 2) 建实现工程 plugins/ruoyi-<name>(不进任何 <modules>)
#    pom 的 parent 用 <relativePath>../../pom.xml</relativePath>
#    平台依赖全部 provided

# 3) 写 app.json(菜单树含 F 按钮)

# 4) 写建表脚本
#    plugins/ruoyi-<name>/migrations/01-create-<name>-tables.sql
#    从库里 SHOW CREATE TABLE 导出 → 改成 CREATE TABLE IF NOT EXISTS

# 5) 建前端工程
#    plus-ui/app-market-poc/<code>-app/
#    vite.config.ts 抄 gallery 的,按实际用到裁剪白名单
#    src/index.ts 默认导出 install(runtime)

# 6) 第一次用:生成签名密钥
powershell -NoProfile -ExecutionPolicy Bypass -File plugins\package.ps1 -Keygen

# 7) 打包 + 签名(脚本会自己构建前后端)
powershell -NoProfile -ExecutionPolicy Bypass -File plugins\package.ps1 `
    -Plugin ruoyi-<name> -SigningKey plugins\keys\private.pem

# 8) 上架:安装包上传 → 保存版本 → 发布 → 上架 → 部署

完整细节见各分节。

与宿主模块抽取的区别

如果你不是从零写,而是把宿主里已有的业务模块抽出来变成应用, 步骤不同(多了"改宿主消费方"与"存量迁移 SQL"两步):

进度:quote / enterprise / member / pay / exam / im / social / mall —— 八个已完成。

从宿主模块抽成应用(SOP)

相关阅读

基于 MIT 协议开源 · 文档与官网由源码生成