ARTICLE · 1350898
snowy插件式开发与落实实践
1、把插件规范,变成能交付的东西
这一份把 「是什么」、「为什么」 和 「怎么落地」 合成一条完整链路:先讲清插件的定义、边界与官方要解决的真实问题, 再给出从建目录、写 pom 到接菜单、打包、验收的每一步可核对的产物。全文以设备巡检 inspect 插件为例,最后一节用一张 双向动态流程图把整条链路完整串起来。
2、认知底座:插件是什么,为什么非这样不可
是什么 · 一条能现场验证的定义
插件 = 能被另一个不相关的系统装上、也能被摘掉的一块业务能力
不是按「表」或按「目录」切出来的代码块,而是一个可交付物:像 U 盘一样插到 A 产品,也能插到 B 产品;官方底座升级时,你的业务插件不用跟着改。判断标准只有一句——把插件从 pom 里摘掉,应用仍能启动。能摘掉才是插件,摘掉就崩,那是耦合。边界一旦定了,模块名、包名、表前缀三处必须一致,后续所有代码靠这三个名字串起来。


官方插件全景 · 先知道自己的插件该放在哪

为什么 · 官方那份「病历」
Snowy 官方在《插件规范(生态产品插件)》里描述的不是架构理想,而是组织扩张期的真实状态:A 组自研脚手架、B 组用开源方案、C 产品线另起中台,个别同学还按个人偏好开发。这种「技术诸侯割据」最后会变成几笔可量化的账:

此外,文档维护占研发投入 > 8%,每个新人都得重读一遍别人的「祖传代码」。所以插件化解决的不是「代码怎么分包」这种形式问题,而是把业务能力变成可交付物——复用率、升级成本、交付节奏一起改善。也正因为目标是「可交付」,才有了下面三条不能让步的设计约束。
三条原理,以及它们各自逼出的落地动作

3、落地路径:五个阶段,五个产物
为什么 按阶段切,是因为依赖方向在 P1 / P2 就定死了。插件化的收益全部来自「依赖可替换」,越往后改方向,返工面越大——所以先看 00 节的单向依赖,再推进五个阶段。

先看全局:一次插件落地的依赖架构
下面这张图由技术架构图技能生成并通过几何与构图校验。它不画业务细节,只画谁依赖谁——落地时最容易出错的正是这一层。

动手前必须锁死的四条硬规则
这四条都来自官方规范原文,破一条,后面所有的「插件化收益」都会失效。
为什么这四条不是风格建议,是让 Maven 在编译期就能强制执行的约束。只有把「调用方看不见实现」写进 pom,「换底座不改业务代码」才不是一句口号。
(1)、跨插件只允许依赖对方的 api,严禁直接引入实现
官方原文:「插件之间的互相调用仅允许通过引用对方的 api 接口方式,严禁为了图方便将对方插件直接引入。」直接依赖 -func 会立刻带来三个后果:Maven 循环依赖、对方重构你被迫跟改、想拆服务时发现编译期已绑死。
依据:SNOWY 后端手册 · 插件规范
(2)、 每个 -api 必须引用 snowy-common
统一分页 PageQuery、统一结果 CommonResult、通用基础实体 CommonEntity、定时任务抽象都在这里。漏引不会立刻报错,但会在写接口返回值时到处造轮子,最后各插件返回结构不一致。
依据:官方插件规范;源码中各 -api 模块仅依赖 common
(3)、 根包必须落在 vip.xiaonuo 下
主启动类 @ComponentSca与 @EnableFeignClients
(basePackages = "vip.xiaonuo") 决定了扫描范围。包名起错是最隐蔽的坑:启动不报错,但接口全部 404、Bean 全部注入失败 ,因为类压根没被注册。
依据:后端开发规范 · 插件创建第 ⑦ 步
(4)、不要把长期业务写进 snowy-plugin-biz
官方对它的定位是「给客户预留的业务插件」,适合验证原型。判断标准很简单:这块业务会不会单独交付给另一个客户? 会,就独立建插件。这一条决定了你是在做插件,还是只是把代码挪了个目录。
依据:生态产品插件规范 / 官方插件职责说明。
▲ 补充一条来自实战资料的判断:不需要部署多个独立的 Snowy 项目。同一个项目里用多插件架构,把新业务按标准插件对开发,既保留快速原型,又为未来可能的服务拆分留出余地。别一开始就把「插件化」等同于「上微服务」。
4、工程落地:目录与 pom 一次做对
目录决定编译期依赖,pom 决定运行时装配。这两处做对,后面 80% 的「Bean 找不到 / 打包缺依赖」都不会发生。
为什么 拆五个 module 不是规范洁癖,是为了同时满足 00 节那三件互相拉扯的事。多出的三个只在跨进程时才有内容,纯单体场景建了也是空的,别为了「看起来规范」白建。

三层 pom 的关键片段(可直接抄)
最容易错的一点:父模块只聚合 module,不声明业务依赖。依赖声明下沉到各个子模块。
<!-- ① snowy-plugin/pom.xml:只加一行聚合 --><module>snowy-plugin-inspect</module><!-- ② 插件父模块:packaging 必须是 pom --><artifactId>snowy-plugin-inspect</artifactId><packaging>pom</packaging><modules><module>snowy-plugin-inspect-api</module><module>snowy-plugin-inspect-func</module><!-- 需要跨进程时再打开下面三行 --><!-- <module>...-feign</module> --></modules><!-- ③ -api 引 common;-func 只引 api;应用只引 func --><dependency><artifactId>snowy-common</artifactId><!-- 在 -api 里 --></dependency>
空壳先行。模块建好、pom 串好之后立刻启动一次,确认能起来再写业务代码。骨架不对时,类写得越多,返工越大。Cloud 版还需要先起 Nacos;单体版不需要。
5、编码与数据落地:把重复劳动交出去
代码生成器能按表一键产出前后端 CRUD、菜单与按钮,但它的边界必须划清楚,否则第二次生成会覆盖掉你的业务代码。
为什么生成器铺的是骨架,不是业务逻辑。插件之所以能被重新生成、被换底座,靠的就是 Controller / Service / Mapper 各司其职、谁也不越层;在生成产物里写判断,等于把可替换性又交回给了机器。
包结构:core + modular 两层
插件内部按「一个功能一个包、包内按职责分层」组织,这是官方与源码实践一致的结构:

数据表:六个字段一次补齐
表名全大写带模块前缀(INSPECT_PLAN)。除业务字段外,公共字段一次到位,缺一个后面要同时改 Entity、XML 和前端:

▲ 两个高频返工点:① 漏 DELETE_FLAG,删除按钮点了没反应;② 在生成产物里写业务判断,第二次生成被全部覆盖。生成器铺骨架,你只改业务差异、查询条件、删掉用不上的方法。
6、接入与装配落地:让功能真的能被用起来
「代码写完了」和「用户能用」之间还隔着四根线,少接一根,表现都是「功能做好了但用不了」。
为什么「装上了」和「用户能用」是两件事。资源授权(菜单 / 按钮)与接口权限是两套独立数据,菜单只决定「看得见」。这是「把业务能力变成可交付物」的最后一公里,少接一根线就退化成一块没人能用的代码。

Cloud 版特有的三个动作
下面这些只在跨进程时才需要。纯单体场景建了也是空模块,别为了「看起来规范」白建:
- 别的服务要调你:建
-feign+-feign-provider,用@FeignClient声明服务名,Provider 侧用@RestController暴露。 - 你要调别人但本地没有实现:建
-api-context,写一个implements XxxApi的壳,方法体转调 Feign,让 Spring 注入不报错。 - 多环境配置:用 Nacos 的 namespace 区分 dev / test / prod;数据库连接、Redis、JWT、Feign 超时都放配置中心。Feign 调用 404 时先核对服务名与注册中心、路径是否一致。
◆数据范围要单独确认语义:它只给你「机构 ID 集合」,空集合表示「全可见」还是「什么也看不到」,需要和产品确认。官方刻意不用注解自动处理,就是为了不替你做这个业务判断。
7、交付验收:八条,逐条打勾
每条都给了可操作的验证方式,不写「检查是否正常」这种无法执行的话。
为什么 第 8 条其实是 01 节那条定义的现场执行:能摘掉,才叫插件。前面七条验的是「做对了」,只有它验的是「是不是插件」。
import,确认没有任何跨插件实现类引用 | ||
-api 都引了 common | CommonResult | |
DELETE_FLAG 已变 | ||
| 能被摘掉 |
◆第 8 条是整套插件化最有效的验收方式,也最常被跳过。能摘掉,才是插件;摘掉就崩,那是耦合。如果这一条不过,前面七条做得再好,也只是把代码写在了新目录里。
8、最后:一条完整落地链路的动态流程图
把前面的落地链路压成一张图:请求怎么进来、契约怎么生效、数据怎么走、远程通道什么时候介入、结果怎么回去。右上角按钮可切换明暗主题。
12 步编号按逻辑顺序播放,整轮 18 秒后自动循环;右上角图标亦可切换主题。


十二步编号对照(图中标签已压缩,语义在这里还原)

-func 到 -api 的依赖保持单向,装配方式换成 Feign 就只是改 pom 的事,业务代码一行不用动——这正是第 8 条验收能通过的底层原因。Snowy3框架介绍 可阅读如下文章















































































