夜雨聆风学习资料网

ARTICLE · 1350898

snowy插件式开发与落实实践

snowy插件式开发与落实实践
SNOWY · PLUGIN ENGINEERING IN PRACTICE 

1、把插件规范,变成能交付的东西

        这一份把 「是什么」、「为什么」 和 「怎么落地」 合成一条完整链路:先讲清插件的定义、边界与官方要解决的真实问题, 再给出从建目录、写 pom 到接菜单、打包、验收的每一步可核对的产物。全文以设备巡检 inspect 插件为例,最后一节用一张 双向动态流程图把整条链路完整串起来。

2、认知底座:插件是什么,为什么非这样不可

是什么 · 一条能现场验证的定义

DEFINITION

插件 = 能被另一个不相关的系统装上、也能被摘掉的一块业务能力

不是按「表」或按「目录」切出来的代码块,而是一个可交付物:像 U 盘一样插到 A 产品,也能插到 B 产品;官方底座升级时,你的业务插件不用跟着改。判断标准只有一句——把插件从 pom 里摘掉,应用仍能启动。能摘掉才是插件,摘掉就崩,那是耦合。边界一旦定了,模块名、包名、表前缀三处必须一致,后续所有代码靠这三个名字串起来。

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

为什么 · 官方那份「病历」

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

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

三条原理,以及它们各自逼出的落地动作

◆唯一真正影响选型的差异是底座升级:单体版底座一变,插件要跟着重编译;Cloud 版插件 jar 不动,只换运行底座。一次性交付的项目选单体更划算;如果这块业务要卖给第二个客户、或需要单独扩缩容,从第一天就该按 Cloud 版建。拆模块是为了保留「以后能拆」的权利,不是逼你现在就拆。

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 节那条定义的现场执行:能摘掉,才叫插件。前面七条验的是「做对了」,只有它验的是「是不是插件」。

#
验收项
怎么验
1
包名在扫描范围内
看启动日志里 Controller 注册记录,或调一个空接口确认不是 404
2
依赖方向单向
全局搜索 import,确认没有任何跨插件实现类引用
3
每个 -api 都引了 common
逐个检查子模块 pom,返回值统一用 CommonResult
4
逻辑删除生效
删一条记录后查库,行还在但 DELETE_FLAG 已变
5
资源与权限都授权
用非超管角色登录,菜单可见、按钮可点、接口返回数据
6
前端路径一致
浏览器 Network 面板核对请求 URL 与后端映射
7
可独立打包
目标 app 能打成 jar 并独立启动
8
能被摘掉
从 pom 移除插件后应用仍能启动;放回去功能恢复

◆第 8 条是整套插件化最有效的验收方式,也最常被跳过。能摘掉,才是插件;摘掉就崩,那是耦合。如果这一条不过,前面七条做得再好,也只是把代码写在了新目录里。

8、最后:一条完整落地链路的动态流程图

       把前面的落地链路压成一张图:请求怎么进来、契约怎么生效、数据怎么走、远程通道什么时候介入、结果怎么回去。右上角按钮可切换明暗主题。

12 步编号按逻辑顺序播放,整轮 18 秒后自动循环;右上角图标亦可切换主题。

时序说明:编号不等于严格时序图:编号与动画表示逻辑调用顺序,不代表真实耗时、精确时间比例或完整的并发时序。
场景假设:插件已被目标应用装配;第 9–10 步演示跨进程分支,本地装配时不发生,两个分支不表示先后依赖。需要生命线、严格消息顺序或并发时序建模时,应改用真正的时序图。

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

◆看这张图时,请把注意力放在 3 / 4 / 6 三步:它们是整份文档所有规则的交汇点。只要 -func 到 -api 的依赖保持单向,装配方式换成 Feign 就只是改 pom 的事,业务代码一行不用动——这正是第 8 条验收能通过的底层原因。

Snowy3框架介绍 可阅读如下文章

一款插件方式实现开源后端管理系统(Snowy3)

回首页,搜索你想要的文档

在首页搜索框输入关键词,快速定位资料

文库首页搜索指引 立即搜索

相关学习资料