首页 / 资讯中心 / 文章详情

无线点餐系统毕业设计:三层架构与订单状态机实战

无线点餐系统毕业设计:三层架构与订单状态机实战 ★ FEATURED ARTICLE
简介这份资源是面向计算机相关专业毕业生的毕业设计项目——无线点餐系统适合正在准备毕设、需要完整可运行案例的学生参考。项目以Android客户端为核心结合后台服务端实现餐桌管理、菜单浏览、下单与支付等餐饮场景功能帮助读者理解移动端与服务器端的数据交互流程。压缩包共365个文件约9.99MB包含75个java源文件、109个class编译文件、30个xml布局与配置、18个jar依赖包以及61张jpg与18张gif界面素材另有11个jsp页面、6份doc文档和apk安装包覆盖源码、资源、文档与可执行程序便于对照学习。目前已有239人学习下载。读者可从中获得一套结构完整的毕设参考方案包括客户端界面与业务逻辑、服务端Servlet处理、数据库文件及项目说明文档适合用来梳理系统架构、理解点餐业务流程并在此基础上进行功能扩展或二次开发。1. 无线点餐系统一份能直接跑起来的毕业设计工程每年到了毕业设计季后台总有人问同一个问题有没有那种不是PPT 项目、下载下来能真跑起来的完整工程这份无线点餐系统就是冲着这个需求来的。它把顾客扫码点餐、后厨接单、前台结账这条最典型的餐饮链路做成了一个可运行的完整项目技术栈覆盖前端页面、后端接口和数据库三层适合拿来做毕业设计的主体工程也适合想练手一个有真实业务闭环的开发者。你拿到手不是一堆散落的代码片段而是一个能启动、能下单、能改菜单的完整系统。下面我按它是什么、怎么跑、怎么改的顺序把这份工程拆开讲清楚。2. 系统架构与目录结构三层结构怎么落地2.1 整体技术选型与分层思路这类点餐系统的业务逻辑其实不复杂核心就是顾客端下单 → 服务端落库 → 后厨端拉单 → 前台结算这条链路。真正决定工程好不好用的是分层是否清晰。这份工程采用的是典型的前后端分离结构前端负责页面渲染和交互后端提供 REST 接口数据库存菜单、订单、桌台三类核心数据。常见做法是前端用 Vue 或原生 HTMLJS 搭页面后端用 Spring Boot 或 Node.js 提供接口数据库用 MySQL。这份工程按毕业设计的常见配置后端接口层、业务逻辑层、数据访问层是分开的这样你改菜单逻辑时不用动接口定义改接口时不用碰 SQL。分层带来的直接好处是答辩时老师问你这个订单状态怎么流转的你能指着 Service 层说清楚而不是在一坨代码里翻。从技术栈角度看需要你本地具备的能力是能跑 Java 或 Node 运行环境、能起一个 MySQL 实例、能用浏览器访问前端页面。这三样齐了工程就能转起来。下面这张表是我整理的核心模块与职责对应关系方便你先建立全局印象再往下看代码。模块职责典型文件位置顾客点餐端展示菜单、加购物车、提交订单frontend/customer后厨接单端拉取待处理订单、更新制作状态frontend/kitchen前台结算端查看桌台、结账、打印小票frontend/cashier接口服务层提供菜单/订单/桌台 REST 接口backend/controller业务逻辑层订单状态机、库存扣减、金额计算backend/service数据访问层菜单、订单、桌台表 CRUDbackend/mapper数据库脚本建表与初始菜单数据sql/init.sql2.2 目录结构逐层说明拿到源码包第一件事不是急着跑而是先看清目录。这份工程的目录大致是这样组织的wireless-ordering/ ├── frontend/ # 前端工程 │ ├── customer/ # 顾客扫码点餐页面 │ ├── kitchen/ # 后厨订单看板 │ ├── cashier/ # 前台结算页面 │ └── common/ # 公共样式与请求封装 ├── backend/ # 后端服务 │ ├── controller/ # 接口入口处理 HTTP 请求 │ ├── service/ # 业务逻辑订单状态流转在这 │ ├── mapper/ # 数据访问SQL 映射 │ ├── entity/ # 实体类对应数据库表 │ └── config/ # 数据库连接、跨域等配置 ├── sql/ │ └── init.sql # 建表语句 初始菜单数据 └── README.md # 启动说明这个结构的关键点在于controller / service / mapper三层是物理分开的。你改一个下单接口只需要动 controller 里对应的方法签名和 service 里的业务方法mapper 层基本不用碰。反过来如果菜单表加了一个辣度字段你只需要改 entity、mapper 的 SQL 和前端展示controller 的接口路径不变。这种改一处不影响全局的特性是判断一个毕业设计工程是否合格的重要标准也是你二次开发时最省心的地方。frontend/common里通常放的是请求封装比如统一带上 token、统一处理错误码。很多同学拿到工程后发现自己加的新页面请求不通八成是没走这个公共封装跨域或鉴权没带上。这一点后面避坑章节会细说。2.3 数据库表设计与订单状态机点餐系统的数据模型不复杂但订单状态机是灵魂。核心三张表menu菜单、orders订单主表、order_item订单明细。订单状态一般设计成枚举待接单、制作中、已完成、已结账。状态流转必须单向不能从已结账倒回制作中否则前台和后厨的数据就对不上了。-- 订单主表status 用整数枚举控制流转 CREATE TABLE orders ( id BIGINT PRIMARY KEY AUTO_INCREMENT, table_no VARCHAR(16) NOT NULL, -- 桌台号扫码时带入 status TINYINT NOT NULL DEFAULT 0, -- 0待接单 1制作中 2已完成 3已结账 total_price DECIMAL(10,2) NOT NULL, -- 下单时算好落库避免重复计算 created_at DATETIME DEFAULT CURRENT_TIMESTAMP ); -- 订单明细一个订单多条记录 CREATE TABLE order_item ( id BIGINT PRIMARY KEY AUTO_INCREMENT, order_id BIGINT NOT NULL, menu_id BIGINT NOT NULL, quantity INT NOT NULL, price DECIMAL(10,2) NOT NULL -- 下单时的单价快照 );这里有两个参数值得说清楚。total_price在下单时就计算好落库而不是每次查询时现算原因是菜单价格可能被后台修改如果现算会导致历史订单金额跟着变这是血泪经验。order_item.price存的是下单时的单价快照同理菜单涨价不影响已下单的订单。status用 TINYINT 而不是字符串是为了查询和索引效率前端展示时再做枚举映射。这三处设计看着小但决定了你后面改需求时会不会翻车。3. 本地跑通从建库到三个端能访问3.1 环境准备与数据库初始化跑这个工程本地需要三样东西运行环境Java 或 Node看后端用什么、MySQL 数据库、一个能开多个标签页的浏览器。先把 MySQL 起起来然后执行sql/init.sql。这一步很多人图快直接复制粘贴结果中文菜单变乱码所以建库时字符集要显式指定。# 登录 MySQL 后执行 mysql -u root -p # 建库时指定 utf8mb4避免中文菜单乱码 CREATE DATABASE ordering DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; # 导入建表与初始数据 mysql -u root -p ordering sql/init.sqlutf8mb4而不是utf8是因为后者在部分 MySQL 版本里只支持三字节遇到生僻字或 emoji 会报错。初始数据里一般会预置几张桌台和十几道菜导入成功后你可以SELECT * FROM menu;确认一下数据在不在。如果表建好了但菜单是空的多半是init.sql里的 INSERT 语句没执行到检查一下文件末尾有没有被截断。3.2 后端启动与接口自测数据库就绪后改后端配置文件里的数据库连接信息然后启动服务。以 Spring Boot 为例配置在application.yml里spring: datasource: url: jdbc:mysql://localhost:3306/ordering?useUnicodetruecharacterEncodingutf8mb4 username: root password: 你的密码 driver-class-name: com.mysql.cj.jdbc.Driver server: port: 8080启动命令按构建工具来Maven 项目就是mvn spring-boot:run或者直接跑打包后的 jar。启动成功后先用浏览器或接口工具访问一个最简单的接口验证比如GET http://localhost:8080/api/menu/list。能返回 JSON 数组说明数据库连通、接口层正常。这一步是整个跑通流程的分水岭接口通了前端问题都好排查接口不通先别碰前端回去看数据库连接和端口占用。提示如果启动报端口被占用先确认 8080 有没有被别的服务占着改server.port或关掉占用进程都行别硬重启浪费时间。3.3 三个前端端的访问与联调前端如果是纯静态页面直接用浏览器打开或起一个静态服务器即可如果是 Vue 工程npm install后npm run serve。三个端分别对应顾客、后厨、前台访问路径不同但共用同一套后端接口。联调时最典型的操作是顾客端下一单切到后厨端刷新看订单有没有出现后厨点开始制作再切前台看状态变没变。// frontend/common/request.js 里常见的请求封装 const BASE_URL http://localhost:8080/api; export function request(path, options {}) { return fetch(${BASE_URL}${path}, { headers: { Content-Type: application/json }, ...options }).then(res { if (!res.ok) throw new Error(请求失败: ${res.status}); return res.json(); }); }这个封装的作用是把后端地址集中到一处后面部署到服务器时只改BASE_URL一个地方。参数说明path是接口相对路径options透传 method、body 等。如果你新加的页面请求 404先确认路径有没有拼错、有没有走这个封装。三个端能各自打开、下单后数据能串起来这个工程就算真正跑通了接下来才是改。4. 核心模块拆解下单链路与状态流转代码4.1 下单接口从购物车到落库下单是整个系统最核心的一条链路涉及金额计算、明细写入、订单主表写入三步必须在一个事务里否则会出现主表有订单、明细是空的这种脏数据。下面这段是 Service 层的典型写法Service public class OrderService { Autowired private OrderMapper orderMapper; Autowired private OrderItemMapper orderItemMapper; Autowired private MenuMapper menuMapper; // 下单核心方法Transactional 保证主表与明细同时成功或同时失败 Transactional public Long createOrder(String tableNo, ListCartItem cart) { BigDecimal total BigDecimal.ZERO; ListOrderItem items new ArrayList(); for (CartItem c : cart) { Menu menu menuMapper.selectById(c.getMenuId()); if (menu null || menu.getStock() c.getQuantity()) { throw new RuntimeException(菜品不存在或库存不足); } // 单价快照防止后续改价影响历史订单 OrderItem item new OrderItem(); item.setMenuId(c.getMenuId()); item.setQuantity(c.getQuantity()); item.setPrice(menu.getPrice()); items.add(item); total total.add(menu.getPrice().multiply(new BigDecimal(c.getQuantity()))); } Orders order new Orders(); order.setTableNo(tableNo); order.setStatus(0); // 0 表示待接单 order.setTotalPrice(total); orderMapper.insert(order); // 插入后 order.getId() 回填 for (OrderItem item : items) { item.setOrderId(order.getId()); orderItemMapper.insert(item); } return order.getId(); } }逐段看循环里先查菜单、校验库存这一步是防止超卖的第一道闸item.setPrice(menu.getPrice())是单价快照前面数据库设计里强调过total用BigDecimal累加而不是 double是因为金额用浮点会算出19.999999这种玄学结果最后主表插入后order.getId()回填再批量写明细。参数上tableNo来自扫码时带上的桌台号cart是前端传的购物车数组。整个方法加了Transactional任何一步抛异常都会回滚这是保证数据一致性的后悔药。4.2 订单状态流转后厨与前台如何协同订单落库后状态是 0待接单后厨端拉取状态为 0 的订单点开始制作改成 1做完改成 2前台结账改成 3。状态更新接口要做的第一件事是校验当前状态防止重复点击或越级流转。// 状态流转只允许按 0-1-2-3 单向推进 public boolean updateStatus(Long orderId, int targetStatus) { Orders order orderMapper.selectById(orderId); if (order null) return false; int current order.getStatus(); // 只允许前进一格禁止跳级和回退 if (targetStatus ! current 1) { throw new RuntimeException(非法状态流转: current - targetStatus); } order.setStatus(targetStatus); return orderMapper.updateById(order) 0; }这段代码的关键是targetStatus ! current 1这个判断。没有它后厨手快点两下开始制作状态可能从 0 直接跳到 2前台看到已完成却根本没出餐这就是典型的翻车现场。参数targetStatus由前端按钮决定但真正的合法性判断必须在后端做前端按钮只是引导不能当保险。后厨端拉单的查询也很简单SELECT * FROM orders WHERE status 0 ORDER BY created_at ASC先到先做符合餐饮场景的实际节奏。4.3 菜单管理增删改查与前端联动菜单是唯一需要频繁改动的数据后台管理页面对应一组 CRUD 接口。这里要注意的是删除策略菜单一旦被历史订单引用物理删除会导致订单明细查不到菜名。常见做法是加一个is_deleted软删除标记查询时过滤掉。-- 软删除保留历史订单的关联完整性 UPDATE menu SET is_deleted 1 WHERE id ?; -- 顾客端只查未删除且在售的菜品 SELECT id, name, price, stock, image_url FROM menu WHERE is_deleted 0 AND on_sale 1 ORDER BY category_id, id;is_deleted和on_sale是两个不同概念前者是这道菜从系统里下架了后者是暂时售罄。前端顾客端只展示on_sale 1的后台管理能看到全部未删除的。这个区分在答辩时是个加分点说明你考虑过数据生命周期。菜单改动后前端不刷新是常见现象因为很多实现里菜单是页面加载时拉一次改完要手动刷新或加轮询这一点在下一章的排查里会提到。5. 避坑与常见问题排查5.1 中文菜单乱码现象数据库里菜单名显示正常但前端页面显示成问号或方块。原因通常是数据库、连接串、页面三处字符集不一致最常见的是建库时用了utf8而连接串没指定characterEncoding。解决建库用utf8mb4JDBC 连接串加useUnicodetruecharacterEncodingutf8mb4前端页面meta charsetutf-8三处对齐后重启服务。改完记得清一下浏览器缓存不然看到的还是旧页面。5.2 前端请求跨域被拦现象浏览器控制台报 CORS 错误接口单独访问正常页面里请求失败。原因前端和后端端口不同浏览器同源策略拦截。解决后端加跨域配置允许前端来源。Spring Boot 里加一个配置类或在 controller 上加CrossOrigin开发阶段图省事可以放开所有来源但上线前要收紧到具体域名这个习惯我建议从毕设阶段就养成。5.3 下单后后厨端看不到订单现象顾客端提示下单成功后厨端刷新没有新订单。原因通常有两个一是后厨端查询条件写死了某个状态值而下单落库的状态和它不一致二是后厨端页面没有轮询或手动刷新机制数据是打开页面那一刻的快照。解决先直接查数据库确认订单在不在、状态对不对再看后厨端的查询 SQL。如果数据在但页面不显示就是前端刷新问题加个定时拉取或手动刷新按钮即可。5.4 金额出现小数误差现象订单总价出现0.30000000000000004这类结果。原因用 double 或 float 做金额运算。解决全链路改用BigDecimal数据库字段用DECIMAL(10,2)前端展示时再格式化。这个坑在答辩演示时特别容易暴露因为老师往往会盯着金额看提前改掉能省不少尴尬。5.5 端口冲突导致启动失败现象后端启动报Port 8080 was already in use。原因上一次启动的进程没退干净或者本机有其他服务占了端口。解决先查占用进程并结束或者直接改server.port换一个端口同时记得同步改前端BASE_URL里的端口号否则前端会请求到旧端口上表现为服务起来了但页面全报错。6. 二次开发把毕设改成能讲出亮点的作品拿到这份工程最忌讳的是原封不动交上去。答辩老师看一眼就知道是模板真正拉开差距的是你改了什么、为什么改。我的建议是从三个方向动手每个方向都能讲出技术点。第一个方向是加桌台状态看板。现在前台只能看订单看不到哪些桌台在用、哪些空着。你可以在orders表基础上加一个桌台状态查询接口按table_no聚合出有未结账订单即占用的逻辑前台页面用不同颜色区分。这个改动涉及一次聚合查询和前端状态渲染工作量不大但演示效果直观。第二个方向是把轮询改成 WebSocket 推送。现在后厨端靠刷新或定时拉取体验一般。加一个 WebSocket 端点下单成功后服务端主动推给后厨端这是能写进论文系统优化章节的实打实改进。改造时注意连接管理和断线重连别为了演示效果把稳定性丢了。第三个方向是补一层简单的权限。现在三个端谁都能访问加一个基于角色的登录顾客扫码免登录、后厨和前台要登录。用拦截器校验请求头里的 token 即可不用上重型框架。这一步能让你的系统从能跑变成像个真系统。改造方向涉及模块难度答辩可讲点桌台状态看板订单查询 前台页面低聚合查询、状态可视化WebSocket 推送后端 后厨端中实时通信、连接管理角色权限拦截器 登录页中鉴权流程、token 校验改造完一定要自己走一遍完整链路验证下单 → 后厨接单 → 制作完成 → 前台结账每一步都确认数据对得上。我见过太多人改完一个模块就急着演示结果结账时金额对不上当场卡壳。从那以后我每次改完核心链路都强制自己从下单走到结账完整跑一遍再去看边角功能。这份工程的价值不在于它多复杂而在于它给了你一个能改、改完能验证的底座剩下的亮点靠你自己往上加。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站