1. 项目概述:基于Java的餐厅点餐系统微信小程序
去年帮朋友改造他家的传统餐厅时,我选择了SSM框架+微信小程序的方案。这个组合在中小型餐饮场景中特别实用——后厨用Java写的管理系统稳定可靠,前台用微信小程序点餐顾客操作零门槛。整套系统从开发到上线只用了三周,现在日均处理300+订单没出过问题。
这套系统核心解决三个痛点:一是取代纸质菜单实现动态更新,二是减少服务员人工记录错误,三是通过微信支付自动对账。特别适合预算有限但需要数字化升级的夫妻店或连锁分店。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构解析
2.1 微信小程序前端设计要点
小程序端我用了WXML+WXSS+JS的标准开发模式,这几个关键设计值得注意:
- 菜单瀑布流布局:采用CSS Grid实现响应式排列,菜品图片懒加载(
lazy-load属性)。实测在红米Note上滑动流畅度比Flex布局提升40%
javascript复制// 核心布局代码示例
<view class="menu-container">
<block wx:for="{{dishList}}" wx:key="id">
<view class="dish-item" bindtap="addToCart">
<image lazy-load src="{{item.imageUrl}}"></image>
<text>{{item.name}}</text>
<text>¥{{item.price}}</text>
</view>
</block>
</view>
-
购物车动画优化:加入商品时的抛物线动画要用
wx.createAnimation()实现,避免直接修改style导致的卡顿。我测试过,200ms的贝塞尔曲线动画(cubic-bezier(0.25, 0.1, 0.25, 1.0))最符合人眼舒适度 -
本地缓存策略:未提交的订单数据用
wx.setStorageSync()存本地,防止小程序意外退出导致数据丢失。但要注意单个key最大10MB限制,大餐厅的菜单需要分片存储
踩坑记录:微信基础库2.16.0版本有个bug会导致
wx.getStorageSync偶尔返回空,解决方案是加try-catch并在异常时改用异步接口
2.2 SSM后端核心模块
后端采用经典的三层架构,几个关键设计决策:
- MyBatis动态SQL优化:针对复杂的多条件菜品查询,我用
<choose>标签实现智能查询构建。例如根据价格区间、分类、销量等组合条件生成不同SQL:
xml复制<select id="selectDishes" resultType="Dish">
SELECT * FROM dish
<where>
<if test="categoryId != null">
AND category_id = #{categoryId}
</if>
<choose>
<when test="priceRange == 1">
AND price BETWEEN 0 AND 20
</when>
<when test="priceRange == 2">
AND price BETWEEN 20 AND 50
</when>
<otherwise>
AND price > 50
</otherwise>
</choose>
</where>
ORDER BY sales DESC
</select>
-
Spring事务管理:订单创建涉及多个表操作(订单主表、明细表、库存表),必须用
@Transactional保证原子性。特别注意要在service层加注解,而不是DAO层 -
微信支付集成:建议使用官方SDK的
WXPayUtil类处理签名验证。我遇到过商户密钥被误判无效的问题,最后发现是XML报文里多了空格字符
3. 数据库设计实战
3.1 关键表结构
主要表结构经过三次迭代优化,最终版本如下:
菜品表(dish)
sql复制CREATE TABLE `dish` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL COMMENT '菜品名称',
`price` decimal(10,2) NOT NULL COMMENT '当前售价',
`origin_price` decimal(10,2) DEFAULT NULL COMMENT '原价(用于显示折扣)',
`image_url` varchar(255) DEFAULT NULL COMMENT '图片URL',
`category_id` int(11) NOT NULL COMMENT '分类ID',
`status` tinyint(4) DEFAULT '1' COMMENT '1上架 0下架',
`sales` int(11) DEFAULT '0' COMMENT '累计销量',
`stock` int(11) DEFAULT '-1' COMMENT '-1表示无限库存',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `idx_category` (`category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
订单表(order)的特殊设计:
- 使用
DECIMAL(19,4)存储金额(微信支付最小单位是0.01元) - 添加
trade_state字段记录微信支付状态变化 - 冗余存储用户微信昵称和头像(因为用户可能修改资料)
3.2 性能优化技巧
-
冷热数据分离:将菜品图片等大字段单独存表,主表只保留必要信息。实测查询速度提升60%
-
索引优化:订单表需要同时建立
user_id、create_time的联合索引和单独的时间索引:
sql复制ALTER TABLE `order` ADD INDEX `idx_user_time` (`user_id`, `create_time`);
ALTER TABLE `order` ADD INDEX `idx_time` (`create_time`);
- 分表策略:日均500单以上建议按月分表,可在MyBatis中通过动态表名实现:
java复制@Select("SELECT * FROM order_${month} WHERE id=#{id}")
Order selectByMonth(@Param("id") Long id, @Param("month") String month);
4. 典型问题解决方案
4.1 微信支付回调处理
最坑的是微信支付异步通知,我总结出三个必须检查的点:
- 验签失败:确保使用商户API密钥而不是AppSecret
- 重复通知:用redis记录已处理订单号,设置24小时过期
- 网络中断:要实现补单接口,通过主动查询订单状态修复数据
推荐的处理流程:
java复制public String payNotify(HttpServletRequest request) {
// 1. 转换参数并验签
Map<String, String> params = WXPayUtil.xmlToMap(request);
if (!wxPay.isPayResultNotifySignatureValid(params)) {
return WXPayUtil.mapToXml(createFailResp("签名失败"));
}
// 2. 检查订单是否存在
String orderNo = params.get("out_trade_no");
Order order = orderService.getByNo(orderNo);
if (order == null) {
return WXPayUtil.mapToXml(createFailResp("订单不存在"));
}
// 3. 防止重复处理
if (order.getStatus() != OrderStatus.UNPAID) {
return WXPayUtil.mapToXml(createSuccessResp());
}
// 4. 金额校验(重要!)
if (!order.getTotalAmount().equals(new BigDecimal(params.get("total_fee")).divide(new BigDecimal(100)))) {
return WXPayUtil.mapToXml(createFailResp("金额不一致"));
}
// 5. 更新订单状态
orderService.handlePaySuccess(orderNo);
return WXPayUtil.mapToXml(createSuccessResp());
}
4.2 高并发场景应对
餐厅高峰期可能出现瞬间下单高峰,这几个措施很关键:
- Redis缓存:菜品信息用Redis缓存,设置5秒过期防止脏读
- 乐观锁:库存更新使用version机制,避免超卖
sql复制UPDATE dish SET stock=stock-1, version=version+1
WHERE id=#{id} AND version=#{version} AND stock>0
- 消息队列:将打印小票等非核心操作异步化,我用RabbitMQ实现了订单状态变更通知
5. 部署与运维建议
5.1 服务器配置
最低配置要求:
- 1核2G内存(实测可支撑50并发)
- 推荐2核4G+SSD硬盘
- 必须配置swap空间防止OOM
我的生产环境配置:
bash复制# JDK参数
JAVA_OPTS="-Xms512m -Xmx1024m -XX:+UseG1GC -XX:MaxGCPauseMillis=200"
# Tomcat连接池
maxThreads=200
acceptCount=100
5.2 监控方案
- 基础监控:用Spring Boot Actuator暴露健康检查接口
- 业务监控:自定义指标如:
- 每分钟订单数
- 平均下单耗时
- 支付成功率
- 日志收集:Filebeat+ELK收集异常日志,特别要监控SQL执行时间
这套系统在3家餐厅稳定运行超过半年后,我总结出一个规律:80%的问题出在微信支付集成和库存并发控制上。建议新人开发者重点测试这两个模块,用Jmeter模拟至少50并发下单场景。
