基于现代Java开发的智能食品储物追踪器
PantryPal 是一款轻量级的智能食品储物追踪器,可记录杂货清单、估算保质期,并提示哪些食物即将过期,避免被扔进垃圾桶。该应用完全基于 Java 26 标准库构建,通过一个真实且日常的场景——减少家庭食物浪费,展示了虚拟线程、结构化并发、密封接口以及模式匹配等技术。
问题
食物浪费是那些“隐形”的家庭问题之一。一袋饼干被塞进了储藏室的角落,牛奶悄悄过了保质期,罐头食品也被遗忘多年——直到你不得不扔掉那些花钱买却从未真正用过的东西。
防止这种情况的信息其实已经存在:它就印在包装上,以条形码的形式显示。问题在于,没人有时间手动将每样购买的商品逐一记录到电子表格中,而且电子表格本身也无法提醒你某些商品即将过期。
PantryPal填补了这一空白:只需将摄像头对准条形码一次,系统便会自动完成后续操作——识别产品、估算保质期,并在需要关注时及时提醒。
工作原理
物理流程简单且以相机为中心:
1. 扫描
将产品的条形码对准连接到树莓派的网络摄像头。
2. 捕捉
Pi 使用轻量级的 Python 扫描脚本,实时解码来自实时摄像头画面的条形码。
3. 查找与日志
扫描仪将条形码发送到PantryPal服务器(该服务器运行在同一块树莓派上),服务器通过Open Food Facts数据库查询产品信息,估算其类别下的保质期,并进行存储。
4. 轨迹
PantryPal 会持续将每件物品分类为新鲜、即将过期或已过期,并实时更新仪表板,显示需要先使用哪些物品。
无需安装应用,无需手动输入条形码商品
只需扫描,然后离开。
系统架构
所有服务器端操作都运行在单个Java进程上——无需外部数据库,无需应用服务器,也无需第三方依赖。整个系统仅需安装JDK 26即可构建和运行。
为什么选择 Java 26?
这个项目不仅关注它的功能,也关注它的实现方式。多种现代Java特性自然映射到食品储藏柜追踪器的问题架构上:
•记录(Product、PantryItem):一旦创建,这两种类型都是天然不可变的值类型,完美地体现了记录的特点——无需繁琐的getter方法,equals/hashCode简洁高效,构造函数也可同时用作验证点。
•虚拟线程:仪表板服务器和HTTP客户端均运行在虚拟线程上,因此扫描大量杂货(数十次条形码查询)时无需进行线程池调优——JVM会透明地处理数千个并发的轻量级线程。
•结构化任务范围:在解析条形码时,PantryPal 会将本地缓存检查与向 Open Food Facts 的网络调用合并为一个结构化的任务单元。哪个先完成(或缓存命中),就获胜,而另一个子任务将被自动取消——无需手动管理线程或泄露后台调用。
•SequencedMap:食品储藏室的内存存储使用 SequencedMap 来以低成本获取“最近添加的内容”,同时支持常规的键值查找,而无需维护单独的排序结构。
硬件设置
网络摄像头通过USB连接到树莓派。一个轻量级的Python脚本(raspberry-pi/scanner.py)会持续监控摄像头画面,使用pyzbar解码条形码,并将每次新的扫描结果直接POST到运行在同一台树莓派上的PantryPal REST API,无需在Java端进行任何修改即可支持此功能。对于没有条形码的物品,仍可通过仪表盘手动输入作为备用方式。完整的设置步骤以及可选的systemd配置(使整个系统在树莓派开机时自动启动)详见仓库中的raspberry-pi/README.md文件。
入门指南
应用首次启动时会预置一些演示项目,因此仪表板不会为空。
挑战与我接下来需要改进的地方
目前的条形码到产品查询使用轻量级正则表达式解析,以避免依赖外部库;生产版本将采用标准的JSON库。保质期估算基于类别启发式方法,而非精确的过期日期——下一步可考虑对打印的过期日期进行OCR识别。当前数据仅存储在内存中;若能持久化至轻量级嵌入式数据库,则可确保食品柜在重启后仍能正常运行。食谱推荐功能可利用needsAttention()列表,推荐在物品过期前用完的食谱。
结论
PantryPal 是一个小型项目,但它很好地展示了 Java 的现代特性——密封类型、模式匹配、虚拟线程和结构化并发——如何让日常的并发状态问题更容易正确建模并清晰阅读,而无需依赖大型框架。
本文编译自hackster.io





