拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Spring Boot构建餐饮点餐收银系统:从订单到后厨的一体化实战

1. 先搞清楚“一体化”到底要解决什么别急着写代码如果你正在为一家中小型餐饮店铺比如快餐店、奶茶店、小餐馆设计点餐收银系统最该关注的不是用了什么框架而是这个“一体化”系统能不能把前厅点餐、后厨制作、前台收银这几个环节真正串起来并且让老板和店员都能用起来不费劲。很多人一上来就琢磨 Spring Boot 怎么配置、Vue 怎么分离结果做出来的系统功能很全但一到实际营业高峰期就卡顿或者后厨打印不出单子又或者收银对账一团乱。所以这个主题的核心价值在于用一个轻量、稳定、易维护的技术栈实现从前台点单到后厨出单再到收银结算的完整业务闭环并且能应对店铺日常运营中的各种小麻烦。基于 Spring Boot 来做优势很明显快速开发、内嵌 Tomcat、约定大于配置非常适合中小型单体应用。但难点也很突出如何设计数据库才能同时高效处理订单流水和库存变化如何保证收银时计算优惠、折扣、抹零的准确性如何让后厨打印稳定可靠这些才是决定项目成败的关键而不是框架本身。我建议动手之前先把下面这几个问题想清楚谁是主要用户是顾客扫码点餐还是服务员用平板点餐还是两者都有核心业务流程是什么从创建订单、后厨接单、出品完成到收银结算每一步状态怎么变钱和账怎么管优惠券、会员折扣、整单抹零这些计算逻辑放在哪一层日结报表怎么生成硬件怎么对接需要连接小票打印机、扫码枪吗网络不稳定时怎么办想明白这些你的数据库表和接口设计就有了方向代码也不会写飞。下面我就按照一个真实店铺从零搭建系统的思路带你拆解每个环节。2. 环境与基础框架搭建选对版本避开初期大坑开始写代码前环境搭建这一步如果没做对后面会冒出各种稀奇古怪的问题。特别是 Spring Boot 版本选择和相关依赖。2.1 开发环境与工具链选择对于餐饮系统这种对实时性有一定要求但并发量不会特别巨大的项目我一般会选择Spring Boot 2.x 的稳定版本比如2.7.x或3.0.x如果你确定所有依赖都兼容。Spring Boot 4.x 对于新项目来说可能过于前沿一些老牌的中间件依赖可能还没完全适配容易踩坑。开发工具IntelliJ IDEA 社区版就足够它创建和管理 Spring Boot 项目非常方便。如果遇到“新建项目没有 Spring Boot 3.4.3 选项”通常是 IDEA 的 Spring Initializr 服务列表没更新可以手动指定https://start.spring.io的地址来解决。项目管理Maven 或 Gradle 都可以看团队习惯。Maven 的pom.xml配置文件更普遍教程也多。数据库MySQL 8.0 或 PostgreSQL。餐饮系统数据关系比较清晰但订单、商品、库存表之间的关联查询和更新会频繁事务一致性要求高。缓存Redis几乎是必选项。不是用来做消息队列虽然Redis Stream可以主要是缓存菜单数据、购物车、会话信息和当日的热门商品极大减轻数据库压力。消息中间件如果后厨分热菜、冷菜、饮品多个区域可能需要异步通知。用Redis Pub/Sub或RabbitMQ就够Spring Boot 整合 ActiveMQ现在用得相对少了。Spring Boot MQTT更适合物联网设备餐饮打印用不上。一个建议的pom.xml核心依赖配置parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.7.18/version !-- 选择一个长期支持的版本 -- /parent dependencies !-- Web核心 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency !-- 数据访问 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-jpa/artifactId !-- 或用MyBatis -- /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId scoperuntime/scope /dependency !-- 缓存 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-redis/artifactId /dependency !-- 消息队列 (可选按需引入) -- !-- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-amqp/artifactId /dependency -- !-- 工具 -- dependency groupIdorg.projectlombok/groupId artifactIdlombok/artifactId optionaltrue/optional /dependency !-- 测试 -- dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-test/artifactId scopetest/scope /dependency /dependencies2.2 项目结构与配置要点不要一上来就追求微服务。对于单个店铺一个结构清晰的单体应用更容易维护。src/main/java/com/yourstore/ ├── config/ # 配置类Redis、MQ、Web等 ├── controller/ # 控制器订单、商品、收银等API入口 ├── service/ # 业务逻辑层 │ ├── impl/ # 实现类 ├── repository/ # 数据访问层 (JPA) 或 mapper/ (MyBatis) ├── entity/ # 实体类对应数据库表 ├── dto/ # 数据传输对象用于API出入参 ├── enums/ # 枚举类订单状态、支付方式等 ├── utils/ # 工具类 └── Application.java # 启动类在application.yml里除了配数据库和 Redis有几个餐饮场景特有的配置要留心spring: datasource: url: jdbc:mysql://localhost:3306/restaurant_db?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: yourpassword hikari: maximum-pool-size: 10 # 连接池不用太大根据实际并发调整 redis: host: localhost port: 6379 database: 0 timeout: 2000ms # 设置超时防止网络波动导致线程阻塞 jackson: time-zone: GMT8 date-format: yyyy-MM-dd HH:mm:ss # 自定义配置 app: printer: retry-times: 3 # 打印失败重试次数 order: auto-cancel-minutes: 30 # 订单未支付自动取消时间(分钟)注意关于“信创”和“东方通TongWeb”如果你的项目有国产化要求需要部署在麒麟系统等信创环境中那么将 Spring Boot 内嵌的 Tomcat 替换为 TongWeb 等国产应用服务器是常见的适配步骤。但这属于部署阶段的工作开发时依然用内嵌 Tomcat 进行确保功能正确后再进行容器替换和兼容性测试。3. 核心业务模块设计与实现订单、后厨、收银的联动这是系统的中枢神经。设计不好要么数据混乱要么流程卡死。3.1 数据库设计围绕订单生命周期表不在多在于能否清晰反映业务状态流转。核心表至少有这几张商品表 (product)id,name,category_id,price,status(上架/下架),stock(库存对于按份卖的菜很重要)。订单主表 (order_master)order_id,table_number(桌号),customer_count(人数),order_amount(总金额),discount_amount(优惠金额),real_amount(实收),order_status(关键字段0-待支付1-已支付2-后厨已接单3-制作中4-已完成5-已取消),pay_type,create_time。订单明细表 (order_detail)detail_id,order_id,product_id,product_name(快照),product_price(快照),product_quantity,detail_status(可独立标记某道菜的制作状态)。后厨任务表 (kitchen_task)task_id,order_id,detail_id,product_name,quantity,task_status(0-待制作1-制作中2-制作完成),printer_id,create_time。这张表是连接前台订单和后厨生产的桥梁。为什么要把后厨任务单独拆出来因为一个订单可能包含多个菜品它们可能在不同厨位制作状态更新独立。直接更新order_detail虽然可以但混入了业务逻辑不利于扩展比如未来想加一个“催菜”功能。3.2 订单创建与后厨通知事务与消息顾客点餐无论是扫码还是服务员操作前端提交商品列表。后端接口逻辑参数校验检查商品是否存在、是否上架、库存是否充足。开启数据库事务。创建订单主表记录状态为“待支付”。批量创建订单明细记录。扣减库存如果商品是有限库存的如特价菜。这里注意使用乐观锁或update table set stock stock - ? where id ? and stock ?防止超卖。生成后厨任务。注意通常只有支付成功后才真正生成后厨任务。但有些店铺流程是“下单即通知后厨准备”这需要在业务逻辑上明确。我们按“支付后通知”来设计。事务提交。支付成功后的回调接口或服务内支付成功方法中更新订单状态为“已支付”。异步生成后厨任务插入kitchen_task表。触发打印或推送消息。这里可以用事件机制。在 Spring Boot 中可以定义一个OrderPaidEvent事件在支付成功后发布 (ApplicationEventPublisher.publishEvent)。然后编写一个KitchenTaskGenerator监听这个事件负责生成任务和调用打印服务。// 简化示例支付成功后的服务方法 Transactional public void confirmOrderPayment(String orderId) { OrderMaster order orderRepository.findById(orderId).orElseThrow(...); if (order.getOrderStatus().equals(OrderStatusEnum.NEW.getCode())) { // 1. 更新订单状态 order.setOrderStatus(OrderStatusEnum.PAID.getCode()); orderRepository.save(order); // 2. 发布支付成功事件 applicationEventPublisher.publishEvent(new OrderPaidEvent(this, orderId)); } } // 事件监听器异步处理 Component Slf4j public class KitchenTaskGenerator { EventListener Async // 使用异步执行不阻塞主线程 public void handleOrderPaidEvent(OrderPaidEvent event) { String orderId event.getOrderId(); // 查询订单明细 ListOrderDetail detailList orderDetailRepository.findByOrderId(orderId); // 生成后厨任务记录 ListKitchenTask tasks detailList.stream().map(detail - convertToTask(detail)).collect(Collectors.toList()); kitchenTaskRepository.saveAll(tasks); // 调用打印服务 printerService.printTasks(tasks); log.info(订单{}后厨任务已生成并发送打印, orderId); } }3.3 收银结算精度、优惠与对账收银台的核心是算对钱。所有金额计算必须用BigDecimal禁止用Double。结算接口逻辑接收订单ID和可能的优惠信息会员折扣码、满减活动ID。重新计算订单总金额基于商品快照价防止中途调价。应用优惠这里逻辑可能复杂要按店铺规则来。例如先计算会员折扣再判断是否满足满减最后可能还有整单抹零。每一步计算都要保留明细方便对账。计算实收金额。记录支付方式现金、微信、支付宝、银行卡。更新订单状态为“已完成”。注意更新订单状态和记录支付流水应该在同一个事务中。日结对账每天营业结束后需要生成日报表。可以跑一个定时任务使用 SpringScheduled统计当日所有已支付订单按支付方式汇总金额并与收银员的交款记录核对。报表数据可以缓存到 Redis前端收银界面能实时显示今日概况营业额、订单数、热门商品。4. 关键细节与生产环境考量功能跑通只是第一步要能稳定用在店里下面这些细节一个都不能放过。4.1 后厨打印的稳定性这是系统最可能出故障的点。网络抖动、打印机缺纸、卡纸都会导致打印失败。设计重试机制在打印服务中集成重试逻辑配置app.printer.retry-times。连续失败后要将任务标记为“打印失败”并在后厨的终端界面上有醒目提示允许手动重打。异步打印如上文所述打印不要放在下单的主线程里要用事件或消息队列异步处理避免因为打印慢导致下单接口超时。打印队列如果有多台打印机热菜、冷饮需要根据菜品分类将任务投递到不同的队列。可以用 Redis 的 List 结构实现简单队列。4.2 库存管理的实时性对于按份销售的菜品库存扣减是个并发问题。下单扣库存顾客下单时预扣支付失败或取消订单时回滚。这能防止超卖但逻辑复杂。支付扣库存只有支付成功才扣减。更简单但可能遇到“最后一个菜被两个人同时支付”的情况概率低但需考虑。可以在支付回调里用数据库行级锁或Redis 分布式锁确保扣减的原子性。// 使用Redis分布式锁确保扣库存原子性 public boolean decreaseStock(String productId, Integer quantity) { String lockKey lock:product:stock: productId; String requestId UUID.randomUUID().toString(); try { // 尝试获取锁 Boolean locked redisTemplate.opsForValue().setIfAbsent(lockKey, requestId, 10, TimeUnit.SECONDS); if (Boolean.TRUE.equals(locked)) { // 查询当前库存 Product product productRepository.findById(productId).orElseThrow(...); if (product.getStock() quantity) { product.setStock(product.getStock() - quantity); productRepository.save(product); return true; } return false; // 库存不足 } return false; // 获取锁失败 } finally { // 释放锁确保是同一个请求释放的 if (requestId.equals(redisTemplate.opsForValue().get(lockKey))) { redisTemplate.delete(lockKey); } } }4.3 前端交互与部署前端选择如果主要是店员使用一个响应式的管理后台用 Vue/React Element UI/Ant Design就够了。如果支持顾客扫码点餐则需要额外开发微信小程序或 H5 页面。这就是“微信小程序校园点餐系统”的类似场景。前后端分离Spring Boot 只提供 RESTful API前端通过 Axios 等库调用。注意配置 CORS 解决跨域问题。部署开发/测试直接打可执行 JAR 包 (mvn clean package)用java -jar your-app.jar运行。生产环境建议用Docker容器化部署环境一致性好。编写 Dockerfile将 JAR 包打包成镜像。更进阶可以用Jenkins Gitea做自动化 CI/CD。高可用单个店铺通常不需要 K8s但如果有多家分店需要统一管理可以考虑微服务化和 K8s 部署但那完全是另一个复杂度了。4.4 安全与监控基础安全使用 Spring Security 管理后台登录权限。API 接口根据角色店长、收银员、后厨进行鉴权。输入安全防止 XSS 和 SQL 注入。Spring Boot 和 MyBatis/JPA 本身有一定防护但用户输入的商品名、备注等仍需在后端做过滤或转义。对于文件上传如上传菜谱图片要限制文件类型和大小。监控接入Spring Boot Admin可以很方便地监控应用健康状态、日志和度量指标。对于订单量、支付成功率等业务指标可以埋点记录到数据库或时序库中。5. 常见问题排查清单系统上线后遇到问题按照这个顺序查能解决大部分情况订单提交失败先看日志检查后端应用日志看是参数验证错误、数据库异常还是网络问题。查数据库连接确认数据库服务是否正常连接池是否耗尽。查库存确认商品库存是否充足。后厨打印机没反应先看打印任务表kitchen_task表里有没有生成新记录状态是什么查打印服务日志打印服务是否被调用网络是否能通到打印机IP检查打印机状态电源、纸张、网络线、驱动。最简单的方法用电脑直接打印测试页。收银金额对不上核对订单流水查order_master表对比order_amount原价、discount_amount优惠、real_amount实收。检查优惠计算逻辑。核对支付流水是否有支付成功但订单状态未更新的情况支付回调处理失败检查并发操作是否有多人同时操作同一张订单关键业务方法要加锁或使用数据库事务隔离级别。系统运行越来越慢查数据库慢查询开启 MySQL 慢查询日志分析哪些 SQL 慢了。通常是订单查询报表的JOIN没加索引。查 Redis 内存是否缓存了过多不必要的数据缓存键设计是否合理查应用服务器资源CPU、内存是否吃紧用top或jvisualvm工具查看。前端页面显示异常看浏览器控制台Network 标签页查看 API 请求是否返回错误4xx, 5xx。Console 标签页看 JS 报错。核对 API 接口前端调用的接口地址、参数格式是否与后端一致特别是 POST 请求的Content-Type。6. 从“能用”到“好用”的优化思路当基础功能稳定后可以考虑下面这些优化点让系统更贴合实际运营套餐与口味定制在order_detail表增加remarks字段记录顾客口味如“免葱”、“加辣”设计套餐表支持组合商品。桌台管理增加table表图形化展示桌台状态空闲、用餐中、待清洁支持并台、换台。会员与营销集成会员系统储值、积分支持丰富的营销活动秒杀、团购、优惠券这些对计算逻辑的灵活性要求很高。数据统计与分析除了日报增加商品销量排行、时段客流分析、顾客消费画像等为经营决策提供支持。离线与容灾考虑极端情况网络断了怎么办可以设计一个“离线模式”订单暂存本地网络恢复后自动同步。这需要前端如小程序和后端都有相应的处理机制。最后想说的是做一个餐饮点餐收银系统技术选型Spring Boot只是地基真正的挑战在于对业务流程的深刻理解和细节打磨。先确保核心的“下单-支付-出单-收银”闭环稳定可靠再根据店铺的实际需求去添加会员、营销、数据分析这些“增值功能”。在开发过程中多和潜在的店员、店长沟通他们的一个痛点提示可能比你埋头写一周代码的价值更大。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门