SpringBoot+Vue校园美食推荐系统开发实战:从协同过滤到毕业设计答辩
把《基于SpringBoot的校园周边美食推荐系统》做成一份能演示、能答辩、能顺利毕业的作品核心不在把代码写得有多炫而是把业务逻辑讲清楚、把推荐功能做真、把前后端联调跑通。我见过不少学生选了 SpringBoot Vue 这套组合最后卡在环境配置、接口跨域、推荐逻辑太单薄这三个地方。这篇文章会按实际开发顺序拆一遍先确认系统到底要做什么再定技术栈然后讲推荐算法怎么落地接着补数据库设计、前后端代码组织、论文开题报告和答辩准备。适合准备做这道毕业设计的同学也适合想用 SpringBoot Vue 完整走一遍全栈推荐系统开发的人。先说明一点材料里提到的“源码、论文、开题”都是这类项目常见的交付物很多同学拿到一个现成项目源码后反而不清楚系统结构为什么这样设计。其实只要理解了系统的角色、数据流和推荐逻辑代码能不能跑通只是时间问题。我更建议你把“理解系统”放在第一位把“运行代码”放在第二位。1. 先搞清楚这个毕业设计到底要做什么1.1 它解决的是校园里真实存在的找吃问题校园周边美食推荐系统的业务场景其实很常见学生校园生活范围有限食堂吃久了想换口味校外店铺多得眼花评价数据又分散在大众点评、美团、小红书各个平台学生群体有自己独特的偏好比如性价比优先、离宿舍近优先、适合宿舍聚餐等。所以系统要解决的问题就是把校园周边的餐厅、小吃店、奶茶店等信息统一管理起来再根据学生的偏好、收藏、评分行为给每个用户推荐合适的美食店铺。这个题目在毕业设计里属于“业务管理系统 推荐算法”的经典组合。你不必做一个像大平台那样复杂的推荐系统但至少要做到用户能登录、能浏览、能搜索、能收藏、能评分、能看推荐结果管理员能管理商家和菜品商家能维护自己的店铺信息。这三条角色主线全部跑通系统在验收角度就已经完整了。1.2 系统给三类角色分别提供什么很多同学一上来就把表结构设计得很复杂角色拆得很细结果开发两三个月还没做完。我更建议第一版只做三个角色把核心闭环打通。用户端学生注册、登录、个人信息维护浏览美食列表、搜索、按分类筛选查看商家详情、菜单、评价收藏、点赞、评分查看系统给自己生成的推荐结果商家端商家入驻和登录维护店铺信息、菜品信息查看自己店铺的评分和用户评论可选简单的订单或预约管理管理端用户管理商家审核和管理分类、标签管理推荐规则或热门榜单配置可选基础数据统计这里有一个很重要的判断标准毕业设计系统不是功能越多越好而是“说得清楚、演示得顺畅、代码结构清晰”最重要。如果你把三个角色之间的操作闭环演示一遍从注册到推荐再到评分整个项目就已经有说服力了。2. 技术栈选型为什么是 SpringBoot Vue Java2.1 后端用 SpringBoot 的理由和边界SpringBoot 在毕业设计里使用率非常高原因很直接对新手友好社区资料多出了问题在搜索平台基本都能找到答案。它内置了 Tomcat很多默认配置能开箱即用不需要像早期 SSM 那样写大量 XML 配置。它适合提供 Restful API 服务正好匹配前端 Vue 的需求。在这个系统里后端要承担的职责包括用户认证、业务数据增删改查、推荐结果计算、图片上传、简单权限控制。用 SpringBoot MyBatis-Plus 就能实现。如果你是第一次做全栈项目我建议用 MyBatis-Plus因为它能快速生成简单的 CRUD 代码减少重复工作把节省下来的时间投入到推荐逻辑和前后端联调上。2.2 前端用 Vue 的适用场景和注意事项前端用 Vue 的优点是组件化开发。美食卡片、评分组件、商家详情、标签选择都可以拆成独立组件复用性高代码结构也清爽。配套使用通常包括 Vue Router 管理页面路由、Axios 发起接口请求、Element Plus 或 Ant Design Vue 提供 UI 组件。但 Vue 的安装和环境配置本身就是一道坎。很多新手卡在 npm install 一直报错、vue 项目启动失败、依赖版本冲突。这类问题绝大多数不是项目本身的问题而是 Node.js 版本、npm 镜像源、依赖版本不一致导致的。我建议第一件事就安装 Node.js 的 LTS 版本不要图新装最新版。npm 源换成国内镜像后安装失败的频率会明显下降。前端开发服务器通过 vue.config.js 配置代理后端接口端口就不会出现跨域问题。2.3 前后端分离架构下一次完整请求怎么走用最简单的场景说明用户在前端页面点击“查看美食列表”Vue 组件发送 axios GET 请求到后端接口。后端 SpringBoot 的 Controller 接收参数调用 Service 层处理业务逻辑Service 调用 Mapper 查询数据库拿到结果后封装成 JSON 返回给前端。前端拿到数据后渲染成美食卡片列表。这张数据流想清楚之后整个项目的开发顺序就很明确先建数据库再写实体类和 Mapper再写 Service再写 Controller然后用 Postman 测试接口最后写前端页面去对接。不要反过来从页面开始写那样会越写越乱。3. 推荐系统才是这个项目的核心得分点3.1 毕设推荐系统可以做到什么程度既然是“美食推荐系统”推荐功能就是评委和答辩老师最关注的地方。你不需要一上来就上深度学习模型校园美食场景下的数据量、训练成本和展示效果都不合适。毕业设计阶段的推荐系统能做到下面三个层次之一就已经非常扎实了。第一个层次基于规则和标签的推荐。系统根据用户选择的偏好标签、历史收藏、评分记录匹配带有相同标签的店铺并推荐出来。第二个层次基于用户协同过滤。找出和当前用户行为最相似的其他用户把相似用户喜欢过但当前用户还没尝试的店铺推荐出来。第三个层次基于物品协同过滤。根据所有用户的评分数据计算店铺之间的相似度推荐和用户喜欢的店铺相似的其他店铺。对大多数毕设项目来说完成第一个层次就能完整讲清楚推荐流程完成第二或第三个层次就能成为答辩的技术亮点。实际开发时建议先做第一个再往上升级。3.2 基于标签的推荐最简单的实现思路标签推荐的核心是让用户先标记自己的偏好。常见做法是在用户首次登录时或者个人中心里提供一个“选择你喜欢的口味”的界面选项包括麻辣、清淡、甜口、面食、快餐、奶茶、烧烤等。每个商家和菜品也由管理员或商家在后台打上对应的标签。推荐时系统把用户感兴趣的标签对应的商家取出来再按热度、评分、距离等规则排序得到推荐列表。这个方案逻辑简单、效果直观、代码量也不大非常适合作为毕设的基线版本。真实实现时要注意用户如果没有选择任何标签或者没有任何历史行为系统必须有一个兜底策略。比如默认按热门店铺、最新上架店铺推荐。推荐结果为空时页面不能直接报错要显示“暂无推荐先看看热门店铺吧”之类的空状态提示。3.3 基于协同过滤的推荐进阶做法如果想把推荐系统做得更有技术含量可以继续实现协同过滤。我建议直接用 Java 实现核心计算逻辑不要依赖外部大模型或者第三方推荐服务这样代码是你自己写的答辩时能讲清楚每一步的原理。用户协同过滤的基本步骤可以拆成五步第一步构建用户-店铺评分矩阵。行是用户列是店铺值是评分没有评分的位置用 0 填充。第二步用余弦相似度或者皮尔逊相关系数计算用户之间的相似度。第三步找到和目标用户最相似的 K 个用户。第四步把这些相似用户评分较高、但目标用户没有评分过的店铺按相似度加权汇总。第五步排序取前 N 个店铺作为推荐结果。这段逻辑用 Java 写下来大概三四百行关键在于数据结构要清晰。可以用一个双层 Map 表示评分矩阵再单独写一个相似度计算工具类。因为毕设数据量不大实时计算完全能承受。3.4 推荐接口的数据结构和效果验证推荐功能在系统中要作为独立接口暴露出来方便前端调用也方便答辩时单独演示。接口示例GET /api/recommend/food?userId101limit10返回结果可以设计成带推荐原因的结构{ code: 200, data: { userId: 101, recommend: [ { shopId: 1, shopName: 川味小厨, reason: 因为你喜欢麻辣口味 }, { shopId: 5, shopName: 老街面馆, reason: 和你相似的同学也喜欢这家 } ] } }加上 reason 字段后前端页面可以展示出推荐依据用户会觉得系统是合理的而不是随便塞了几个店。答辩时这个字段也很有说服力因为你能主动证明推荐结果和用户行为是相关的。关于推荐效果的评价毕设阶段不需要做精确的离线指标评测但至少要做抽样式验证创建三到五个测试用户分别模拟不同的标签选择、收藏和评分行为确认推荐结果会随着行为变化而改变。这一点一定要提前测好答辩时最容易翻车的不是算法不够复杂而是“我明明喜欢川菜推荐列表却全是甜点”。4. 核心模块和数据库设计建议4.1 功能模块怎么拆分把系统功能拆成下面这些模块既方便代码组织也方便写论文时画功能结构图。用户模块注册、登录、信息维护、密码加密。店铺模块店铺增删改查、分类查询、图片上传、地址信息。菜品模块菜品增删改查、菜品种类、价格、描述、图片。评价模块评分、评论内容、评价时间、店铺评分均分计算。收藏模块用户收藏店铺、收藏列表展示。标签模块标签管理、用户偏好标签、店铺标签维护。推荐模块推荐算法计算、推荐结果接口、热门榜单。功能模块拆好之后你的开发计划基本就出来了。按模块逐一完成即可不会出现“想到哪写到哪”的混乱状态。4.2 数据库表设计表的设计尽量精简但该有的关系还是要体现清楚。核心表可以按照下面这个结构来设计具体字段可以根据自己的需求扩展表名核心字段说明userid, username, password, nickname, avatar, role用户表role 区分学生、商家、管理员shopid, name, category_id, address, phone, image, avg_score, status店铺表foodid, shop_id, name, price, description, image, status菜品表categoryid, name, sort分类表tagid, name标签表shop_tagid, shop_id, tag_id店铺标签关联表user_tagid, user_id, tag_id用户偏好标签关联表ratingid, user_id, shop_id, score, comment, create_time评分评论表favoriteid, user_id, shop_id, create_time收藏表这里有个很实际的经验用户查询频率高的表比如 rating 和 favorite建议提前给 user_id 和 shop_id 建立索引。数据量小的时候可能看不出差别但评分数据一旦超过几百条没有索引的查询会明显变慢答辩演示的时候就可能卡顿。4.3 搜索、排序、分类怎么和推荐结合一个完整的美食系统不能只有推荐页面普通搜索和筛选功能也是必须的。这些功能和推荐接口可以统一设计。首页默认展示个性化推荐用户进入“全部美食”页面后支持按分类筛选、按价格区间筛选、按评分排序、按收藏数排序。搜索框支持按店铺名和菜名模糊搜索。常见的错误做法是把所有查询条件都直接写在 Controller 里导致一个方法几百行。我更建议把查询条件封装成一个 Query 对象Service 层负责组装查询条件Mapper 层负责执行 SQL。这样代码结构清晰后期加过滤条件时只改很小的范围。5. 本地运行需要准备哪些环境和条件5.1 环境版本和工具链先从硬件说起。这套系统开发和运行门槛不高普通电脑就能承载。如果你只有 8G 内存要跑 IDEA、MySQL、前后端两个服务内存会有点紧张但也能运行。我建议开发时不要同时开太多软件让核心进程保持干净。如果推荐计算模块比较大还要额外估算 Java 进程的堆内存占用。软件方面常用工具链如下工具建议配置用途JDK8、11 或 17 等 LTS 版本避免追最新Java 后端运行环境Maven3.6 以上后端依赖管理和打包Node.js16 LTS 或 18 LTS前端依赖管理和构建MySQL5.7 或 8.0数据存储Redis可选5.0 以上缓存登录态和热门数据IDEA2021 以后版本开发和调试Postman / Apifox任选接口测试Navicat / DBeaver任选数据库管理这里要特别提醒原始项目材料里给出的环境版本不一定适配你的电脑。实际落地时要以你自己机器上的 JDK、Node、MySQL 实际版本为准。JDK 版本过高有时会遇到第三方依赖兼容问题Node 版本过高有时会遇到 npm 构建警告。使用长期维护稳定版本是最省心的选择。5.2 项目结构怎么组织毕设项目建议采用前后端分离的目录组织方式两个目录独立管理。后端结构backend/ ├── pom.xml └── src/main/java/com/example/campusfood/ ├── controller/ ├── service/ ├── mapper/ ├── entity/ ├── dto/ └── config/前端结构frontend/ ├── package.json ├── vue.config.js └── src/ ├── views/ ├── components/ ├── router/ ├── api/ └── store/这种结构的优点是后端能独立测试接口前端只关心页面渲染和接口调用写论文画系统架构图时也一目了然。5.3 启动步骤后端先跑通再跑前端我见过不少同学拿到项目代码后直接把前后端都启动然后开始联调结果报错时根本分不清是前端问题还是后端问题。更合理的启动顺序是这样第一步启动 MySQL创建数据库导入建表 SQL。第二步配置后端 application.yml 里的数据库连接、端口、文件上传路径。第三步启动 SpringBoot 后端用浏览器或 Postman 访问一个简单接口确认能正常返回 JSON。第四步创建前端项目安装依赖运行 npm run serve。第五步确认前端页面能访问再配置代理把前端请求转发到后端端口。第六步所有接口联调通过后再处理推荐功能的测试数据和异常情况。先单端、再联调这个顺序能帮你节省非常多排查时间。6. 前后端核心代码怎么组织6.1 后端 Controller Service Mapper 三层后端建议严格按三层结构写代码。Controller 只做参数接收和结果封装Service 写业务逻辑Mapper 访问数据库。以推荐接口为例Controller 层大致是这样RestController RequestMapping(/api/recommend) public class RecommendController { Resource private RecommendService recommendService; GetMapping(/food) public Result getRecommend(RequestParam Long userId, RequestParam(defaultValue 10) Integer limit) { ListRecommendItem list recommendService.recommendByUserId(userId, limit); return Result.success(list); } }Service 层负责处理真正的推荐逻辑。如果使用了 MyBatis-PlusMapper 层可以非常薄public interface RatingMapper extends BaseMapperRating { }这个分层结构的优点是代码简单、容易讲清楚也方便在论文里画“基于 SpringBoot 的三层架构图”。6.2 推荐算法的 Java 实现片段这里给一个基于标签推荐的最简版本伪代码方便理解整体思路public ListRecommendItem recommendByUserId(Long userId, int limit) { // 1. 查询用户偏好的标签 id ListLong userTagIds userTagMapper.selectByUserId(userId); // 2. 查询这些标签对应的店铺 id ListLong shopIds shopTagMapper.selectShopIdsByTagIds(userTagIds); // 3. 排除用户已收藏或已评分的店铺 ListLong ratedShopIds ratingMapper.selectShopIdsByUserId(userId); // 4. 按评分、收藏数等排序取前 limit 条 return shopMapper.selectRecommendPage(shopIds, ratedShopIds, limit); }真实代码里要把参数校验、空集合判断、兜底策略都加好。比如用户没有偏好标签时userTagIds 是空集合需要走热门店铺逻辑。用户已经对所有候选店铺都评过分时也不能返回空列表要从推荐池里按热度补位。这些小细节反而是答辩时最能体现工程能力的地方。6.3 Vue 页面和 axios 调用Vue 端对推荐结果的渲染一般放在首页最显眼的位置。推荐数据的请求统一放在 api 目录下管理不要在页面里到处写 axios。比如在 frontend/src/api/recommend.js 中import request from /utils/request; export function getRecommendFood(userId, limit 10) { return request({ url: /recommend/food, method: get, params: { userId, limit } }); }在 Home.vue 中调用这个接口拿到 data 后渲染成卡片列表。展示时把 reason 字段显示出来比如“因为你喜欢麻辣口味”这个细节会让页面体验完整很多也方便答辩时向老师演示推荐逻辑。6.4 用户登录和权限控制用户认证建议使用 JWT。用户在登录接口输入账号密码后端验证成功后生成 token 返回给前端。前端把 token 保存起来每次请求时放在请求头中。后端使用拦截器检查所有受保护接口的请求是否携带有效 token。角色权限可以用 user 表中的 role 字段区分管理员可以访问后台管理接口商家可以访问商家接口普通学生用户只能访问用户接口。不需要把 Spring Security 的完整过滤器链都引入进来一个拦截器加上角色判断对毕设项目来说已经足够清晰。注意登录态和权限是演示时的重点环节。三个角色各注册一个测试账号演示时分别登录让老师看到不同角色看到的菜单和操作按钮不一样这个演示效果会非常加分。7. 论文、开题报告和答辩怎么准备7.1 开题报告写什么开题报告是很多同学最先卡住的地方因为代码还没写却要先写研究意义。其实开题报告的重点不是预测最终结果而是说明三点这个课题值得做你打算怎么做做完之后怎么验证。具体可以写以下内容研究背景和意义从校园学生找饭困难、现有平台不聚焦校园场景切入说明做校园周边美食推荐的实用价值。国内外研究现状简要说明推荐系统在电商、外卖、本地生活领域的应用不需要大篇幅综述重点是引出校园场景的精细化推荐需求。研究内容说明系统包含哪些模块推荐算法用什么方案前端后端整体如何搭建。技术路线画一张从需求分析到系统测试的流程图。预期成果说明系统完成后包含哪些功能推荐效果如何验证。开题报告不是正式论文核心是让导师或者评委看出你已经把整个开发流程想清楚了。7.2 论文大纲结构论文结构可以参考下面的主线摘要和关键词第一章 绪论研究背景、研究意义、国内外研究现状、论文组织结构第二章 相关技术介绍SpringBoot、Vue、MyBatis、MySQL、推荐算法、JWT第三章 需求分析系统角色、功能需求、非功能需求、用例图第四章 系统设计总体架构、功能模块设计、数据库设计、推荐算法设计第五章 系统实现每个模块的实现页面、核心代码、效果截图第六章 系统测试功能测试用例、测试结果、推荐效果验证第七章 总结与展望完成情况、不足之处、后续改进方向参考文献、致谢这里有一个很实用的建议论文不要留到最后一个月才开始写。每完成一个功能模块就顺手把对应的功能描述、页面截图、核心代码整理到一个独立文档里。到最后写论文时你只是把这些零散文档整合成正式论文而不是从零开始憋字。7.3 答辩演示最容易被追问的点答辩时老师最关注推荐相关的几个问题提前准备一下会从容很多。你的推荐结果和别的用户有什么区别如果你切换测试用户后推荐列表没有明显变化老师一眼就能看出来。所以测试数据要构造多条让不同用户的标签和评分行为有明显差异。你的推荐算法如果用协同过滤相似度怎么算建议至少能说出余弦相似度公式并且能举一个简单例子。比如用户 A 喜欢川菜用户 B 也喜欢川菜他们之间相似度较高系统会把用户 B 吃过但用户 A 没吃过的川菜馆推荐给 A。新用户没有行为数据怎么办这就是冷启动问题。可以回答新用户没有行为数据时默认推荐热门店铺新店铺没有评分时通过标签匹配或者管理员置顶让它进入推荐池。这个兜底策略要提前做好不能等老师问的时候才临时想。推荐效果怎么评价可以从两个层面回答功能层面是推荐结果随用户行为合理变化工程层面是推荐接口响应时间可接受日志和异常处理完善。不需要提到离线 AUC 或召回率除非你确实做了。8. 运行过程中最常踩的坑和排查顺序8.1 前后端联调失败先分清是哪端的锅最常见的现象是前端页面能打开但点击按钮后拿不到数据控制台报 404、405 或 CORS 错误。排查顺序是先看后端服务是否启动再看后端接口路径是否和前端请求路径一致再看请求方式是 GET 还是 POST再看参数名是否一致最后看跨域配置和代理配置。我见过太多案例是因为前端请求路径是 /api/food/list后端 Controller 写的是 /food/list就差一个前缀结果排查了大半天。建议前后端把接口路径统一对照一遍再联调。8.2 后端启动失败从三个角度查后端启动失败时按端口、数据库、依赖版本三层排查。第一端口被占用。SpringBoot 默认端口是 8080如果已经被其他程序占用启动就会失败。可以在 application.yml 里换一个端口或者直接关掉占用端口的程序。第二数据库连接不上。检查 MySQL 服务有没有启动数据库名、用户名、密码是否正确时区和编码配置是否合适。数据库连接串里建议加上 useUnicodetruecharacterEncodingutf8 和 serverTimezoneAsia/Shanghai。第三依赖版本冲突。Maven 依赖下载慢、某些依赖找不到、JDK 版本不匹配这三类问题占后端启动失败的大多数。建议先确认 Maven 镜像源已经配置好再检查项目 pom.xml 里的依赖版本是否满足你的 JDK 版本。8.3 推荐结果为空不要急着改算法推荐结果为空时先按以下顺序检查第一步确认用户选择了标签或者有收藏、评分行为。第二步确认店铺和菜品都打了标签。第三步确认推荐接口的查询条件没有把所有店铺都排除掉。第四步确认数据库中存在符合条件的数据。如果用户没有任何行为数据系统必须走兜底逻辑返回热门店铺。空结果在答辩演示时非常尴尬所以建议提前用多组测试账号反复验证。8.4 正式演示前的前置检查清单演示前建议按这个清单过一遍数据库服务已启动且后端能正常连接。后端启动无报错控制台没有红色异常。后端主要接口能用 Postman 正常访问。前端 npm run serve 已启动页面无控制台报错。用学生、商家、管理员三个不同角色账号分别登录确认权限控制生效。推荐接口用两组不同行为数据的用户测试结果有差异。清理测试过程中产生的脏数据避免页面上出现明显的错误内容。提醒如果决定在演示前临时修改代码、数据库或依赖版本一定要预留足够时间做回归测试。不要踩着答辩时间点还指望代码能稳定运行临时改动造成的未知风险往往比你想象的大。9. 最后给几个落地建议对于基于 SpringBoot 和 Vue 的毕业设计系统真正落地的难点往往不是单个功能不会写而是“功能、数据库、代码、论文、答辩”这条完整链路没有打通。我个人更建议先做出一个最小可用版本所有角色能登录、店铺列表能展示、推荐接口有返回。跑通这个闭环之后再逐步加功能。技术层面不要把推荐算法一开始就定成协同过滤。先实现基于标签的版本跑通之后如果时间充裕再加用户协同过滤作为系统的进阶亮点。答辩老师更看重你能不能把自己实现的逻辑讲清楚而不是算法本身有复杂。时间安排上建议按照“数据库设计 - 后端 CRUD - 前端基础页面 - 推荐算法 - 联调 - 论文 - 答辩准备”的顺序推进。每完成一步就顺手记录截图和关键代码这些内容都是写论文和做 PPT 的原始素材。如果你正在做这个题目或者准备选这个题目不用太焦虑功能数量。把用户、商家、管理员三条线的闭环打通把推荐逻辑做成能用行为变化展示的交互过程再把数据流和论文结构讲顺这套系统就已经是一份合格的毕业设计作品了。真正动手做起来之后你会明白代码量并没有想象中那么多反而是环境配置、数据测试和逻辑梳理最花时间。