开篇:为什么改造开源智慧园区而不是从零自研

第 1 / 10 章
开篇:为什么改造开源智慧园区而不是从零自研

去年下半年,我接了一个产业园区的数字化项目。甲方是一家区属国资运营公司,手里管着三个园区、四十多栋楼宇,业态混着研发办公、轻型制造和小微企业孵化。谈需求的那天,他们的信息科主任给我看了一张表——那张表上列着他们现在在用的所有系统:门禁一家供应商、停车一家、能耗监测又一家、访客登记居然还在用纸质登记本拍照存档。他问我:"能不能把这些东西捏到一个平台里?"

我说能,但怎么做,比能不能更重要。这一章我先讲清楚一个决策问题:这种园区综合管理平台,到底是该从零自研,还是找一个开源项目改造。以及我在 GitHub 和 Gitee 上翻了一个多星期之后,为什么最终把票投给了 genchuan-smart-city 这个项目。

先算账:自研的隐性成本到底有多大

很多人一听"综合管理平台",第一反应就是拉团队自研,觉得业务都是自己的、代码攥在手里才踏实。我劝你先算三笔账。

第一笔是业务广度的账。一个园区平台要跑起来,至少要覆盖这几块:人员与车辆的出入管理(含人脸、访客预约)、停车与计费、水电气的能耗采集与分摊、安防视频监控、企业租户档案。这五块里没有一块是"简单 CRUD"——光是访客预约,就牵扯审核流、通行凭证、核销离园的完整状态机;光是停车计费,就有账单生成、优惠减免、催缴补缴、发票开具一整套财务口径的流转。从零写这些业务,一个五人团队至少半年起步,这还是一切顺利的前提下。

第二笔是协议对接的账。园区行业的设备侧是个大染缸:人脸门禁有的是海康协议、有的是大华协议、还有一堆 OEM 白牌走私有 TCP;水电气表可能是 DL/T 645,可能是 MQTT 直传,也可能是抄表平台转发的 HTTP。这些协议适配工作没有业务价值但极其耗人,自研团队往往在这里消耗掉三分之一的人力。

第三笔是试错的账。园区业务有很多只有踩过坑才知道的细节:比如访客凭证被拍照转发给第三人怎么办?车位预约了不来怎么释放?能耗数据采集中途断了几小时怎么补数?这些问题开源项目里往往都留有处理痕迹,而自研团队要在生产环境里把坑重新踩一遍。

所以我的结论是:园区平台这类"业务广度大、单点深度浅、设备协议繁"的系统,改造开源底座远比从零自研划算。真正需要自研打磨的,是底座之上贴合自己园区的业务规则。

选型:我把候选项目一个一个拆开看了

定了改造路线,接下来就是选底座。我在 Gitee 和 GitHub 上前后看了四五个候选项目,这里把评估过程如实摆出来——因为"看 README 很美"和"代码真的能跑"之间,隔着一条巨大的鸿沟。

候选一:kungfupan/smart-park(Gitee)。 README 写得很完整,技术栈是 Spring Boot 3.2 + Vue3 + Three.js,字段注释齐全,甚至有完整的 API 文档。但我把代码拉下来翻了半天发现,它的"园区业务"只有园区、楼宇、楼层三级空间管理,加上一个文章管理模块凑数。三级空间管理撑不起一个平台,这个项目更像一个教学级脚手架。放弃,但它清晰的包结构给了我一个参照系。

候选二:fcba/ics-park(GitHub)。 这个项目 star 有两千多,README 宣传 V3.0 全功能,看着非常唬人。我把 master 分支拉下来检查数据库脚本,结果整库只有 5 张 ics_ 前缀的业务表(党建、政策、费用之类的边缘场景),剩下的全是 RuoYi 框架表——宣传里的园区核心功能在商业版里,开源的只是个壳。这件事给我提了个醒:star 数和 README 都不等于代码完整度,一定要翻到 DDL 和 Service 实现层再下结论。

候选三:java110/MicroCommunity。 这个是成熟的物业系统,代码量大、生产验证充分。但它的业务重心在"小区物业"——业主、房产、物业费收缴,和"产业园区"的诉求不对口:园区没有"业主"概念,核心是企业租户、工位与能耗分摊。硬改的话,等于把人家的领域模型拆了重装,得不偿失。

候选四:genchuan/genchuan-smart-city(Gitee)。 拉下来之后我确认了三件事,然后决定就是它了。

第一件事,底座够硬。它基于芋道 yudao-cloud 微服务框架,JDK 17/21 + Spring Boot 3.2 + Spring Cloud Alibaba 全家桶(Nacos 注册配置、Gateway 网关、Sentinel 限流、Seata 分布式事务),整个仓库 3800 多次提交,不是玩具。

第二件事,园区业务是真的。仓库里有一个独立的 genchuan-module-industrialpark(产业园区)模块,我数了一遍,光这个模块就有 200 多个 Java 文件,拆成四个子模块:出入管理(accessmgmt)、能耗管理(energymgmt)、企业服务(enterprisesvc)、综合安防(integratedsecurity)。我把核心的 Service 实现类逐个读过去,账单状态机、访客审核流、能耗采集异常计数,业务逻辑都是真实落地的,不是接口空壳。

第三件事,许可干净。Apache-2.0 + MIT 双协议,商用改造没有法律上的后顾之忧。

底座长什么样:一段真实代码先睹为快

空口无凭,我贴一段产业园区模块里的真实代码。这是访客预约的核心数据对象 VisitorAppointDO,位于 genchuan-module-industrialpark 模块下:

@TableName("visitor_appoint")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class VisitorAppointDO extends BaseDO {

    @TableId
    private Long id;
    /**
     * [访客姓名] 访客姓名
     */
    private String visitorName;
    /**
     * [身份证号] 访客身份证号
     */
    private String idCard;
    /**
     * [被访企业] 被访企业名称
     */
    private String visitCompany;
    /**
     * [到访时间] 预约到访时间
     */
    private LocalDateTime visitTime;
    /**
     * [预约状态] 如:待审核/已通过/已驳回/已取消/已离园
     */
    private String appointStatus;
    /**
     * [通行凭证] 审核通过后生成的通行凭证号
     */
    private String ticket;
    /**
     * [到达时间] 实际到达时间
     */
    private LocalDateTime arriveTime;
    /**
     * [离开时间] 实际离园时间
     */
    private LocalDateTime leaveTime;
}

这段代码有几个细节值得咀嚼。它继承了 BaseDO——芋道框架的基类,里面统一封装了创建人、创建时间、更新时间、逻辑删除这些每个表都需要的审计字段,业务表自己只声明业务字段,这是框架底座带来的第一层红利。它用 @TableName 声明映射到 visitor_appoint 表,字段注释把预约状态枚举直接写成了"待审核/已通过/已驳回/已取消/已离园"五个状态——这背后就是一个完整的访客生命周期状态机,审核、核销、离园的整套 Service 方法都围着它转。还有 ticket 这个通行凭证字段,审核通过后生成、闸机核销时验证,把线上的预约流程和线下的门禁动作串了起来。

我后来的二开工作里,大量时间就是和这样的 DO、Service 打交道。这个模块的代码风格相当统一:Controller 收参数校验,Service 写业务规则,dal/dataobject 放表映射,dal/mysql 放 Mapper,六层结构清清爽爽。改造时顺着约定写代码就行,不需要去猜原作者的意图。

把评估方法固化:五个维度给候选项目打分

四个候选看完之后,我把这次踩过的弯路提炼成了一套可复用的评估方法,后来做其他项目选型我也一直在用。五个维度,每个维度都有明确的验证动作:

业务完整度:不看 README 的功能列表,直接打开 dal/dataobject 目录数 DO——DO 的数量和命名就是业务域的真实地图。候选一有三个园区 DO,候选二有五个党建政策 DO,候选四有十三个覆盖出入、能耗、安防、企业的 DO,高下立判。

实现深度:抽两三个核心 Service 实现类通读,看业务逻辑是真实落地还是接口转调。判断标准很简单:状态迁移有没有校验前置状态?异常路径有没有业务错误码?如果 ServiceImpl 里只有清一色的"查出来转 VO 返回",那它只是个数据库的 HTTP 皮肤。

工程成熟度:看提交历史的持续性与规模——3800 多次提交意味着这个项目被真实地开发和维护过很久;再看有没有 CI 配置、代码规范约束、统一的异常与响应封装。这些"工程周边"直接决定你二开时的顺手程度。

许可合规:逐字读 LICENSE 文件而不是看仓库标签。候选四的仓库里同时有 Apache-2.0 和 LICENSE.MIT 两个文件,我专门确认了二者的适用范围——框架底座与业务模块分别适用哪个协议、商用是否要求保留版权声明。这一步十分钟,但它决定你的项目能不能合法地卖钱。

技术栈世代:JDK 8 的项目不是不能用,但你接下来三五年的维护都要背着它。候选四基于 JDK 17/21 与 Spring Boot 3.2,意味着虚拟线程、GraalVM、最新的 Spring Security 6 都在可选清单里,这个"世代红利"会在维护期持续兑现。

这五步走完,选型就从"看眼缘"变成了"看证据"。后来有朋友问我怎么判断一个开源项目能不能商用二开,我都让他先去做这套体检——十分钟的尽调,避免的是几个月的返工。

二开前的技术准备:环境与依赖盘点

决定动手之后,我没有立刻写业务代码,而是花了两三天做环境盘点。这份清单你可以直接拿去用。

开发机资源:微服务架构对开发机的内存是实打实的考验。Nacos、MySQL、Redis 三个基础设施加 Gateway、system、infra、industrialpark 四个服务,全起一遍峰值内存 8G 上下。我的开发机 32G 内存余量充足,如果你的机器吃紧,Nacos 和 MySQL 可以放 Docker,Java 服务本地起两个最常用的,其余按需启动。

中间件版本:对照 yudao-dependencies 里的版本锁定清单核对本地环境——MySQL 用 8.x、Redis 用 6 以上、JDK 按项目配置选 17。版本错位最典型的坑是 MySQL 5.7 与 8.0 的默认字符集和认证插件差异,连不上库的时候先查这个。

账号与初始化:框架自带的 sql 目录有系统库初始化脚本(用户、菜单、字典、租户的基础数据),初始化之后先用默认管理员登录一遍管理后台,把菜单结构过一眼——这个动作能帮你快速建立"系统有哪些能力"的全景认知,比翻代码快得多。

保留一份原始快照:clone 之后我立刻打了一个 git tag(v0-baseline),后续所有二开提交都在它之上。这个习惯在需要对照"原项目这里原来怎么写的"时非常救命——diff 一下就是最准确的文档。

环境盘点的产出是本地开发环境的完全可复现:任何人拿到这份清单,半天内能把项目在自己机器上跑起来。这件事在团队协作时价值翻倍,一个人的脑内知识只有变成文档才算资产。

我的二开策略:不贪多,先立住五条业务线

拿到这个底座之后,我没有把整个 smart-city 仓库全部跑起来,而是做了一次"业务聚焦":只取 genchuan-module-industrialpark 这一个模块作为二开主场,围绕园区的五条核心业务线展开——人脸门禁与通行记录、访客预约全链路、停车计费闭环、能耗采集与区域监测、综合安防告警。企业租户档案作为贯穿这些业务线的主数据,放在收尾阶段做整合。

为什么这么取舍?因为 genchuan-smart-city 本质上是一个"智慧城市"全家桶,里面还有智慧校园、水务、市场监管等十几个模块,那些模块和园区平台无关,全量拉起服务只会拖垮开发机的内存和你的耐心。微服务架构的好处在这里就体现出来了:模块边界清晰,我只关注自己的四个子模块,网关路由、注册中心配置好依赖关系,其他模块连编译都不需要。

技术底座方面,我保留的是这套组合:Nacos 做注册与配置中心,Spring Cloud Gateway 做统一入口,MySQL 存业务数据,Redis 做缓存与会话。Sentinel 和 Seata 在单园区场景下暂时用不上,配置先留着不启用——这也是二开的一个原则:底座能力可以闲置,但不要急着拆除,等你的平台真的要支撑多园区高并发时,这些东西能立刻顶上来。

这个系列会怎么写

接下来的九章,我会沿着真实改造的顺序展开,每一章都基于模块里的真实代码来讲:

  • 第 2 章讲架构总览,把 yudao-cloud 底座和 industrialpark 模块的分层约定讲透,这是后面所有章节的地基;
  • 第 3、4 章讲门禁与访客,人脸库管理、通行记录、访客预约的五状态生命周期,这是园区日常运转最频繁的链路;
  • 第 5、6 章讲停车,车位台账、账单生成、BigDecimal 计费、催缴与发票闭环,这是园区最直接的现金流业务;
  • 第 7、8 章讲能耗,电水气热四类数据的采集接入、异常治理、区域看板与分摊分析,这是园区降本增效的故事主角;
  • 第 9 章讲安防,视频监控接入与实时告警;
  • 第 10 章讲企业档案与生产部署复盘,把多租户隔离、上线配置和踩过的坑一次讲完。

写这个系列时我给自己定了一条规矩:贴出来的代码全部来自仓库原文,改造点我会明确标注"这是原实现"、"这是我改的"。改造开源项目不是照抄照搬,而是先读懂人家的设计意图,再决定哪里保留、哪里推翻。这个过程里的思考,比结论本身更值钱。

下一章,我们从架构总览开始。