
做Java毕设的同学十个里有八个绕不开“xx管理系统”剩下两个大概率就在做“xx交流社区”这类偏内容型的项目。我最早接触美食交流社区这个题目是在一个学弟的选题清单上当时第一反应是“这不就是论坛换了个壳”但真正动手梳理需求后才意识到这类系统最考验人的不是某个单独的技术难点而是业务模块之间怎么串联——用户、帖子、评论、点赞、分类、搜索、个人中心每一块单拎出来都不难合在一起却能把一个新手绕晕。所以如果你正在做或准备做“基于Spring Boot Vue的美食交流社区系统”这篇内容应该能帮你把整个项目的骨架、关键代码思路和容易踩的坑一次说清楚。这个项目适合的人群很明确Java方向的大四学生、准备秋招想补一个完整项目的初级开发者以及单纯想学前后端分离开发流程的同学。它的核心价值在于用一套不算复杂的业务场景把Spring Boot后端、Vue前端、MySQL数据库、Redis缓存、文件上传、权限校验这些高频知识点全部串起来了做完它你对“一个真实项目是怎么从零到一跑起来”这件事会有一个完整的体感而不是停留在背面试题的层面。下面我按实际开发顺序把这套系统的设计思路、核心实现和排坑经验完整拆开讲。1. 项目整体设计与核心思路拆解1.1 先想清楚业务边界美食社区到底包含哪些功能很多人做毕设的习惯是拿到题目就建工程、写代码结果写到一半发现功能越加越多数据库表改了三轮前端页面重构两遍最后时间全耗在返工上。美食交流社区这个题目看起来简单实际功能边界如果不提前框死很容易膨胀成“美食版知乎 电商 社交”的四不像。我建议把核心业务控制在六个模块用户模块注册、登录、个人信息、帖子模块发布、编辑、删除、分页列表、详情、分类模块美食分类的管理与筛选、评论模块帖子下的评论与回复、互动模块点赞、收藏、个人中心模块我发布的、我评论的、我收藏的。这六个模块已经能覆盖一个内容社区的完整闭环做出来之后系统是自洽的。先想清楚业务边界再设计数据库你觉得呢——其实很多毕业设计的评分点就在这里拉开了档次功能做得多不如做得闭环。至于消息通知、关注关系、私信、后台管理端这些属于锦上添花。时间充裕可以加时间紧张就砍掉评审老师更在意的是核心流程是否跑通、代码结构是否清晰。我就见过一个同学把后台管理做成另一个完整的Vue项目结果前端两个工程、后端几十张表答辩前三天还在联调整个人快崩溃了。1.2 为什么是 Spring Boot Vue而不是 SSM JSP这个题目的标准技术栈是Spring Boot做后端、Vue做前端前后端分离开发。很多同学第一次接触前后端分离会问一个很实际的问题学校课程里教的是SSM加JSP我为什么还要额外学一套Vue我的回答是你要往长远看。SSM加JSP的开发模式下前端页面是后端“渲染”出来的Java代码里混着HTML标签页面逻辑稍微复杂一点JSP文件就变得又长又乱。而且前后端代码耦合在同一个工程里你改了页面整个后端工程都要重新打包部署。Vue那套组件化思路把每个页面拆成独立的组件数据由接口提供页面交互在前端完成后端只负责输出JSON数据两边可以并行开发——这在团队协作和生产环境的部署上优势非常明显也是现在企业里真正在用的主流模式。技术选型对比下来这个项目的优势就很直观维度SSM JSPSpring Boot Vue本方案开发效率每次改页面要重新编译部署前端热更新后端只出接口并行开发代码耦合页面和业务逻辑混在一起前后端完全分离职责清晰部署方式打包成war丢给Tomcat前端静态资源用Nginx托管后端打成jar独立运行简历价值属于“过时技术栈”贴近企业真实开发模式面试可聊的点更多学习成本低需要额外补Vue和跨域等知识但收益高Spring Boot这边不用多说内置Tomcat、自动配置、生态丰富比SSM那一堆XML配置不知道省了多少事。Vue这边我推荐直接用Vue 3加Vite加Element Plus的组合组件库成熟页面搭建速度快适合毕设这种工期紧张的项目。如果你以前用过Vue 2上手Vue 3最需要适应的就是组合式API和响应式机制的变化建议提前花半天把setup语法糖和ref、reactive的用法过一遍不然后面写页面会很别扭。2. 环境准备与基础设施搭建2.1 JDK、Maven、Node 的版本搭配怎么选环境配置是毕设劝退第一关。很多同学代码还没写一行先在装环境上卡了两天一搜“java环境变量配置”网上教程版本新旧不一照着配完还是报javac不是内部或外部命令。这里我给你一套稳妥的版本组合和配置思路照着做基本不会出问题开发环境推荐JDK 8或JDK 11 Maven 3.6 Node 16或18 MySQL 5.7或8.0 Redis 6.x。这套组合的兼容性经过了大量项目验证资料最多踩坑最少。如果你用JDK 17甚至21不是不行但要注意Spring Boot版本必须选2.7或3.xMyBatis-Plus和一些第三方库的版本也要跟着升级版本不对就会出现奇怪的兼容性问题。单纯做毕设没必要追求新版本稳定压倒一切。JDK装好后打开命令行输入java -version和javac -version两个命令都能正常输出版本号才算配好环境变量。Maven装好后跑一下mvn -v重点看它用的是哪个JDK如果提示找不到JDK通常是JAVA_HOME没配好或者Maven的路径配置有问题。Node装好后跑node -v和npm -v验证通过再继续。2.2 IDEA 创建 Spring Boot 项目超时的处理环境装好后第一个坎来了IDEA里通过Spring Initializr创建项目加载官方地址特别慢经常转半天圆圈最后提示超时。这个问题的根源是Spring Initializr的官方服务在国外网络访问不稳定。解决办法有两个一是修改IDEA里HTTP Proxy或自定义Initializr地址把https://start.spring.io换成阿里云的https://start.aliyun.com创建速度会快很多。需要注意阿里云这个地址对Spring Boot版本的枚举可能不是最新但选2.7.x的稳定版完全够用。二是手动搭建工程直接在IDEA里创建一个普通的Maven项目然后在pom.xml里把要用的依赖写进去让Maven慢慢下载这样做虽然多几步操作但胜在稳定不受网络波动影响。依赖下载慢的问题同样可以靠阿里云Maven镜像解决。在Maven的settings.xml里配置阿里云镜像mirror idaliyunmaven/id mirrorOfcentral/mirrorOf name阿里云公共仓库/name urlhttps://maven.aliyun.com/repository/public/url /mirror配置完后再创建项目、下载依赖体验完全不一样。Vue这边同样有类似的网络问题。用npm create vitelatest创建项目时如果下载卡住先把npm源切到国内镜像npm config set registry https://registry.npmmirror.com然后正常执行创建命令。项目创建好之后进入目录执行npm install依赖安装速度会有质的提升。如果公司的网络环境特殊npm install报各种证书或者网络错误还可以试试用cnpm替代但cnpm对依赖的解析和npm原生有些差异能用npm就用npm。3. 后端核心模块设计与实现3.1 数据库设计从一张用户表说起美食交流社区系统的表结构核心是六张表用户表、分类表、帖子表、评论表、点赞表、收藏表。我先说用户表它决定了后面所有业务模块怎么关联。字段上我建议至少要有id、username、password、nickname、avatar、signature、create_time、status。密码存MD5或BCrypt加密后的值绝对不能明文存。status字段用来表示账号是否被封禁0正常、1禁用这个字段平时不起眼但演示的时候可以现场展示封禁用户的效果是个加分项。帖子表是整个系统的核心。字段设计上我见过很多新手把发帖人ID、用户名一起放到帖子里这是典型的对范式理解不到位——用户改了昵称所有历史帖子的用户名就全对不上了。所以帖子表只存user_id需要展示用户名和头像时通过关联查询去用户表拿。帖子表的核心字段大致是id、user_id、category_id、title、content、cover_image、view_count、like_count、comment_count、status、create_time、update_time。其中content字段要用text类型而不是varchar因为varchar有长度上限帖子正文可能很长选text能避免后期数据写不进去的尴尬。分类表很简单就id、name、sort_order三个字段预设几个美食分类比如“地方菜系”、“家常菜谱”、“街头小吃”、“烘焙甜品”、“探店分享”。评论表要支持回复功能可以加一个parent_id字段表示父评论ID顶级评论该字段为0。点赞表和收藏表就是典型的关系表字段为id、user_id、post_id、create_time唯一索引设为user_id和post_id联合——这个唯一索引很重要它能从数据库层面保证同一个用户不能对同一篇帖子重复点赞否则前端按钮防抖做得再好并发请求还是会打出重复数据。关于建表我建议直接用Navicat或MySQL命令行窗口执行建表SQL同时把SQL脚本单独存一份放在项目根目录的sql/文件夹下。这既是好习惯答辩时老师问起数据库设计也能直接打开脚本讲。3.2 分层架构与接口设计规范后端工程我推荐按经典的四层结构组织Controller、Service、Mapper、Entity实体类。很多同学刚开始会纠结一个事情要不要引入mybatis-plus-boot-starter还是用原生的MyBatis这个我说得直接一点用MyBatis-Plus。它提供的通用Mapper和条件构造器能让你少写至少一半的CRUD代码单表查询基本不用写SQL把精力留给业务逻辑和复杂查询。它对毕设项目来说是实打实的效率提升不是偷懒。MyBatis-Plus依赖引入后还需要配置分页插件否则selectPage方法不生效Configuration public class MybatisPlusConfig { Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL)); return interceptor; } }不加这个配置分页查询会查出全表数据这属于典型的“代码没报错但功能不正常”的隐蔽问题排查起来很浪费时间提前配好省心。接口风格上建议统一规范前端和后端之间传输的数据一律使用一个统一的Result包装类。结构如下Data public class ResultT { private Integer code; private String msg; private T data; public static T ResultT success(T data) { ResultT r new Result(); r.setCode(200); r.setMsg(操作成功); r.setData(data); return r; } public static T ResultT error(String msg) { ResultT r new Result(); r.setCode(500); r.setMsg(msg); return r; } }为什么要统一你在前端用Axios拦截器统一判断code是否为200只要不为200就统一弹错误提示。如果每个接口返回的格式都不一样前端光是处理各种响应结构就能写出一堆重复代码。3.3 登录鉴权JWT 拦截器这样实现最快登录鉴权是美食交流社区系统里比较重要的一块因为前面说的发帖、评论、点赞、收藏全都要求登录后才能操作。这里我给出的方案是JWT加拦截器不引入Spring Security。说句实话Spring Security功能强大但学习曲线陡峭尤其是新版本里SecurityFilterChain的配置写法和旧版差异很大很多人照着网上的教程配完发现一个接口都访问不了Debug一整天还是懵的。毕设项目用JWT加拦截器完全够用代码量少逻辑直观遇到问题也容易排查。如果你求职目标是中大型企业之后可以单独补Spring Security但不要在毕设阶段卡在这个上面。JWT的工作流程不复杂用户登录时后端校验用户名密码校验通过后用密钥生成一个令牌Token把这个令牌返回给前端。前端把它存在本地存储里之后每次请求都在请求头带上Authorization: Bearer token。后端写一个拦截器拦截需要登录的接口解析请求头里的Token解析通过就放行解析失败就返回401前端收到401后跳转到登录页。生成Token的核心代码大致长这样以jjwt为例public class JwtUtil { private static final String SECRET your-secret-key; private static final long EXPIRE 7 * 24 * 60 * 60 * 1000L; // 7天 public static String generateToken(Long userId, String username) { return Jwts.builder() .setSubject(username) .claim(userId, userId) .setExpiration(new Date(System.currentTimeMillis() EXPIRE)) .signWith(SignatureAlgorithm.HS256, SECRET) .compact(); } }拦截器注册时注意一点登录接口和注册接口要排除在拦截范围之外否则用户还没登录就被拦截器挡在门外形成死循环。前端静态资源的访问路径也要放行。3.4 帖子上传、列表分页与图片处理的坑发帖功能里图片上传是绕不开的。前端用户选择图片后通过multipart/form-data方式把文件POST到后端接口后端把文件保存到服务器磁盘的某个目录然后把访问URL返回给前端。这里有一个新手很容易踩的坑Spring Boot默认只允许上传1MB文件如果用户传一张几MB的美食照片直接报错。所以要在application.yml里调整上传限制spring: servlet: multipart: max-file-size: 20MB max-request-size: 50MB文件保存后前端要能通过URL访问到这张图片需要配置静态资源映射。如果你把文件存在/data/upload/目录下那么要加这样一个配置类Configuration public class WebConfig implements WebMvcConfigurer { Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler(/upload/**) .addResourceHandler(file:/data/upload/); } }这样前端通过http://localhost:8080/upload/xxx.jpg就能直接访问图片。磁盘目录建议不要放在工程目录下否则以后打包部署时图片路径会乱掉。帖子列表分页这是访问量最高的接口也是演示时最容易出问题的接口。实现上直接用MyBatis-Plus的分页能力Override public IPagePostVO getPostPage(int current, int size, Long categoryId) { PagePost page new Page(current, size); LambdaQueryWrapperPost wrapper new LambdaQueryWrapper(); wrapper.eq(categoryId ! null, Post::getCategoryId, categoryId) .orderByDesc(Post::getCreateTime); IPagePost postPage postMapper.selectPage(page, wrapper); // 然后遍历帖子列表查出每个帖子的作者昵称和头像组装成VO返回 return postPage; }这里需要结合连表或封装考虑一下性能不要在for循环里逐条查询用户表而应该先把作者ID集合查出来批量查用户信息再用Map映射。虽然数据量小的时候性能差异不明显但这是个好习惯而且面试官问起来你能说出个所以然印象分会好很多。4. 前端页面搭建与交互实现4.1 Vue3 Vite Element Plus 项目初始化前端部分我用的是Vue 3加Vite加Element Plus这套组合。Vite启动速度快开发体验比老一代的Webpack舒服太多。创建项目的命令npm create vitelatest food-community -- --template vue cd food-community npm install npm install vue-router4 axios element-plus element-plus/icons-vue npm run dev项目跑起来后先做两件事。第一件是把目录结构整理清楚src/views放页面组件src/router放路由配置src/api放接口请求封装src/utils放工具函数这样结构清晰后续加页面不会乱。第二件是把Element Plus按需引入配好完整引入会导致打包体积很大页面加载变慢按需引入的方式网上有很多现成配置直接照着粘就行。页面规划上前端至少需要这些页面首页帖子瀑布流/列表、帖子详情页、发布帖子页、分类列表页、登录页、注册页、个人中心页。路由配置用Vue Router路由跳转时要处理好登录状态页面需要登录才能访问的在前置路由守卫里判断Token是否存在。这里提醒一下Vue 2和Vue 3的一个关键差异很多同学在搜索教程时会混用。Vue 3里创建路由实例用的是createRouter和createWebHistory而不是Vue 2里的new VueRouter()。如果网上抄了一段代码发现createRouter is not defined多半是把两个版本的写法搞混了。4.2 Axios 封装与接口对接前端所有接口请求强烈建议统一封装成一个Axios实例不要每个页面直接import axios from axios就发请求。统一封装的好处是可以在请求拦截器和响应拦截器里集中处理公共逻辑。比如请求拦截器里加Tokenimport axios from axios const service axios.create({ baseURL: /api, timeout: 10000 }) service.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers[Authorization] Bearer token } return config }) service.interceptors.response.use( response { const res response.data if (res.code ! 200) { ElMessage.error(res.msg || 请求失败) if (res.code 401) { router.push(/login) } return Promise.reject(new Error(res.msg)) } return res }, error { ElMessage.error(error.message || 网络异常) return Promise.reject(error) } )这段代码封装好后所有页面调用接口都是service.get(/post/list)这种形式返回结果统一处理避免每个页面都写一遍重复的错误处理逻辑。401的统一跳转也是在这里处理——后端拦截器返回401前端收到后自动清空本地Token并跳转登录页体验会专业很多。4.3 路由参数、列表页与详情页的数据流转从列表页点击一篇帖子跳转到详情页需要把帖子的ID传过去。Vue Router传参有两种常见方式path带参数或query查询参数。比如详情页路由定义成/post/:id跳转时用router.push(/post/ id)在详情页通过route.params.id拿到ID。这种方式URL结构清晰刷新页面参数不会丢失我推荐用这种。有些同学喜欢用router.push({ name: post-detail, params: { id: 1 } })这种方式这种写法有个坑一旦刷新页面刷新后参数会丢失详情页拿不到ID页面直接空白。如果你非要用params传参那就要配合Vuex或Pinia做状态持久化但这样就复杂了完全没有必要。详情页拿到帖子ID后发请求获取帖子详情、评论区列表。评论区这块要注意美食社区的评论可能有回复嵌套后端返回的数据结构要设计好。简单方案是后端一次性查出某个帖子的所有评论在前端按照parent_id组装成树形结构再渲染数据量大的时候再考虑后端分页返回毕设阶段用前一种方案就行。4.4 富文本与图片上传组件的联动帖子正文如果只是纯文本页面会显得很素。我建议引入简单的富文本编辑器。这里不推荐特别重型的编辑器学习成本高打包体积也大。用过几款之后我比较推荐wangeditor或md-editor-v3前者是所见即所得的富文本风格更容易上手后者是Markdown语法排版更简洁。这两个编辑器都支持自定义图片上传也就是说你在编辑器的工具栏里点图片按钮会调你指定的上传接口把图片传到你自己的服务器。这里有一个容易掉的坑上传接口需要登录才能调用但编辑器内部的图片上传是通过它自己发起的请求不会自动携带你Axios实例里的Token。解决方案是在初始化编辑器时单独为上传配置一个带Token的请求const editor new WangEditor(#editor) editor.config.uploadFileName file editor.config.customUpload async (file, insertFn) { const formData new FormData() formData.append(file, file) const res await uploadImage(formData) // 这个uploadImage内部用带Token的Axios实例 insertFn(res.data) }这样图片上传的登录校验就能正常走通了。踩过这个坑之后我后来的项目都习惯把编辑器的图片上传单独封装不会再依赖编辑器默认的上传实现。内容发布后详情页展示时要注意一点富文本编辑器输出的内容是HTML片段渲染到页面上要使用v-html指令。使用v-html要确保内容是后端返回的可信数据防止XSS注入。安全起见发布接口后端建议对HTML内容做一下白名单过滤或者至少做个基础校验。5. 常见问题与排查技巧实录5.1 前端访问后端接口跨域报错的三种解法前后端分离项目跨域是最经典的问题前几名。现象很统一前端页面通过Axios请求后端接口浏览器控制台报CORS相关的红色错误。为什么会跨域因为前端运行的地址是http://localhost:5173后端的地址是http://localhost:8080两者端口不同浏览器默认阻止跨域请求。解决思路有三种第一种后端开启跨域。写一个配置类实现WebMvcConfigurer重写addCorsMappings方法允许指定来源的请求跨域访问。这种方式配置简单一劳永逸适合毕设。第二种前端配置代理。开发环境下用Vite的proxy配置把所有/api开头的请求代理到后端地址。配置在vite.config.js里server: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } }这种方式的好处是浏览器看到的请求是同源的不会触发跨域限制而且对接联调时非常灵活。它的本质是“骗过浏览器”实际请求由开发服务器转发给后端。第三种部署时用Nginx反向代理。前端静态资源部署在Nginx后端接口也通过Nginx转发前端页面请求/api/xxxNginx把请求转发到后端Java服务浏览器同样不觉得跨域。我给的建议是开发阶段用Vite代理部署阶段用Nginx。如果为了省事也可以后端直接加CORS配置两种都行关键是别开发时用代理后端又加了CORS两者叠加产生的一些边界安全问题虽不至于影响毕设但概念上容易混淆。5.2 刷新页面 404 的坑做过Vue项目的同学特别带过vue-router的应该都遇到过这个经典问题路由用createWebHistory模式本地开发一切正常打包部署到服务器后进入某个子页面一刷新就是404。原因很明确前端路由跳转是在浏览器端完成的URL变了但并没有真正向后端发请求但一旦刷新浏览器会按URL访问服务器服务器上并不存在/post/123这个物理路径于是返回404。而本地开发时Vite的开发服务器天然支持历史路由回退所以不会暴露这个问题。解决方案有两种。一种是省事的把路由模式从createWebHistory改成createWebHashHistoryURL会多一个#号但刷新就不会404了这种方式适合不想折腾部署配置的场景。另一种是规范的保持history模式然后在服务器端做重写配置。比如Spring Boot后端写一个转发器把非接口路径全部转发到index.htmlNginx则配置try_files $uri $uri/ /index.html;。两种方案都可以毕设阶段如果部署环境不好调直接用hash模式也能顺利演示。5.3 Redis 自增报错与缓存一致性很多同学在社区项目里会加一个“帖子阅读数”或“点赞数”的功能用Redis做计数然后定时同步到MySQL。这里我遇到过一个非常经典的报错用redisTemplate.opsForValue().increment(key)实现点赞增量运行时控制台报错“not integer or out of range”。这个问题的根源是类型匹配。increment方法返回的是Long但如果你在Mapper或实体里把这个值赋给Integer类型就会出现类型转换异常。解决起来不复杂统一使用Long接收自增结果。但这里想提醒的是使用Redis做计数器还要想清楚一个问题什么时候把Redis里的数据写回MySQL。最简单的方案是每次点赞操作直接更新MySQLRedis只做缓存更“高级”的方案是Redis计数后后台每隔几分钟批量同步一次但这个方案要考虑数据丢失风险服务器一重启Redis里还没同步的数据就全没了。毕设项目里不需要搞得这么复杂直接用MySQL存点赞数配合Redis做热点数据的读取缓存逻辑清楚又不容易出bug。5.4 Lombok 编译报错、Node 版本过高、npm 依赖安装慢有些同学在项目里用了Lombok结果IDEA里编译直接报错提示you arent using a compiler supported by lombok, so lombok will not work。这个报错通常是IDEA里Lombok插件没安装或者IDEA版本太新、Lombok版本太旧导致的。解决方法是先确认IDEA的插件市场里Lombok插件已启用了再把pom.xml里的Lombok依赖升级到较新版本大多数情况下问题就能解决。如果你用的是JDK 21配合老版本的Lombok大概率会踩这个坑。Node版本过高的问题也很常见。有些同学电脑装了Node 20甚至更高版本然后npm install报各种莫名其妙的错误比如cb() never called、Node Sass does not yet support your current environment。这些大多是因为某个依赖和太新的Node版本不兼容。遇到这种问题我建议直接用nvm安装一个Node 16或Node 18的LTS版本切过去再重新npm install大部分问题都会消失。开发这个项目不需要最新版的Node稳定才是第一位的。npm依赖安装慢的问题前面说过核心就是换源。npm config set registry https://registry.npmmirror.com改完之后速度能快上好几倍。如果你发现换了源还是慢可以检查一下是不是项目依赖里有个别包体积巨大或下载源不在国内可以单独通过npm install 包名 --registry指定源。6. 项目扩展从毕业设计到简历亮点6.1 时间紧张时的 MVP 功能裁剪清单如果你离答辩只剩两周功能还没做完别慌按优先级砍功能。我做了个裁剪清单按“必须做”和“可以延期”分类必须做的核心功能底线用户注册登录、帖子发布与列表分页、帖子详情页、评论功能、分类筛选、个人中心查看自己的帖子。这六个功能做完系统就算闭环了所有核心业务能跑通答辩不会挂。可选加分功能有空再做点赞收藏、头像上传、富文本编辑、Redis缓存、阅读数统计、搜索功能。这些功能属于锦上添花做出来是亮点不做也不会伤筋动骨。优先级判断的依据很简单一个功能能否成为“完整用户旅程”中不可跳过的环节。比如没有点赞用户依然可以浏览、发帖、评论核心体验不受影响但没有登录用户就发不了帖社区内容生产直接断掉所以登录注册优先。6.2 能写到简历和答辩中的加分设计这个项目做完之后怎么写进简历、怎么在答辩中讲出亮点是非常重要的。很多同学的项目做得不错但表达不出来面试官一问“你这个项目有什么难点”答一个“没有”好项目就浪费了。我觉得这个项目里至少有四个点可以讲第一数据库表结构设计尤其是点赞收藏表用联合唯一索引防止重复帖子和用户表分离避免数据冗余这些都是能体现基本功的点。第二JWT登录鉴权方案的设计可以从无状态认证讲起和Session方案做对比再展开讲拦截器的实现。第三文件上传与静态资源映射如果你折腾过上传大小限制和路径映射完全可以讲成一个排查过程的小故事。第四Redis缓存的使用场景为什么用缓存、缓存什么数据、怎么保证缓存和数据库的一致性这套逻辑讲通了面试官对你的评价会明显不一样。答辩时准备一张系统架构图包含用户端Vue、后端Spring Boot、以及MySQL和Redis讲的时候按请求链路走一遍用户在页面操作前端通过Axios发送请求后端Controller接收Service处理业务逻辑Mapper操作数据库结果一层层返回。这一套讲下来老师会对你的项目有一个清晰的整体认知分数自然不会低。6.3 部署上线的一些建议如果你想把项目部署到云服务器上给一个小小的上线流程参考。后端打成jar包在服务器上执行nohup java -jar xxx.jar app.log 21 就能在后台运行。前端npm run build打包出dist目录用Nginx托管Nginx里配置好静态文件路径和接口反向代理。数据库脚本在服务器MySQL里执行一遍然后把配置文件里的数据库地址改成服务器地址。部署过程中最容易出的问题是端口没开、安全组没放行、防火墙拦截这些都可能导致网页打不开。排查的时候先检查进程是否启动成功再看日志最后看网络和安全组配置。第一次部署大概需要半天时间但这个过程本身非常值得它能逼你搞清楚项目运行时的真实依赖关系。如果你不想租服务器也可以先在本地把前后端跑通用局域网IP让同学手机访问测试效果也不差。重点是项目本身经得起推敲部署方式不是决定项。最后再分享一个答辩演示的小技巧演示前先用浏览器的无痕模式打开页面避免浏览器缓存或者你日常登录状态对演示造成干扰准备两个账号一个用来发帖一个用来评论互动演示发布美食帖时提前准备好一张处理过的图片不要现场临时找图。这个项目做下来我最深的感受是技术栈其实就是那么几个框架的排列组合真正拉开人与人差距的是你能不能把一个业务场景从头到尾想明白、做闭环并且把过程中踩过的坑整理成自己的经验——这比多写几千行代码有价值得多。