Spring Boot + Vue 美食分享管理系统全栈开发实战

发布时间:2026/10/17 15:18:13
Spring Boot + Vue 美食分享管理系统全栈开发实战 项目标题: 基于springboot vue美食分享管理系统(源码数据库文档)一个基于Spring Boot和Vue的美食分享管理系统听起来是再常见不过的全栈练手项目但真正把前后端分离、源码数据库文档三件套完整做下来你会发现在学校课堂上学的那些东西远远不够用。这个系统核心解决的是这样一个场景普通用户注册登录之后能上传自己做的家常菜谱浏览别人的私房菜做法顺手点赞、评论、收藏让好味道不止停留在朋友圈九宫格里而是能在一个属于自己的社区里沉淀下来。我前后带过不少同学做类似项目从零开始到能跑通上线踩过的坑基本都摸了一遍。今天这篇文章就把这套系统从需求设计、数据库建模、后端接口、前端页面到联调部署的完整链路拆开讲清楚穿插一些常规文档里不会写的实战教训适合正在做毕业设计、课程设计或者想快速入门Java全栈的人参考。1. 项目概述这个美食分享系统到底在解决什么问题1.1 核心需求拆解任何项目动手前先把需求问清楚不然写出来的功能别人根本不用。这个系统表面上就是发菜谱、看菜谱、评论收藏但拆开来看其实要处理这么几类核心需求第一用户体系。要不要登录才能看内容我建议的内容策略是游客可浏览登录才能互动——这样既保证搜索引擎和访客能直接看到内容又让点赞、评论、收藏这些高价值操作必须留痕。用户表里除了基本的用户名密码还要考虑头像、个性签名、个人简介这类社交属性字段。第二内容管理。菜谱是最核心的实体标题、封面图、分类、食材清单、步骤描述、难度、耗时、标签缺一不可。分类这块可以采用两级结构比如家常菜—鱼香肉丝甜品—提拉米苏数据上就是一张分类表加一个 parent_id 字段简单又灵活。第三互动体系。点赞、评论、收藏这三个功能是社交分享类系统的灵魂。点赞要处理取消点赞评论要做楼中楼还是平铺列表收藏要区分想吃的和做过的。很多初学者在这里会写出混乱的表结构后面我会详细给出一版可直接落地的设计方案。第四个人中心。用户能看到自己发过什么、收藏了什么、收到多少赞和评论。这部分数据量不大直接联表查询就行不需要引入太重的统计方案。1.2 技术选型背后的权衡选型这事没有绝对的最佳只有更适合当前场景。这套系统选 Spring Boot Vue本身就是冲着成熟稳定、资料多、招人需求大这三个优点去的。Spring Boot 2.7 JDK 8以目前的环境来说依然是最稳妥的组合新项目没必要追新上 JDK 17/21 给自己找兼容性麻烦MyBatis-Plus 代替原生 MyBatis开发和维护效率高一大截连表查询、逻辑删除、自动填充都有现成支持MySQL 8.0 存储数据和文件路径稳定不出错。前端这块Vue 2 Element UI 或者 Vue 3 Element Plus 都可以考虑到很多学校的老项目模板还停留在 Vue 2 时代有大量现成组件和踩坑经验可参考如果你的机器配置一般选 Vue 2 反而更省心。前端工程用 Vue CLI 或 Vite 都行Vite 启动快、热更新爽是对开发体验提升最明显的一个选择但如果团队里用的都是老 node 环境Vue CLI 兼容性更保险。整个系统的数据流是这样的前端 Vue 发起 Axios 请求通过路由代理转发到后端 Spring Boot 的 ControllerController 调 ServiceService 通过 MyBatis-Plus 访问 MySQL拿到的数据再原路返回前端渲染成页面。登录状态用 JWT 令牌维护用户操作时前端把令牌放在请求头里带给后端校验简单高效自带无状态特性前后端分离下比传统 Session 方案好操作得多。2. 数据库设计和后端核心实现一张表一个坑2.1 表结构设计先想清楚少走三个月弯路数据库设计决定了一个项目的天花板。很多同学上来就建两三张表写到后面发现功能对不上再回头改表各种外键牵连痛苦到怀疑人生。这套美食分享系统我建议至少规划以下七张核心表用户表 userid、username、passwordBCrypt 加密后存储、avatar、nickname、signature、create_time、update_time、deleted。deleted 字段用逻辑删除避免真实数据物理销毁这是 MyBatis-Plus 的常规操作。分类表 categoryid、name、parent_id、sort、create_time。顶级分类的 parent_id 为 0子分类的 parent_id 指向父级一张表完成无限级分类。给 sort 字段加个普通索引查询排序不至于每次都要 filesort。菜谱表 recipeid、user_id、category_id、title、cover_image、ingredients食材清单JSON 字符串或长文本、steps步骤描述、difficulty简单/中等/困难、cook_time、status0草稿、1发布、view_count、like_count、collect_count、create_time、update_time、deleted。菜谱和分类之间用 category_id 直接关联而不是前后端都查分类表再拼装一来可以减少一次连表二来冗余字段可控。点赞表 recipe_likeid、user_id、recipe_id、create_time加上 unique(user_id, recipe_id) 唯一索引防止重复点赞。这里的计数字段都在 recipe 表里冗余了每次点赞做两条更新插入点赞记录 菜谱 like_count 1取消防点赞就在事务里同时删记录和减计数这样查询时不需要 count 大表。评论表 commentid、recipe_id、user_id、content、parent_id、create_time。parent_id 非空时表示这条评论是某条评论的回复前端展示的时候可以做递归列表。收藏表 recipe_collectid、user_id、recipe_id、create_time同样加唯一索引。这里顺便说一下收藏和点赞不要混在一张表里用 type 字段区分确实可以省一张表但会让查询逻辑变复杂业务一旦扩展就是灾难分开表反而是最省心的方案。如果你还需要后台管理功能再补管理员表 admin、吐槽举报表 report 就差不多了。以下给一个关键字段对照方便你建表时自查表名核心字段关键索引建议userid, username, password, avataruk_usernamecategoryid, name, parent_id, sortidx_parent_idrecipeid, user_id, category_id, title, cover_imageidx_user_id, idx_category_idrecipe_likeid, user_id, recipe_iduk_user_recipecommentid, recipe_id, user_id, contentidx_recipe_idrecipe_collectid, user_id, recipe_iduk_user_recipe2.2 认证授权实现JWT 和 Spring Security 的搭配先说结论我推荐 Spring Security JWT 的标准组合来实现登录认证。很多同学觉得 Spring Security 复杂配了一堆难懂的过滤器链其实用起来路子是固定的。JWT 令牌就是一个经过签名的 JSON 字符串里面包含用户 id、用户名、过期时间等信息。用户在登录接口提交用户名密码后端校验成功后签发令牌返回给前端前端把令牌存在 localStorage 里此后每次请求都带上 Authorization: Bearer token。后端在过滤器里解析令牌解析通过就把用户信息塞进 Spring Security 的上下文之后的接口直接用注解拿到当前用户。写这套东西最核心的两个类一个是 JwtUtil负责生成和解析令牌另一个是 JwtAuthenticationTokenFilter继承 OncePerRequestFilter在每次请求时做校验。核心配置上有三个坎第一放行路径要配好登录、注册、获取分类、浏览公开菜谱是放行的其余接口要校验登录第二密码加密要用 BCryptPasswordEncoder千万不要用明文存储第三令牌过期时间我给项目里的默认值一般是 24 小时给演示环境够用生产环境建议改成 2 小时加 Refresh Token但这套系统用不到那么重。2.3 文件上传别把图片压垮数据库菜谱封面图是刚需。很多新手直接存 Base64 到数据库能跑但很蠢一张图几 MB 进去数据库瞬间膨胀接口响应也慢。正确做法是把图片文件存到服务器的某个目录数据库只存文件路径。后端用 Spring 自带的 MultipartFile 接收文件保存时按日期分目录文件名用 UUID 重命名防止用户上传同名文件互相覆盖。上传接口返回的是一个可访问的 URL前端拿到这个 URL 后连同其他表单数据一起提交这样上传过程可以单独做进度条用户体验更好。开发环境下的静态资源映射要手动配一下把某个 URL 前缀映射到上传目录比如Configuration public class WebConfig implements WebMvcConfigurer { Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler(/upload/**) .addResourceHandler(file: uploadPath); } }提示前端和后端若部署在不同服务器/upload/ 路径必须通过 Nginx 反代指向同一个静态目录否则图片会全部 404。这里再补一个容易踩的坑上传文件大小默认只有 1MB必须显式调大。在 application.yml 里加上 multipart 配置不然前端传一张手机拍的图直接就报错。2.4 核心接口设计与返回值规范前后端分离项目一定要约定统一的返回结构。后端接口的返回格式我习惯用这样一个对象code、message、data 三段式。code 为 200 表示成功401 表示未登录500 表示服务器异常前端 Axios 拦截器按 code 统一处理错误提示和跳转登录页。菜谱列表、评论列表这种分页接口返回内容除了数据本身还要带上 total、pages、current、size 等分页元数据。接口层面设计合理前端就不需要解析乱七八糟的字段名。一张标准的分页接口似乎写起来很容易但前方有多少接口要统一这套格式前后端联调时才能少出多少幺蛾子。接口清单可以这样规划模块路径说明认证POST /api/auth/login用户登录返回 token认证POST /api/auth/register用户注册菜谱GET /api/recipe/page分页查询菜谱支持关键词/分类过滤菜谱GET /api/recipe/{id}菜谱详情含作者、评论列表菜谱POST /api/recipe发布新菜谱菜谱PUT /api/recipe/{id}编辑菜谱菜谱DELETE /api/recipe/{id}删除菜谱互动POST /api/recipe/{id}/like点赞/取消点赞互动POST /api/recipe/{id}/comment发表评论用户GET /api/user/{id}/collections查看某人收藏列表3. 前端页面与交互实现Vue 怎么把后端数据变成美食页3.1 前端工程结构和路由设计前端工程我习惯按这几种目录拆分views 放页面视图、components 放公共组件、api 放接口封装、router 放路由配置、store 放全局状态。这种结构虽然老生常谈但确实能帮助团队快速定位代码尤其项目做到中期要加功能的时候不会到处乱找文件。页面的话至少要覆盖以下几块首页美食瀑布流展示轮播图 热门推荐 最新菜谱列表菜谱详情页大图展示、作者信息、食材清单、制作步骤、评论区发布页富文本编辑菜谱信息图片上传个人中心我的菜谱、我的收藏、我的评论、个人信息修改登录注册页路由设计有个细节要注意发布页和编辑页最好复用同一个组件用路由参数区分是新增还是编辑。这样一来表单校验、图片上传这些逻辑都只写一遍。Vue Router 配置时记得用路由懒加载import 改成动态引入首屏加载速度会明显提升。之前有个同学没做懒加载把 Element UI 全部组件都打进一个包里首屏白屏时间能到三四秒改成按需加载之后直接掉到一秒内。3.2 美食展示与发布核心页面是怎么做出来的首页的瀑布流列表是门面主要靠分页滚动加载实现。前端监听页面滚动到底部后自动请求下一页数据并追加在列表末尾。这个交互的核心是分页参数 pageNum 和 pageSize 的维护加载中要显示 loading数据加载完要给出到底了的提示。菜谱详情页要注意几点首先展示的封面图要大而清晰这是这个页面吸引用户的直接入口其次食材清单和制作步骤尽量分段展示不要一坨文字混在一起评论区支持一级评论和楼中楼回复这个前端递归渲染稍有点工作量但做完之后你会对各种树形结构数据的处理都有感觉。发布页是整个系统里交互最复杂的一页。表单字段包括标题、分类、封面图、食材清单、制作步骤、难度、耗时等其中食材清单、制作步骤要支持动态增加和删除行。Element UI 的 el-form 配合动态表单项比较好每行的验证规则用 v-for 渲染。前端做好数据组装之后一次性 POST 给后端减少请求次数利于出错回滚。点赞和收藏的按钮状态依赖该用户是否已经点过。这个在前端不能每次都查后端应该在请求详情接口时一并返回两个布尔值liked、collected。前端根据这两个值初始化按钮状态点击做乐观更新——点击后立刻改变按钮状态请求失败再回滚交互反馈迅速用户体验好很多。3.3 请求封装Axios 拦截器和 token 管理Axios 封装看起来不复杂但细节决定成败。我们需要做到以下几点创建 axios 实例设置基础 URL 为 /api超时时间为 10 秒请求拦截器里从 localStorage 取 token存在就附加到请求头响应拦截器里统一处理错误码401 未登录时清空用户状态并跳转登录页其他错误码直接弹出提示。这套东西很多同学在课设项目里都写过我要特别提醒一个安全细节不要把 token 存进 localStorage 之后不做任何过期处理。JWT 过期之后用户第一次点击我收藏的菜谱就会拿到 401前端引导重新登录没问题但如果你只在拦截器里弹出错误提示而不跳转登录用户就会感觉像系统坏了所以 401 的统一跳转逻辑一定要写在拦截器层。4. 联调、部署与异常排查实录4.1 前后端联调常见的拦路虎前后端分离的项目联调阶段十个里有九个会先碰上跨域。前端在 8080 端口后端在 8081 端口浏览器默认不允许跨域请求。解决方式有两种一是前端配置代理在 vue.config.js 里把 /api 代理到后端地址这样浏览器端看到的是同源请求二是后端开启 CORS 配置。开发阶段我推荐代理方案上线后一般用 Nginx 反代同源更干净。时间格式也是联调高频问题。后端 LocalDateTime 默认序列化会是2024-05-20T13:14:00前端展示时还得再转换。一劳永逸的做法是在后端的全局 Jackson 配置里统一日期格式为yyyy-MM-dd HH:mm:ss前端不用做任何处理就能直接显示。图片上传成功但页面不显示大概率是静态资源映射配置有问题。先检查上传目录里文件是否真实存在再直接在浏览器访问图片 URL如果 404就是映射没生效如果图片能访问但列表里还是没有就要查后端接口返回的 URL 是否完整。4.2 打包部署本地能跑不够服务器上跑得动才是真的开发完成后接下来是打包部署。前端执行 npm run build 生成 dist 目录后端执行 mvn clean package 打成 jar 包服务器上配合 Nginx 提供静态页面服务和反向代理。一个可用的部署架构大概是这样的Nginx 监听 80 端口把 / 路径指向 dist 目录的静态资源把 /api 路径反向代理到后端服务监听的 8081 端口把 /upload 路径映射到上传文件的物理目录。哪些路径必须走 Nginx哪些路径必须落在后端提前在 Nginx 配置里写清楚不要等部署完才想起 404。配置成品可以直接参考下面这个思路server { listen 80; server_name your.domain.com; location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://127.0.0.1:8081; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } location /upload/ { alias /data/upload/; } }后端启动时推荐用 nohup java -jar 或者 Systemd 托管不要直接在终端前台跑不然一关终端服务就停了。数据库记得在服务器上建好连接数据库的账号密码要单独建一个普通权限账号千万别用 root 裸奔。4.3 高频问题速查表整理一份我在带人做这类系统时遇到最多的故障列表方便你对照排查问题现象可能原因处理建议前端请求 404路由未配置 / 代理未生效检查 vue.config.js 代理检查后端 Controller 的 RequestMapping登录后请求返回 401token 未附带或过期请求拦截器检查 Authorization 头刷新页面重新登录上传图片报 500上传目录不存在或权限不足手动创建目录chmod 赋予写权限检查 multipart 配置分页数据缺失参数名不对pageNum/pageSize 拼写不一致统一用驼峰命名别 frontend 用 pageNum后端读 pageNum菜谱图片不显示静态资源映射配置错误浏览器直接访问图片 URL 验证检查映射规则评论发不出去前端没带 token或后端接口没处理用户信息确认登录状态后端打印 token 解析结果5. 从需求到交付的全流程沉淀5.1 需求文档和项目文档怎么写才不凑字数项目标题里带了文档两个字这里就得单独聊聊这三件套里的文档部分。很多同学把文档当成应付老师的大作文写一堆形容词充数结果答辩时被一问就露馅。真正有用的项目文档应该是需求分析说明用户角色、核心功能流程数据库设计说明每张表的字段含义和外键关系接口文档列出每个接口的入参、出参和错误码部署文档讲清楚环境要求和启动步骤。写文档这事特别适合培养你的抽象表达能力。你把一个功能的实现思路从业务层面讲清楚比堆代码注释有用得多。代码注释应当告诉你为什么这么写而需求文档应当告诉你这个功能为了解决谁的问题。如果要把这套项目做成商业级的文档里还得加上操作日志、数据备份恢复策略、异常监控方案等但目前课设和毕设阶段以上五部分已经足够了。5.2 这套代码真正值钱的地方最后说点实在的。Spring Boot Vue 项目网上模板一抓一大把光会跑只能应付验收真正能让你在面试和答辩里拿出竞争力的是这三块第一你对业务的理解是否完整。面试官问你的系统用户收到这么多点赞有什么作用如果你能说出点赞数影响菜谱在首页热门榜的排序权重从而提升优秀创作者的曝光这种产品层面的话会让面试官高看你一眼而不是单纯背 CRUD。第二工程化细节是否到位。统一返回值、全局异常处理、逻辑删除、分页封装、JWT 认证过滤器这些代码虽然简单但体现了你有没有生产级项目的思维。我会强烈建议你在代码里显式加上全局异常处理器 GlobalExceptionHandler它能把 Service 层抛出的业务异常统一转成前端可读的提示信息而不是返回 500 加一堆堆栈。第三你对系统扩展性的预判。现在这套系统做的是菜谱分享但同一套用户、评论、点赞、收藏架构换一下内容模型就可以做旅游攻略分享、读书笔记分享、宠物晒图社区。面试或者答辩被问到你的课设有什么创新点你说我设计时考虑了功能复用和模块解耦菜谱模块可以替换成任何内容类型远比说我用了最新框架有力。从某种程度来说所有带着源码 数据库 文档字样的项目都是在提前模拟你未来进入企业后的完整工作流程从需求设计开始到编码实现再到文档沉淀、部署上线、问题排查每一环都不轻松但每一步都在积累真本事。这套项目做完我也强烈建议你再往前走一步选一个曾经困扰你的点比如搜索优化、推荐算法、Excel 导出亲手改进一版它就会成为你手里真正拿得出手的作品。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询