1. 项目背景与核心价值
校园食堂的用餐高峰期总是人满为患,学生们排着长队等待点餐和取餐的场景几乎成了每个大学的日常。这种传统的就餐模式存在几个明显的痛点:排队时间长导致用餐效率低下、人工点单容易出错、食堂难以精准预估食材用量造成浪费。而微信点餐小程序恰好能解决这些问题——学生可以提前在手机上浏览菜单、下单支付,食堂则能根据订单数据优化备餐流程。
这个毕业设计项目采用SSM(Spring+SpringMVC+MyBatis)作为后端框架,VUE.js构建前端界面,最终打包成微信小程序。这种技术组合在当前企业级应用开发中非常主流:SSM框架提供了稳健的后台服务能力,VUE则让前端开发更加高效,而微信小程序平台则免去了App安装的麻烦。对计算机专业的学生来说,完成这样一个项目能全面锻炼全栈开发能力,从数据库设计、API接口编写到前端交互实现,覆盖了软件开发的全生命周期。
提示:选择微信小程序而非原生App可以大幅降低用户使用门槛,学生无需下载安装,扫码即用,这对食堂这种高频但低粘性的场景特别合适。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术架构设计解析
2.1 后端SSM框架搭建
SSM框架组合是Java Web开发的经典选择。在这个项目中,Spring 5.x作为容器管理各类Bean,通过IoC和AOP实现松耦合;SpringMVC处理HTTP请求,采用RESTful风格设计API接口;MyBatis 3.x作为ORM框架,配合PageHelper插件实现数据分页。数据库选用MySQL 8.0,主要考虑到校园场景下数据量不会特别大,且MySQL的部署和维护相对简单。
一个典型的项目包结构如下:
code复制src/
├── main/
│ ├── java/
│ │ └── com/
│ │ └── campus/
│ │ ├── config/ # Spring配置类
│ │ ├── controller/ # 控制器层
│ │ ├── service/ # 业务逻辑层
│ │ ├── dao/ # 数据访问层
│ │ └── entity/ # 实体类
│ ├── resources/
│ │ ├── mapper/ # MyBatis映射文件
│ │ ├── application.yml # 应用配置
│ │ └── application-dev.yml # 开发环境配置
│ └── webapp/
└── test/ # 单元测试
2.2 前端VUE技术选型
前端采用VUE 3.x + Vant Weapp组件库的组合。VUE的响应式特性非常适合点餐这种需要频繁更新视图的场景,而Vant Weapp提供了丰富的微信小程序UI组件,能快速构建出美观的界面。项目使用Vue CLI初始化,通过配置vue.config.js实现多环境打包。
关键依赖包括:
javascript复制"dependencies": {
"vue": "^3.2.0",
"vue-router": "^4.0.0",
"axios": "^0.21.0",
"vant-weapp": "^1.0.0",
"weui-miniprogram": "^1.0.0"
}
3. 核心功能模块实现
3.1 微信小程序登录与授权
微信生态下的用户身份识别是小程序开发的第一道门槛。我们采用微信官方提供的登录流程:
- 前端调用wx.login()获取临时code
- 将code发送到后端API
- 后端用appid+secret+code向微信服务器换session_key和openid
- 后端生成自定义登录态(token)返回给前端
- 前端存储token用于后续接口鉴权
关键代码示例(后端):
java复制@RestController
@RequestMapping("/api/auth")
public class AuthController {
@Value("${wechat.appid}")
private String appid;
@Value("${wechat.secret}")
private String secret;
@PostMapping("/login")
public ResultVO login(@RequestParam String code) {
String url = "https://api.weixin.qq.com/sns/jscode2session?" +
"appid=" + appid +
"&secret=" + secret +
"&js_code=" + code +
"&grant_type=authorization_code";
// 使用RestTemplate调用微信接口
String response = restTemplate.getForObject(url, String.class);
JSONObject json = JSON.parseObject(response);
if(json.containsKey("errcode")) {
return ResultVO.error("登录失败: " + json.getString("errmsg"));
}
String openid = json.getString("openid");
String sessionKey = json.getString("session_key");
// 生成并存储token逻辑...
return ResultVO.success(token);
}
}
3.2 菜品展示与购物车功能
菜品数据通过后端API获取,前端用VUE的v-for指令渲染列表。考虑到性能,我们实现了分页加载:
javascript复制// 前端分页加载逻辑
const loadMore = () => {
if(loading || finished) return;
loading = true;
axios.get('/api/dishes', {
params: {
page: currentPage,
size: pageSize
}
}).then(res => {
dishes.value = [...dishes.value, ...res.data.list];
currentPage++;
if(res.data.list.length < pageSize) {
finished = true;
}
}).finally(() => {
loading = false;
});
};
购物车采用Vuex进行状态管理,核心store模块:
javascript复制const store = createStore({
state() {
return {
cartItems: [],
totalPrice: 0
}
},
mutations: {
addToCart(state, dish) {
const item = state.cartItems.find(i => i.id === dish.id);
if(item) {
item.quantity++;
} else {
state.cartItems.push({...dish, quantity: 1});
}
state.totalPrice += dish.price;
},
// 其他购物车操作方法...
}
});
4. 数据库设计与优化
4.1 主要表结构设计
sql复制-- 菜品表
CREATE TABLE `dish` (
`id` bigint NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL COMMENT '菜品名称',
`price` decimal(10,2) NOT NULL COMMENT '价格',
`stock` int NOT NULL DEFAULT '0' COMMENT '库存',
`category_id` int NOT NULL COMMENT '分类ID',
`image_url` varchar(255) DEFAULT NULL COMMENT '图片URL',
`description` varchar(255) DEFAULT NULL COMMENT '描述',
`status` tinyint NOT NULL DEFAULT '1' COMMENT '状态:0下架 1上架',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 订单表
CREATE TABLE `order` (
`id` bigint NOT NULL AUTO_INCREMENT,
`order_no` varchar(32) NOT NULL COMMENT '订单编号',
`user_id` varchar(64) NOT NULL COMMENT '用户openid',
`total_amount` decimal(10,2) NOT NULL COMMENT '订单总额',
`status` tinyint NOT NULL DEFAULT '0' COMMENT '状态:0待支付 1已支付 2已取消',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`pay_time` datetime DEFAULT NULL COMMENT '支付时间',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_order_no` (`order_no`),
KEY `idx_user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
4.2 查询性能优化
针对高并发的菜品查询接口,我们做了以下优化:
- 添加合适的索引:在category_id、status字段上建立组合索引
- 使用MyBatis二级缓存,配置如下:
xml复制<cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>
- 热点数据预加载:在系统启动时,将分类信息等不常变的数据加载到Redis
- 分页查询使用PageHelper插件,避免内存分页
5. 项目部署与上线
5.1 后端部署方案
推荐使用Docker容器化部署,Dockerfile示例:
dockerfile复制FROM openjdk:8-jdk-alpine
VOLUME /tmp
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
部署步骤:
- 使用Maven打包:
mvn clean package -DskipTests - 构建Docker镜像:
docker build -t campus-food . - 运行容器:
docker run -d -p 8080:8080 --name food campus-food
5.2 小程序发布流程
- 在微信公众平台申请小程序账号
- 配置合法域名(后端API地址)
- 使用微信开发者工具上传代码
- 提交审核(需准备完整测试账号)
- 审核通过后发布
注意:微信小程序对网络请求有严格限制,所有接口必须使用HTTPS,且域名需备案。开发阶段可在微信开发者工具中勾选"不校验合法域名"选项。
6. 毕业设计扩展建议
如果想在基础功能上做出亮点,可以考虑以下扩展方向:
- 智能推荐系统:基于用户历史订单数据,使用协同过滤算法推荐可能喜欢的菜品
- 食堂人流热力图:通过订单数据预测各时段人流密度,帮助学生错峰就餐
- 营养分析功能:为每道菜标注营养成分,计算整单的营养摄入量
- 社交化功能:允许学生分享美食照片,点赞评论形成互动
- 订单实时追踪:接入WebSocket实现从下单到取餐的全流程状态更新
实现智能推荐的简单示例(基于用户的协同过滤):
java复制public List<Dish> recommendDishes(String userId) {
// 1. 找出与当前用户口味相似的其他用户
List<String> similarUsers = findSimilarUsers(userId);
// 2. 获取这些用户喜欢但当前用户未点过的菜品
List<Dish> candidateDishes = getUnorderedDishes(userId, similarUsers);
// 3. 计算推荐得分并排序
return candidateDishes.stream()
.sorted((d1, d2) ->
Double.compare(calculateRecommendScore(userId, d2),
calculateRecommendScore(userId, d1)))
.limit(5)
.collect(Collectors.toList());
}
7. 常见问题与调试技巧
7.1 微信登录失败排查
如果遇到微信登录接口返回错误,可以按照以下步骤排查:
- 检查appid和secret是否正确(特别注意是否混淆了小程序的appid和服务号的appid)
- 确认服务器IP已加入微信公众平台的白名单
- 检查服务器时间是否准确(误差不能超过2分钟)
- 临时code只能使用一次且有效期5分钟
- 确保网络请求走的是HTTPS协议
7.2 VUE开发调试技巧
- 使用Chrome的Vue Devtools插件检查组件状态
- 在vue.config.js中配置代理解决跨域:
javascript复制devServer: {
proxy: {
'/api': {
target: 'http://localhost:8080',
changeOrigin: true
}
}
}
- 善用console.log调试,但记得在生产环境移除
- 使用VUE的errorHandler全局捕获错误:
javascript复制app.config.errorHandler = (err, vm, info) => {
console.error(`Error: ${err.toString()}\nInfo: ${info}`);
// 可以上报错误到服务器
};
8. 项目文档编写要点
毕业设计除了代码实现,文档同样重要。建议包含以下内容:
- 需求分析:详细描述项目背景、用户角色、功能需求和非功能需求
- 系统设计:架构图、模块划分、数据库ER图、接口设计
- 核心算法:如推荐算法、订单超时处理等复杂逻辑的说明
- 测试报告:单元测试覆盖率、接口测试用例、压力测试结果
- 部署手册:环境要求、安装步骤、配置说明
- 用户手册:小程序使用指南,最好配截图
文档撰写工具推荐:
- 架构图:Draw.io或Lucidchart
- 接口文档:Swagger UI或YApi
- 论文排版:LaTeX或Word样式模板
我在实际开发中发现,保持代码与文档同步非常重要。推荐使用Swagger自动生成API文档,在Java代码中添加注解即可:
java复制@ApiOperation("获取菜品列表")
@GetMapping("/dishes")
public ResultVO<List<DishVO>> listDishes(
@ApiParam(value = "分类ID", required = false)
@RequestParam(required = false) Integer categoryId,
@ApiParam(value = "页码", defaultValue = "1")
@RequestParam(defaultValue = "1") Integer page,
@ApiParam(value = "每页数量", defaultValue = "10")
@RequestParam(defaultValue = "10") Integer size) {
// 方法实现...
}
