做毕设辅导这几年,被问得最多的一句话是"Java选题做什么比较稳"。个人博客系统几乎是我每次都会推荐的一个方向,原因很简单:它业务边界清晰、功能闭环完整,技术栈也是最典型的java + vue + SpringBoot + MySQL组合,没有复杂的分布式概念,又能把登录鉴权、CRUD、前后端分离、部署上线这些核心能力全部覆盖到。这篇文章就围绕这个题目,把我带学生完成毕设时的完整路线梳理一遍——从技术选型、数据库设计、核心功能实现,到部署上线和答辩准备,每一步的取舍和原因都会讲清楚。不管你是打算照做,还是想在此基础上改造,都能直接拿去做参考。
1. 技术选型逻辑:为什么SpringBoot + Vue成了毕设标配
1.1 从评审视角看这个选题的独特价值
很多同学选毕设题目时有个误区:觉得题目越偏、技术越新,就越容易拿高分。实际上,评审老师看一个毕设项目,核心判断标准是"完整性"和"技术落地能力",而不是"你用了多冷门的东西"。个人博客系统恰好在这两点上表现突出。
往完整了说,它需要用户注册登录、文章的发布与编辑、分类管理、标签体系、评论互动,还要有管理后台和门户展示端。这个业务跨度决定了项目不可能只写几个增删改查接口就交差,它天然要求你处理"页面—接口—数据库"三层之间的完整链路,而这条链路正是计算机专业核心能力最直观的体现。
过往的评审反馈也印证了这一点。用这个题目答辩的同学,只要能把"用户从浏览器发起请求,到后端校验身份,再到数据库持久化,最后回到前端渲染"这条链路讲清楚,评审基本都会认可。相比纯管理系统,博客系统最大的加分点是它看得见摸得着——前台网页实时呈现,评委可以亲自操作,体验完成度一目了然。这一点在答辩演示环节非常占便宜。
1.2 后端选型:SpringBoot不是唯一答案,却是最稳答案
后端框架的选择其实有不少,SpringBoot、SpringMVC、SSM,甚至有人用Servlet纯手写。如果只从"能跑通"的角度看,哪个都能做,但毕设项目要同时考虑开发效率、文档丰富度、问题排查难度,SpringBoot就成了最优解。
SpringBoot的核心价值在于"自动装配"和"约定优于配置"。同样一个项目,SSM需要写大量XML配置文件,Bean管理、事务声明、数据源配置交织在一起,光调试环境就要花掉两三周;SpringBoot把这些繁琐的东西自动化的同时,还保留了Spring家族完整的功能生态。对毕设开发周期来说,这省下来的时间可以用来打磨功能细节和写论文,性价比完全不同。
为什么不用Spring Cloud这类微服务框架?是因为个人博客系统的业务体量根本够不上微服务的级别。微服务的注册发现、配置中心、熔断降级这些概念,在这个项目里没有任何实际载体,硬塞进来只会让答辩时漏洞百出。技术选型不是越高级越好,而是"刚好够用并且能解释清楚",这点在后面的答辩环节会再次提到。
1.3 前端选型:Vue的渐进式设计让联调省心
前端部分选Vue,而不是React或原生JavaScript,原因也很实际。Vue的学习曲线对Java方向的学生来说是最友好的:模板语法接近HTML直觉,响应式数据绑定免去了手动操作DOM的繁琐,单文件组件的组织方式天然适合中小型项目。
具体到版本选择,Vue 2 + Element UI和Vue 3 + Element Plus是目前两种主流组合。我的建议是预算够就一步到位用Vue 3,理由不是"新的就更好",而是Vue 3的组合式API(Composition API)在处理登录状态管理、路由守卫这些逻辑时,代码组织确实比Options API清晰很多。更重要的是,Element Plus组件库对表单校验、表格分页、弹窗交互的支持,基本覆盖了博客系统后台管理端的所有场景,能省掉大量造轮子的时间。
有学生担心从没接触过前端会不会学不动。以我做过的案例看,只要具备基础的HTML和CSS认知,跟着官方文档把Vue的核心概念——数据绑定、组件通信、路由、状态管理——过一遍,一周内就能上手写页面。真正花时间的往往不是语法,而是"一个页面里的数据从哪来、到哪里去"的思维方式转换,这恰恰是前后端分离架构的核心素养。
1.4 数据库选型为什么锁死MySQL
数据库选择上,MySQL是绝大多数毕设项目的默认答案。有人会用SQLite图轻量,有人用PostgreSQL图性能,但在"个人博客系统"这个场景里,MySQL是综合收益最高的选项。
先说轻量的问题。SQLite确实部署简单,但评审现场老师一旦问"你的系统并发能力怎么样""如果用户量上来怎么扩容",SQLite几乎没有任何回答空间。MySQL作为关系型数据库的绝对主流,资料多、生态好、出了问题随手一搜就有解决方案,这个隐性优势毕设阶段非常重要。
再说设计层面。博客系统的数据天然是结构化、关系型的:用户与文章是一对多,文章与分类是多对一,文章与标签是多对多,评论是自关联的树形结构。这些关系用MySQL的外键和联合查询来表达,天衣无缝,也方便在论文中画E-R图。配合Navicat或MySQL Workbench这样的可视化工具,建表、改结构、导数据都非常直观,适合在写报告时快速产出数据库设计相关图表。
2. 数据库设计:博客系统的表结构规划与关系梳理
2.1 五张核心表到底怎么建才够用
接手这个项目时,我通常建议学生不要一上来就急着写代码,先在数据库里把表结构摸清楚。一个能支撑完整业务闭环的博客系统,最少需要五张表:用户表、文章表、分类表、标签表、评论表。
用户表是最常规的,注意几个容易遗漏的字段:用户名和邮箱建议分别设置唯一索引,密码字段存储的是加密后的密文而不是明文,状态字段用于禁用/启用账号。文章表是业务核心,字段除了标题、正文、摘要、封面图之外,还要有分类外键、作者外键、浏览量、是否置顶、发布状态。这里要特别提一下发布状态字段,很多初学者把它做成"删了就没了",但更合理的做法是用一个status字段区分草稿和已发布,这样文章编辑时的自动保存机制才有落地的数据基础。
分类表和标签表乍一看很像,但语义完全不同。分类是层级结构的,比如"编程"下面可以分"Java"和"前端";标签则是扁平化的,一篇文章可以打多个标签,一个标签也能挂多篇文章。这个差异直接决定了它们的表设计:分类表需要一个parent_id自关联表示层级,标签表则通过一个中间表article_tag和文章形成多对多关系。中间表的设计经常被忽略,但它恰恰是论文里"数据库设计合理性"的重要加分点。
评论表要同时关联用户和文章,还需要一个parent_id字段指向自身来做楼中楼回复。FIRST一点是删除策略:用户删除评论时,子评论怎么处理?通常的做法是软删除,用一个is_deleted标志替代物理删除,这样既保留评论关系,又避免级联删除带来的复杂逻辑。
2.2 索引设计:不要等到数据多了才后悔
数据库这关真正拉开差距的,不是建表,而是索引设计。很多学生把主键索引建完就认为完事了,结果到答辩演示时,数据量稍微大点,查询接口就明显卡顿,一查慢查询日志,全表扫描。
博客系统里最常用的查询场景有三个:前台按发布时间倒序拉取文章列表,后台按分类或标签筛选文章,用户中心查询自己的文章列表。对应到索引策略,就是给文章的create_time建普通索引,给category_id、author_id建外键索引,给标签中间表建(article_id, tag_id)联合索引。
这里有个实战细节:不要每个字段都加索引,索引不是越多越好。写操作频繁的表,索引过多会拖慢插入和更新性能。我见过有人给评论表的content字段加索引,这就是典型的无意义操作——评论内容基本不会作为查询条件,反而白白增加了存储开销。建立索引的原则始终是"跟着查询走",你的SQL里WHERE、ORDER BY、JOIN用到了哪一列,优先给哪一列建索引。
2.3 初始化数据与演示账号的坑
数据库设计完成后,别急着写代码,先把初始化数据和演示账号准备好。这一步看着不起眼,实际影响答辩体验。
演示账号的建议是建两个层次:一个是管理员账号,用来演示后台管理的文章审核、用户管理、分类维护;一个是普通用户账号,用来演示前台评论、点赞等用户行为。密码统一用BCrypt加密后再写入SQL文件,千万别把明文密码直接放进初始化脚本,这既不安全,也容易在答辩时被评委追问"密码为什么是明文存储"。
初始化数据还有一个容易被忽视的点:文章的初始数据不要太少,也不要是清一色的"测试文章"。建议准备8到10篇内容不同的文章,覆盖两三个分类,带几个标签,顺便造一些浏览量和评论数。这样做的好处是,打开前台页面时视觉效果完整,分组筛选、标签云、搜索这些功能演示起来才有操作对象。如果整个页面只躺着两三条测试数据,再好的前端设计都显得空洞。
3. 后端核心模块实现:登录鉴权、文章管理与接口设计
3.1 JWT登录鉴权的完整链路
用户登录是博客系统里最有技术含量、也是答辩最容易被追问的模块。我的建议是选择JWT(JSON Web Token)方案,而不是传统的Session方案,原因有三:前后端分离架构下Session天然不友好(需要处理跨域Cookie、Session共享),JWT无状态特性契合RESTful风格,JWT本身就携带用户信息方便前端做权限控制。
具体实现链路是这样的:用户登录成功后,服务端用JWT工具类生成一个带过期时间的Token,Token的payload里放用户ID、用户名和角色,然后返回给前端。前端拿到Token后存储在本地,之后每次请求都在请求头Authorization字段里带上它。服务端通过拦截器或过滤器统一校验Token的合法性和有效期。
这块最容易出问题的地方是拦截器配置。我的经验是登录接口、注册接口和前台的文章列表接口必须放行,后台管理接口全部拦截。实际开发中不少学生在这里栽跟头:拦截器写得太死,把前台的正常请求也拦下来,导致页面打不开,排查半天才发现是Token没过期却被误判。
密码安全层面,推荐使用Spring Security自带的BCryptPasswordEncoder,或者Hutool工具类里的BCrypt支持。BCrypt的特点是每次加密结果都不同,但校验算法可以正确比对,能有效抵御彩虹表攻击。这个细节虽然简单,但能体现你对密码存储安全性的理解,答辩提一句就是加分项。
3.2 文章CRUD与Markdown处理的细节
文章管理是整个系统功能密度最高的模块。后台需要支持新增、编辑、删除、置顶、上下架,前台需要支持分页查询、详情展示、浏览量累加。每一个操作背后都有对应的接口设计,写代码前先把接口清单列出来能少走很多弯路。
文章正文的存储格式是我碰到的咨询最多的问题。纯文本格式简单但不适合排版,富文本编辑器的HTML内容保存后容易有XSS注入风险,两者都不是理想选择。比较推荐的方案是使用Markdown编辑器(前端用mavon-editor或vditor),后端存储Markdown原文,展示时前端用markdown-it等库渲染成HTML。这样既保留了排版的灵活性,又因为Markdown本身是纯文本格式而规避了大部分注入风险。
浏览量累加这里有个性能细节。文章每被访问一次就执行一次UPDATE article SET view_count = view_count + 1 WHERE id = ?,在低并发场景下没问题,但答辩如果往高并发方向聊,可以提一下"先更新Redis缓存再定期批量落库"的优化思路。不需要真的实现,但能说明白思路就是好的知识储备。
3.3 统一返回结构与前端的"对齐焦虑"
前后端分离项目里,接口返回格式不统一是联调阶段最大的痛点。常见的问题是:有的接口返回{code: 0, data: {...}},有的返回{success: true, result: [...]},前端需要为每个接口单独适配,代码写出来既丑陋又容易出错。
正确做法是在后端定义一个统一的响应对象Result<T>,包含三个字段:状态码code、提示信息msg、业务数据data。成功时返回Result.success(data),失败时返回Result.error(code, msg)。配合全局异常处理器@RestControllerAdvice,把空指针、参数校验失败、业务异常统一包装成Result结构返回。
这样设计后,前端可以写一个统一的请求封装,在响应拦截器里判断code是否为200,不是就全局弹出错误提示,业务代码完全不用关注错误分支。别小看这个设计,它在论文"系统设计"章节里是很扎实的亮点,也是真正工作环境下的大厂规范。
4. 前端工程化实践:页面组织、路由守卫与展示层实现
4.1 从零搭建Vue目录结构
前端代码的组织方式直接影响项目的可维护性和答辩时的讲解流畅度。我第一次带学生做这个项目时,有人把几十个组件全堆在components目录里,页面路由和组件混在一起,后期改需求时痛苦不堪。
推荐的结构是:src/api放所有接口请求封装,src/views按页面功能划分目录(首页、文章详情、登录注册、分类、标签、后台管理等),src/router统一管理路由配置,src/store放全局状态管理,src/components只放通用组件。后台管理端和前台门户端在路由层面做区分,后台路由统一加上/admin前缀,配合路由守卫做权限控制。
这个结构的价值在写论文时也能体现出来,"前端采用按功能模块划分的工程化目录结构"这样一句话是有真实落地支撑的,比起空谈"模块化"更有说服力。
4.2 路由守卫与Token持久化的配合
前台页面人人都能访问,但后台管理的每个页面都必须登录后才能进。这个控制逻辑放在后端拦截器里是一层,前端路由守卫是第二层。两层的意义不同:后端拦截保障数据安全,前端守卫提升用户体验。
前端的实现方式是,在全局前置守卫里读取本地存储中的Token,判断用户要访问的路由是否在requiresAuth列表里,是则检查Token是否存在,不存在就跳转到登录页并带上redirect参数,登录成功后原路跳回。这里最容易被忽略的是Token失效的后续处理:当我们调用后台接口返回401时,前端要做的不仅是弹个错,还要清掉本地Token并跳转回登录页,避免用户停留在页面里反复触发无效请求。
Token的存储位置,有人放localStorage,有人放sessionStorage,还有人用Cookie。我的建议是localStorage,原因很简单:博客系统是内容型站点,用户可能希望下次打开还保持登录状态,sessionStorage关闭浏览器就丢了,体验不好;而Cookie方案还要额外处理跨域携带的问题,不值当。
4.3 编辑器接入与页面渲染的双向细节
编辑器的接入是前端工作量最集中的地方。选型上,mavon-editor基于Markdown,界面清爽、文档齐全,适合中文场景;如果不想用现成编辑器,也可以使用简单的textarea配合预览面板,但交互体验会差一大截。
接入编辑器时要注意两个问题。第一个是模型绑定:编辑器的输入内容要同步到表单数据模型,通常用v-model就能实现,但要注意编辑已有文章时,编辑器初始化需要拿到文章内容回显到编辑区,此时要在组件挂载完成后调用markdown的API设置文章内容。第二个是图片上传:粘贴或上传图片时,编辑器会发送请求到后端,后端需要单独提供一个图片上传接口,返回图片URL再回填到编辑区,这涉及到后面提到的静态资源映射问题。
前台展示端相对简单,用markdown-it把后端返回的Markdown原文渲染成HTML就行。需要注意的是XSS处理,即使文章作者是可信的,也建议对渲染结果做一轮xss过滤,这是答辩时"系统安全性"部分的言之有物的证明。
5. 前后端联调:跨域、文件上传与格式化踩坑记录
5.1 跨域配置的正确写法
前后端分离架构下,跨域是躲不开的第一道坎。前端跑在localhost:8080,后端跑在localhost:9090,浏览器的同源策略直接拦截跨端口请求。解决方式很多:CorsConfiguration手动配置、@CrossOrigin注解、前端代理转发,我推荐的是后端统一配置CorsFilter。
为什么不用@CrossOrigin?因为这个注解是加在Controller方法或类上的,一两个接口还好,接口多了每个都要加一遍,容易遗漏而且不优雅。CorsFilter全局配置一次,所有接口统一生效,既省事又规整。
配置时有个细节容易踩坑:允许的请求来源allowedOrigins别图省事写成*。写成*意味着任何域名都能跨域访问你的接口,这在答辩安全性质疑面前是减分项。正确的做法是明确指定前端的实际访问地址,比如http://localhost:8080,如果需要支持线上域名再补充上。这对学生来说可能觉得"我本地跑通关我啥事",但我负责地说,这些细节恰恰是专业度的体现。
5.2 文件上传路径与静态资源映射
博客系统里绕不开用户上传头像和文章配图的需求。文件上传接口本身不复杂,但文件存哪、怎么访问,是两个容易在联调期炸雷的问题。
我的建议是后端定义一个统一的上传目录,比如项目根目录下的upload/文件夹,按日期分子目录存放。文件保存后,把"/files/2024/05/20/xxx.jpg"这样的访问路径返回给前端。前端拿到这个路径后,如果直接拼到后端域名下面去访问,就会出现404,因为SpringBoot默认只映射classpath:/static/下的静态资源。
解决办法是配置一个映射规则,把URL路径/files/**映射到本地磁盘的上传目录。实现方式可以继承WebMvcConfigurer重写addResourceHandlers,也可以通过配置文件指定。这一步做完后,前端就能直接通过host + /files/...访问到图片资源了。还有一个小技巧:上传时对文件名做随机化处理(UUID),避免用户上传同名文件互相覆盖,也避免中文文件名在部分浏览器里出现编码问题。
5.3 时间格式化与前端展示不一致问题
联调时另一个高频bug是时间类型前后端不一致。后端MySQL里的datetime字段,通过Jackson序列化返回给前端时,默认是2024-05-20T12:00:00.000+00:00这种带T的ISO格式,前端直接用显示效果就是"2024-05-20T12:00:00",看着非常别扭。
解决方案有两条路。第一是在后端统一配置Jackson的时间序列化格式,在配置文件中把spring.jackson.date-format设为yyyy-MM-dd HH:mm:ss,同时设置时区GMT+8。第二是后端返回时间戳,前端在展示层用工具函数格式化,好处是彻底避开时区问题。
我倾向于方案一,因为改动最小、影响面最广,前端所有页面自动生效。但有一个坑值得提醒:如果接口里返回的字段名是createTime,前端在JavaScript里可能会遇到长整型精度问题,这是下一个踩坑点——Long类型主键在经过JSON序列化传给前端时,JS的Number精度会丢位。解决方式是在主键字段上用@JsonSerialize(using = ToStringSerializer.class)注解,将其转成字符串返回。这个坑我不会说必踩,但大概率会踩,提前打上补丁能省一晚上的排查时间。
6. 部署上线:从jar包到云服务器的完整路径
6.1 本地打包构建与常见报错
部署上云这件事,很多学生一直拖着不做,直到答辩前一周才手忙脚乱地搞。我的建议是提前两周开始,因为部署涉及的东西和本地开发完全不同,问题往往不在代码逻辑,而在环境。
后端打包前,检查一下application.yml里的配置是否适合生产环境。数据库连接地址要改成云服务器的MySQL地址,端口、账号密码同步更新。如果Redis有使用,同理。打包命令很简单,在项目根目录执行mvn clean package -DskipTests,确认编译通过后在target目录下能生成xxx.jar文件。
常见报错里,最让我印象深刻的是"本地能启动,打包后启动报错",十有八九是配置文件里的绝对路径问题,比如日志文件路径、上传目录路径用的是C:/...这种本地路径。打包前把这些路径改成相对路径或者用user.dir动态拼接,能省去大量部署时的低级报错。
前端打包是npm run build,产物在dist目录下。打包完成后先本地预览一下,我的习惯是本地起一个Nginx或者直接双击index.html验证产物是否正常,确认无误再传到服务器。前端打包最常见的问题是资源路径不对,部署到服务器子目录时空白页,解决方式是调整vue.config.js里的publicPath配置。
6.2 Nginx反向代理与后端进程守护
JDK和MySQL安装完成、数据库导入完毕后,就到了关键的部署环节。生产环境的架构通常是这样:Nginx监听80端口,处理前端的静态文件请求,同时把/api前缀的请求反向代理到后端SpringBoot的9090端口。
Nginx配置里最核心的location块是:
location /api/ { proxy_pass http://127.0.0.1:9090/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }proxy_pass后面带不带最后的斜杠,行为差别很大,带斜杠表示代理时去掉/api前缀再转发,这是很多初学者反复踩的坑。另外,前端静态文件的location需要配置try_files $uri $uri/ /index.html;,否则刷新路由时会404,因为Vue是单页应用,路由由前端接管而非后端。
后端进程管理上,有人习惯直接nohup java -jar xxx.jar &,但这有个问题:服务器重启后还需要手动启动。建议用systemd编写一个服务文件,实现开机自启和崩溃重启。用systemd还有一个附加优势:可以把应用日志统一交给journalctl管理,排查问题方便一条命令就能看日志。
6.3 数据库的迁移与线上数据初始化
部署时数据库这块有两件事:一是本地数据库的表结构和数据同步到服务器;二是确认线上库的账号密码和配置文件一致。
表结构和数据同步,最简单的做法是用Navicat的结构同步和数据同步功能,图形化操作,十几秒搞定。更纯粹的方式是导出SQL脚本,在服务器上执行mysql -u root -p < blog.sql。无论哪种方式,都要在导入后做一次完整的验证:登录后台、发布一篇文章、上传一张图片、发一条评论,把核心链路在线上环境跑通。
如果本地环境有意调过数据,比如为了演示准备了多篇真实感文章,最好在同步时就把这些演示数据带上。但记得清掉隐私数据,比如本地测试用的真实手机号。
线上环境还有一个校验要点:检查数据库连接的时区参数serverTimezone=Asia/Shanghai,否则可能会出现与本地环境不一致的时区偏移,导致文章发布时间显示错误。
7. 报告写作与答辩现场的攻防准备
7.1 论文结构怎么组织最省力
写论文这件事,如果项目是认真做的,其实只需要把做过的内容结构化复述一遍,重点是不要浪费时间在"凑字数"上。
推荐的结构是:第一章绪论,写研究背景和意义、国内外研究现状、主要工作;第二章相关技术介绍,用两三页篇幅把Vue、SpringBoot、MySQL、Element UI介绍清楚;第三章需求分析,画用例图、功能需求表格、非功能需求;第四章系统设计,详细画出系统架构图、功能模块图、数据库E-R图和表结构;第五章系统实现,按功能模块逐一分段截图加描述;第六章系统测试,用测试用例表格覆盖核心功能;最后是总结与展望。
论文写作的一个建议:不要先写完全部内容再改,而是边开发边记录截图和心得。项目做到哪一步,论文就写哪一部分,最后统一整理排版。很多学生项目做完了论文一个字没动,等到deadline前通宵赶工,写出来的质量和边开发边写的完全不在一个量级,因为开发过程中的细节、踩坑经历、设计调整,这些都是论文素材,过一个月你会全部忘光。
7.2 答辩演示的黄金三分钟
答辩时演示环节的节奏比内容更重要,因为评委的注意力在最开始的三分钟最集中。开局的解决方案是:先展示前台效果,用一两句话介绍这是面向用户的博客门户首页,然后马上切到后台,现场发布一篇新文章,再到前台刷新看到效果。这个完整闭环的冲击力非常大,看着台上几十秒内走完了"写文章→审核→展示"的全程,比讲任何技术细节都更有说服力。
演示前务必准备一个"失败预案":如果Nginx挂了、数据库连不上、演示数据被误删了怎么办。我的习惯是在电脑本地也保留一套独立的环境,答辩时万一云服务器出问题,立刻切到本地演示。另有几个演示细节:提前清空掉可能泄露隐私的本地数据;浏览器提前打开所有会用到的页面,别在答辩现场敲URL;展示后端接口时用接口测试工具而不是直接用浏览器,可以看到返回JSON,更有技术感。
7.3 高频追问与回答思路
答辩环节会被问的问题,来来回回就那么几类,提前准备比临场发挥要稳得多。
第一类:为什么用这个技术栈?这时合理归因到我在第1章讲的"业务体量匹配、团队/个人技术栈熟悉、社区生态完善"。注意,答辩时一定要坦诚,用"适合项目"而不是"最流行"来回答,反而更可信。
第二类:安全问题,比如"密码怎么存储""如何防止SQL注入"。前者答BCrypt加密,后者答MyBatis/MyBatis-Plus的预编译机制#{}占位符。顺便可以提一下Token过期时间的设计,这是你没有用Session带来的潜在质疑点,提前想好解释:JWT的过期时间为什么设为24小时、如何通过Redis黑白名单解决JWT无法主动失效的问题。
第三类:功能扩展的探索,比如"如何优化性能""如何应对高并发"。实话实说这个系统不支撑高并发,但要展示思维——比如在数据库层面加索引、加Redis缓存、横向扩展部署多实例。建议不要为了答辩而虚构实现过的功能,被追问到细节就会露馅。
这三类问题之外,还有一个几乎必问的:你自己在项目中遇到的最大困难是什么,怎么解决的。这个问题我反而建议提前准备一个"真实故事"——可以是跨域联调时排查了很久才发现是代理配置的错误,也可以是前端表格数据id精度丢失导致编辑失败的bug。具体的困难故事远比"没有遇到什么困难"这个回答更能展示工程实践能力。
最后说点个人的体会。我带过的学生里,凡是亲自动手把整个流程走完的,答辩时都很有底气,因为项目里的每个细节都是自己趟过的;凡是买现成源码背PPT的,被评委追问一轮就会破绽百出。这个道理放在就业里也一样,简历上写着博客系统项目,面试官大概率还会继续问"你的博客怎么处理评论的层级关系""如果让你重构你打算怎么做",没有真实做过,这些问题一个都接不住。老老实实把每一步跑通,比什么技巧都重要。