# aimom-extends-plugins
aimom **外部扩展插件仓库**:一个仓库承载多个 aimom Java 插件。
工作方式:插件是**普通 Maven jar**(不是 Spring Bean、不是 OSGi)。应用启动时扫描 classpath 上所有 `plugin.json`(`name` 以 `@aimom` 开头的才会被发现),按 `basePackageDir` 反射实例化入口类;"打进 classpath ≠ 启用",启用状态存数据库 `applicationPlugins` 表。
## 仓库结构
aimom-extends-plugins/
├── pom.xml # 聚合 pom,继承 com.sie.aimom:aimom:1.0.0-SNAPSHOT(统一版本管理)
│ # 并为所有插件模块注入 aimom-core + lombok(provided)
└── plugin-hello-world/ # 全栈示例插件:collection + REST action + ACL + migration + i18n
└── src/main/
├── java/com/sie/aimom/plugins/helloworld/
│ ├── PluginHelloWorld.java # 插件入口(唯一 Plugin 子类,构造器 (Application, PluginOptions))
│ ├── actions/ # (可选)自定义 REST action(静态 Handler + 单例,入口类统一注册)
│ ├── collections/ # (可选)CollectionDefine 子类(框架按 basePackageDir 自动扫描)
│ ├── migrations/ # (可选)Migration 子类(类名 = migrations 表幂等键,自动扫描执行)
│ ├── constants/ # 常量类 + 字典枚举
│ ├── api/ # 对外 REST 的请求/响应 DTO
│ ├── type/ # 插件内部使用结构 bean
│ └── ai/ # (可选)AI 实现类:tools/** 工具、mcp/** MCP、aiemployees/** AI 员工
└── resources/
├── plugin.json # name=@aimom/plugin-xxx + basePackageDir
├── collections/*.json # 表结构定义(建表走 db.sync,无需手写 DDL)
├── locale/{en-US,zh-CN}.json
└── ai/ # (可选)AI 定义资源,按目录约定自动扫描,无需注册代码
├── tools//description.md # 工具描述(实现类在 java 侧 ai//tools/**)
├── skills/
└── aiemployees/
## 命名契约
命名契约(`plugin.json` name ↔ Maven artifactId ↔ basePackageDir ↔ 外置 jar 文件名,任一处错位插件即"不可见")以 `.harness/rules/plugin-rule.md` 为准。
## 构建
前置:Maven 能解析平台工件——父 pom `com.sie.aimom:aimom` 与框架 jar `com.sie.aimom:aimom-core`(来自内部 Nexus,或平台方/联调环境装入本地 `~/.m2` 的快照)。本仓库不需要平台源码。
```bash
mvn clean install # 全量构建(jar 装入 ~/.m2,供 aimom-starter 引用)
mvn clean deploy # 发布到 Nexus(deploy 目标继承自父 pom,Nexus 凭证配在 Maven settings.xml)
mvn test -pl plugin-hello-world # 只跑测试
规则自检:python3 .harness/scripts/check-rules.py——对命名契约、i18n、日志/异常、pom 约定等做静态校验,覆盖范围见脚本头部说明。
新增一个插件
python3 .harness/scripts/new-plugin.py qms-spc # 生成 plugin-qms-spc
python3 .harness/scripts/new-plugin.py qms-spc --dry-run # 只看计划不落盘
脚本内嵌模板自生成最小骨架(与范例模块解耦,不复制现有代码):模块目录 + pom(artifactId)+ plugin.json(name/basePackageDir)+ 唯一入口类(Plugin<驼峰>,仅必需构造器),并登记根 pom <modules>;不生成测试与其他资源文件。需要完整目录树骨架时加 --full(§2 子包与 collections/locale/ai 资源目录,纯空目录,内容按需自建)。生成后自动跑 check-rules.py 自检。
人工待办(脚本结束会打印清单):plugin.json 的 displayName/description;集合/动作/ACL/迁移/i18n 等按需自建(全栈写法参照本仓库 plugin-hello-world 范例与 .harness/rules/plugin-rule.md)。
多段命名示例(产品-功能):QMS 产品的 SPC 功能 → new-plugin.py qms-spc 生成 plugin-qms-spc,name @aimom/plugin-qms-spc,包(basePackageDir) com.sie.aimom.plugins.qmsspc。
集成进 aimom-starter
- 路径 A(主推):Maven 依赖引用随 fat-jar 分发——本仓库交付 jar 后,由平台方在 aimom 主仓库登记两处(根
pom.xml<dependencyManagement>按字母序登记版本 +aimom-starter/pom.xml<dependencies>无版本引用,不含插件源码)并重打 starter;依赖由 Maven 正常装配,无 shade 问题 - 路径 B(备选):外置 JAR 放入外部插件目录(默认
./plugins,自动加载默认开启),重启进程即被加载并自动启用;注意事项与本地操作见下方「本地启动调试」
本地启动调试(fat jar + ./plugins)
没有 aimom 源码也能本地调试插件:一个 aimom-starter fat jar(约 300MB,由平台组提供;有源码的机器也可在主仓库 mvn -pl aimom-starter -am clean package -DskipTests 自打)+ 本仓库构建的插件 jar,前置 JDK 21,三步跑通。
1. 构建插件并放入 ./plugins/
# 在 starter jar 所在目录执行(./plugins 相对 java 进程工作目录解析,与 aimom-starter.jar 平级)
mvn clean install -pl plugin-hello-world
mkdir -p plugins && cp plugin-hello-world/target/plugin-hello-world-1.0.0-SNAPSHOT.jar plugins/
- 外部插件自动加载默认开启;
./plugins为唯一外部插件目录,相对 java 进程工作目录解析(目录不存在仅 WARN 跳过) - 外置 jar 文件名须符合命名契约(
.harness/rules/plugin-rule.md§1) - 增删 jar 后需重启进程生效(运行期动态加载
pm:add未实现) - 不要把 starter 已内置的同名插件再放进
./plugins/——资源重复会触发启动异常 - 插件用到的第三方依赖必须 shade 进插件 jar(
aimom-core为 provided 不打入);插件模块禁止 spring-boot-maven-plugin
2. 准备外部配置(无内网必做)
starter 内置 yml 的数据源默认指向内网开发库(PostgreSQL 192.168.168.54:5436/aimom_dev_v3,Redis 192.168.168.207:32180)。无内网的开发者必须覆盖为自己的 PostgreSQL/Redis,任选一种方式:
- 外部配置文件:jar 内置
spring.config.import会读取optional:file:/springboot_config/aimom-starter.yml(文件不存在则跳过)。在该路径放置自备的aimom-starter.yml,覆盖数据源/Redis 等配置。- Windows 注意:
file:/springboot_config/...按当前盘符根目录解析——jar 从 D 盘某目录启动即对应D:\springboot_config\aimom-starter.yml,从 C 盘启动则是C:\springboot_config\aimom-starter.yml - 也可用启动参数显式指定配置文件位置:
java -jar aimom-starter.jar --spring.config.location=file:./aimom-starter.yml
- Windows 注意:
- 环境变量覆盖单项:
AIMOM_DB_URL/AIMOM_DB_USERNAME/AIMOM_DB_PASSWORD
3. 启动与验证
java -jar aimom-starter.jar # JDK 21,默认端口 14000
- 日志同时写入
${java.io.tmpdir}/aimom-logs/aimom-starter.log(Windows 即%TEMP%\aimom-logs\aimom-starter.log) - local 插件登记后的启用行为随交付 starter 版本不同:新版平台默认登记不启用(
aimom.plugin.auto-enable-local=false),需在平台插件管理中手动启用;旧版登记即自动启用。后续启停均经平台端插件管理操作
验证清单:
- 本仓库
mvn clean install通过(含契约测试:plugin.json 命名 + 双语 locale key 一致) - 路径 A:平台方完成两处引用登记,重打 starter(
mvn clean install -pl aimom-starter)通过 - 启动日志出现
[PLUGIN_DISCOVER] discovered ... plugin-hello-world ...与[PM_LOAD]行(被排除时会打 skip 原因) - local 插件已被自动登记并启用
- REST 冒烟:登录态
GET /api/helloWorlds:stats返回{"total": 2, ...}(install() 已种子 2 条)
开发约定
规则正文在 .harness/rules/(命名契约与工程结构、编码、数据访问与事务、i18n、日志、异常、构建与提交),AI 协作约束入口见 AGENTS.md。