每年这时候,都有一批计算机专业的同学被毕业设计折腾到头秃。代码写不出来是种折磨,项目做完了论文没东西写又是另一种折磨。我见过太多人卡在这两关之间反复横跳,最后只能临时找个模板改改交差,答辩的时候一问三不知。
如果你也在为毕设选题发愁,又想用一套技术栈把开发、论文、部署全流程一次打通,那我强烈推荐你考虑“SpringBoot+Vue+MySQL 手机商城”这个方向。手里这套欢迪迈手机商城,就是典型的前后端分离项目:前台用户可以注册登录、浏览商品、加购物车、下单支付,后台管理员可以管理商品、订单、用户、分类,功能覆盖了电商系统的核心链路,既不会像并发秒杀那么深奥难啃,也不是只有增删改查的摆设,工作量、难度、论文深度都正好卡在本科毕设的甜点上。
这篇文章我不讲空话,直接把整个项目的设计思路、后端接口、前端页面、数据库表、部署流程、论文写法,包括实际开发中踩过的坑,一次性给你讲透。你照着这个思路去复现或者改造,至少能少熬两个星期的夜。
1. 项目整体定位与技术选型:为什么这套组合最省心
1.1 手机商城作为毕设题目的底层逻辑
说“手机商城”是毕设常青树,真不是因为它简单,而是因为它的业务链路足够完整,能让你把大学四年学的东西串起来。
回头看一个电商站点的核心流程:用户登录→浏览商品→添加购物车→提交订单→支付→查看订单→收货完成,再加上后台的商品上架、订单处理,这套流程里涉及到用户权限、商品检索、状态流转、事务处理,每一项都能在系统设计里找到对应的落脚点。论文写起来逻辑也很顺——“需求分析→系统设计→数据库设计→功能实现→系统测试”,每一章都有真实内容填充,不会出现那种“写了两千字就开始复制粘贴”的尴尬。
更关键的是,手机商城的需求边界清晰,模块之间耦合度适中,扩展空间也大。比如你想加分,可以加个商品评论模块、收藏功能、后台数据统计;想控制工作量,砍掉支付对接改成模拟支付也是常规操作。这种“可深可浅”的特性,特别适合答辩时间不确定、导师要求不明确的场景。
1.2 技术栈选择的真实理由
技术栈上,SpringBoot+Vue+MySQL 是毕设圈绝对的“三件套”,但为什么是这三样,很多人其实没想清楚。
后端用 SpringBoot,核心优势是“约定优于配置”。你不用像以前用 SSH 那样写一堆 XML 配置文件,建一个 Spring Initializr 项目就能直接写接口,内置的 Tomcat 让它打包成 jar 即可运行,这对精力大部分被论文占用的毕业生来说极其友好。同时 SpringBoot 对 MyBatis-Plus 的整合几乎零成本,单表 CRUD 连 SQL 都不用写,直接调用现成的 Service 方法,能把开发周期压缩 40% 左右。
前端用 Vue,国内生态最成熟。组件的思路让页面代码可复用性很高,比如商品卡片、订单状态标签这种东西写一次就能到处用;配合 Vue Router 做页面路由,配合 Axios 做接口请求,配合 Element UI/Element Plus 做现成的组件库,一个新手也能在短时间内拼出一个像模像样的商城页面。Vue2+Element UI 的资料最多,遇到问题几乎都能搜到答案,Vue3+Vite+Element Plus 的性能更好、组件库也在快速完善。做毕设建议选熟悉的那一套,如果之前上课学过 Vue2 就直接用 Vue2,稳稳当当能跑就行。
MySQL 更不用多说,开源免费、资料多,Navicat 一导 SQL 就能把表建好,学习成本几乎为零。
1.3 前后台功能模块拆解
整个欢迪迈手机商城分两个“端”,对应两套前端页面和一组后端接口。
前台用户端是给普通用户用的。这里要区分清楚,这不是单纯做个静态页面展示,而是要把用户操作闭环跑通。用户注册登录后,能看到首页轮播图、手机分类、热销商品列表,点进商品详情看参数和价格,加购物车,进购物车改数量、选规格,下单选地址,提交订单进入支付流程。支付这块如果没对接真实支付渠道,就做“模拟支付”,用户点付款后直接由系统把订单状态改成已支付,留出一个扩展对接的接口位置,论文里也能写“后续可对接第三方支付平台”,这是毕设里最常见的做法。
后台管理端是给管理员用的,功能按管理员身份区分为商品管理、分类管理、订单管理、用户管理、轮播图管理。管理员登录后能上下架商品、修改库存和价格、处理订单发货、查看用户列表。后台页面不需要多花哨,实用性优先,Element 的表格和表单组件拿过来用就行。
2. 后端核心模块设计:把一条用户购买链路拆开看
2.1 用户模块:注册登录与 JWT 鉴权
用户模块是所有模块的地基,因为后面所有操作都要基于“当前登录用户是谁”这个前提。
注册逻辑很直接:前端把用户名、密码、确认密码提交过来,后端先校验用户名是否已存在,再对密码进行加密存储。密码千万不能存明文,这几乎是整个项目里我最想叮嘱你的一件事。毕设答辩时老师随手打开数据库一看,如果用户密码全是明文,印象分直接减半。用 Spring Security 的 BCryptPasswordEncoder 或者 Hutool 的 MD5 加盐都可以,前者更规范,后者更简单,毕设选一个实现明白原理就够了。
登录逻辑要处理的是状态保持。传统 JavaWeb 用 Session 存用户信息,前后端分离的项目一般改用 JWT(JSON Web Token)。用户登录成功之后,后端生成一个 Token 返回给前端,前端把它存在 localStorage 里,每次请求都放到请求头的 Authorization 字段中。后端写一个拦截器,放行登录注册接口,拦截其他需要身份的接口,逐个校验 Token 的合法性并从 Token 里解析出用户 ID,存入请求上下文供后续逻辑使用。
这里你还需要把用户角色区分开。普通用户访问的是 /user/** 下的接口,管理员访问的是 /admin/** 下的接口,拦截器里校验 Token 之后还要判断角色,权限不足直接返回 403。实际开发中我用一个简单的 UserContext 类,用 ThreadLocal 存放当前登录用户信息,请求结束时清理掉,代码会清爽很多。
2.2 商品模块:分类、搜索与上下架
商品模块是商城的门面,前端看到的所有商品数据都来自这里。
商品的表结构设计上要注意“一对多”的层级关系。一个分类下面有多个商品,一个商品有多个 SKU(比如不同颜色、不同存储容量的型号),毕设项目通常会把商品基本信息表(product)和 SKU 表(product_sku)分开建,商品详情页展示主图、介绍、参数,选择规格时根据 SKU 对应的价格和库存来展示。如果不想在 SKU 上花太多精力,也可以把“颜色”“内存”当成商品字段直接存字符串,价格和库存就存一份——两种方案都能跑通,区别在于论文里写“系统设计了 SKU 机制”会更显深度。
商品接口的核心是分页查询和条件筛选。用 MyBatis-Plus 的 Page 对象配合 LambdaQueryWrapper,可以很优雅地实现按分类筛选、按关键词模糊搜索(手机名称)、按价格排序、按销量排序。有一个细节我特别提醒:库存和销量这两个字段千万不要每次请求都去统计订单表,直接在 product_sku 表里加一个 sales 字段,下单成功就给对应 SKU 加销量减库存,展示数据秒出。
商品上下架就是个状态位的切换,product 表里加一个 status 字段,1 表示上架,0 表示下架。前台查询接口默认只查 status=1 的数据,管理端则全部显示出来用 Switch 开关控制。
2.3 购物车与订单:事务与状态机
购物车是订单的前置准备,它的表结构很简单:用户 ID、商品 SKU ID、数量、加入时间。这里要注意一个体验问题,同一个用户把同一个 SKU 加两次购物车,不应该产生两条记录,而是把数量累加。查询购物车列表时要联表查出 SKU 的商品图、名称、价格,因为前端列表页不可能只展示几个 ID。
提交订单是整个项目里事务最密集的地方。用户在结算页确认收货地址和商品清单后,点击提交订单,后端要做的事情按顺序排开:检查库存是否充足→锁定库存→生成订单主表记录→生成订单明细表记录(快照商品名称、价格、图片)→清空购物车对应商品→如果订单选择余额支付还需要扣减余额。中间任何一步出错,整个操作都必须回滚,所以这个流程要用 @Transactional 注解包起来。
我实际开发时踩过一个坑:一开始把“扣减库存”写在生成订单之后,结果并发情况下会出现订单生成了库存变负数的情况。后来调整逻辑,把库存校验和扣减放在最前面,并且给 product_sku 表的库存字段加了判空条件,SQL 里带上库存大于等于购买数量的条件,用数据库层面的行锁来兜底,才彻底解决。
订单状态也是毕设论文里必须重点写的一块。我设计的枚举有五态:待付款(0)、待发货(1)、待收货(2)、已完成(3)、已取消(4)。状态流转是“提交订单→待付款→模拟支付→待发货→管理员发货→待收货→用户确认收货→已完成”,任何一步都要校验当前状态合不合法,比如已支付订单就不能再取消,已取消订单更不能去发货。
2.4 支付与回调的处理细节
毕设项目的支付处理有两条路。
第一条是接支付宝沙箱。支付宝开放平台有现成的沙箱环境,你申请一个开发者账号,配置好应用公钥、私钥、支付宝公钥,引入 alipay-sdk 就能调通支付流程。好处是论文里截图特别真实,支付页面一出来,答辩老师就知道你是真做了东西;坏处是配置过程繁琐,公钥私钥的坑能折腾一整天,而且沙箱账号和手机号实名信息容易出问题。
第二条是模拟支付,也是我更推荐的做法。所谓模拟支付,就是在支付页面放一个“确认支付”按钮,前端调后端的支付接口,后端直接把这个订单的 status 从 0 改成 1,同时做一笔支付流水记录。我在这个项目里还把支付的接口名写成 /pay/simulate,并且预留了一个 PayStrategy 的接口,注释里写明后续如果对接微信或支付宝,只需要实现同一个接口——这种“可扩展设计”在论文里是实打实的加分项,比写一堆“本系统界面友好”的废话有说服力得多。
无论选哪种,订单支付成功后的回调逻辑都是一样的:校验订单状态、更新状态、更新 SKU 库存和销量、生成支付流水。这些操作和前面一样要放事务里。
2.5 后台管理接口的设计思路
后台管理接口的代码量其实比前台还大,因为涉及的实体多,每个实体都有列表、新增、修改、删除、分页几个标准接口,但难点在于写通用查询和权限控制。
管理员模块的核心是角色与权限。毕设版通常只做“超级管理员”一种角色,能操作全部功能,所以只需要一张 admin 表存账号密码(同样加密),登录成功后返回一个 role=admin 的 Token。后端拦截器对 /admin/** 路径统一校验角色,校验不过直接返回 401。如果你想写得更细一点,可以抽一张 resource 表存菜单权限,admin_role 表和 role_resource 表做多对多关联,前端根据返回的权限列表动态渲染菜单——这个扩展我在论文里作为“系统可改进方向”写了,并没有实际写到代码里,但答辩时能讲出这个思路已经比同届多数同学强了。
商品、分类、轮播图、订单的后台管理接口可以统一走一个套路:分页查询接口(Controller 接收页码、每页条数、查询条件)、新增接口、修改接口、删除接口。订单管理额外有一个发货接口,把订单状态置为 2 并补全发货时间、物流单号。删除商品时要注意关联数据,如果某个商品已经有用户下单了,直接物理删除会让订单明细变成“悬空数据”。我用了逻辑删除,product 表加 deleted 字段,列表查询时 MyBatis-Plus 会自动过滤,既能保住数据完整性,论文里也能写一笔“采用逻辑删除保护历史数据”。
3. 前端实现思路:从页面骨架到接口联调
3.1 前台页面的路由与组件规划
前端这部分我用 Vue 来搭,用 Vue Router 管理页面跳转,页面划分为两大类:不需要登录就能看的和需要登录才能看的。
不需要登录的有:首页、商品列表页、商品详情页。需要登录的有:购物车页、结算页、订单列表页、订单详情页、个人中心页。这个“需要登录”的判断逻辑在路由配置里用导航守卫实现,判断 localStorage 里有没有 token,没有就弹登录框或跳登录页。
首页是给老师的第一印象,包含顶部导航、轮播图、分类入口、热销商品列表。商品列表页是搜索和筛选的主战场,顶部是搜索框,左侧是分类栏,右侧是商品卡片列表,用分页组件加载数据。商品详情页的信息比较密集,要展示商品的轮播大图、标题、价格、规格选择器、库存数量、购买数量、直接购买和加入购物车两个按钮。
购物车页要支持勾选、修改数量、删除、合计结算四个动作。这里有个小坑:全选框的“全选”和单个商品的“勾选”要联动,选中状态变化时重新计算总价,而总价的计算不要用 v-model 的响应式去监听每一项再手动加,直接在 computed 里遍历选中项算出总和,代码简洁不容易出 bug。
结算页要做两步:确认商品清单和填收货地址。收货地址我单独建了一张表,结算页里可以新增、选择、删除地址,选中的地址 ID 随订单提交给后端。订单提交成功后跳转到支付页,支付页展示订单号和应付金额,点击确认支付调用后端支付接口,然后跳转到订单列表页,让用户看到新的订单状态。
3.2 后台管理页面的实现思路
后台管理页面和前台是两套独立的路由,我习惯把 vue-router 的 history 模式配好之后,在 /admin 路径下建一个 AdminLayout 父组件,里面放左侧菜单和右侧内容区,菜单项渲染后台各功能模块。
每个模块页面就是 Element 组件的排列组合。商品管理页用 el-table 展示商品列表,每行有编辑、上下架、删除按钮;点击新增或编辑时弹出 el-dialog 表单,包含商品名称、分类下拉框、主图上传、价格、库存等字段;分类管理页用 el-tree 展示多级分类,也可以简化成一级分类用 el-table 直接管理。订单管理页展示订单列表,订单状态用 el-tag 展示不同颜色,操作列有发货按钮,发货时弹窗填物流单号。
后台页面有两点值得多说。一是表单校验,Element 的 form 组件自带 rules 规则,必填项、格式校验(价格必须大于 0、库存必须是整数)直接配置就行,不用手写一堆 if。二是图片上传,我用的方式是前端把图片文件传到后端一个 upload 接口,后端保存到服务器本地并返回访问路径,前端再把路径作为商品字段提交。上传时要限制文件类型和后缀,防止有人传个 exe 进来,虽然毕设项目攻击面不大,但论文里写了“做了文件类型白名单校验”就不会被老师挑刺。
3.3 Axios 封装与接口联调的关键细节
前后端联调最容易出的问题,第一是跨域,第二是 Token 丢失。
跨域问题在后端解决更干净。我在 SpringBoot 里写了一个 WebMvcConfigurer 配置类,重写 addCorsMappings 方法,允许所有来源访问所有接口,允许携带凭证,允许所有方法。这个方法配置完就不用前端做什么了。但是要注意,如果后面你把前端打包后用 Nginx 和 SpringBoot 端口分开部署,反向代理本身会解决跨域,但如果直接本地开两个端口联调,CORS 配置就是必须的。
Axios 封装的核心是拦截器。请求拦截器里读 localStorage 的 token,存在就加到请求头的 Authorization 字段。响应拦截器里做三件事:HTTP 状态码 401 时跳转登录页、后端返回的业务错误码(比如 code 为 500)时弹出错误提示、其他情况正常返回数据。封装好之后,页面里的请求就只剩一个 api.xxx() 的函数调用,代码非常干净。
接口联调时我建议先把接口文档和命名规范提前定死。后端接口返回统一用 { code: 200, data: ..., msg: "success" } 这种格式,前端封装层解析一次,后面所有页面都不用关心异常结构。这算是一个小的工程化实践,论文里也能提一句“前后端通过统一响应体进行数据交互”。
3.4 图片资源的本地存储方案
图片这块是很多新手容易卡住的地方。
最简单的方案是把图片放到 SpringBoot 的 static 目录下,部署时一起打进 jar,但这样每次发布都要重新打包。我用的是独立目录存储:后端配置一个本地磁盘路径(比如 D:/upload 或者项目外的 upload 目录),上传接口把文件写到这个目录,同时返回访问 URL(比如 http://localhost:8080/upload/xxx.png)。为了让这个 URL 可访问,需要一个映射配置,把 /upload/** 路径映射到实际磁盘目录。
这个方案在本地开发很好使,但要注意几个点:一是文件名的冲突问题,我用 UUID 重新生成文件名,避免中文或重复名;二是服务器重启后数据不会丢,因为目录在工程外;三是答辩换机器演示时,记得把 upload 目录一起拷贝过去,不然页面图片全是裂图,那场面非常尴尬。我自己就因为这个在预答辩时吃过亏,后来每次打包都先确认有没有遗漏图片目录。
4. 数据库设计:手机商城到底需要几张表
4.1 核心表结构与字段设计
很多人拿到题目第一时间就是建表,但我的习惯是先画一遍业务流程图,把每个环节涉及的实体写出来,再转成表结构。欢迪迈手机商城的核心表大概九张:
| 表名 | 作用 | 关键字段 |
|---|---|---|
| user | 用户表 | id、username、password、nickname、phone、avatar、status |
| admin | 管理员表 | id、username、password、real_name、role |
| category | 商品分类表 | id、name、parent_id、sort |
| product | 商品表 | id、category_id、name、sub_title、main_image、detail、status、deleted |
| product_sku | SKU表 | id、product_id、spec、price、stock、sales、image |
| cart_item | 购物车表 | id、user_id、sku_id、quantity、checked |
| address | 收货地址表 | id、user_id、name、phone、province、city、district、detail、is_default |
| orders | 订单表 | id、order_no、user_id、address_json、total_amount、status、pay_time、ship_time |
| order_item | 订单明细表 | id、order_id、sku_id、product_name、product_image、price、quantity |
订单表为什么要存 address_json 而不是存地址 ID?因为用户下单后地址可能改了,订单需要保留当时快照。同样,order_item 里存了商品名称和图片的冗余字段,也是为了让历史订单不依赖商品表的现有数据。这个“快照”的概念,正是数据库设计里第三范式与冗余取舍的典型案例,放到论文里可作为重点展开。
4.2 字段类型与索引的两个关键点
字段类型上最容易被忽略的是金额字段。价格一律用 decimal(10,2),千万别用 float 或 double,浮点数的精度问题会在累计计算时出各种妖蛾子。库存用 int 就够了,但要在应用层保证不小于 0,数据库层面可以加 CHECK 约束,MySQL 8 以上是支持的。
索引的设计别贪多,但两个核心索引必须有:user_id 在 orders 表(查询某用户订单列表高频)、order_id 在 order_item 表(查询订单明细高频)。此外,order_no 唯一索引也建议加上,因为前端用订单号展示,后端也用订单号定位记录,重复单号会直接导致业务异常。
4.3 事务与并发:下单防超卖的处理
前面提到下单流程要用事务,这里展开讲讲具体怎么处理“超卖”。
最简单的防超卖 SQL 是 UPDATE product_sku SET stock = stock - #{quantity} WHERE id = #{skuId} AND stock >= #{quantity},这条 SQL 利用了数据库的行锁,在并发情况下只有一条会执行成功,受影响行数为 0 时说明库存不足,直接抛异常回滚。用 MyBatis-Plus 的话,就是写一个 UpdateWrapper,setSql("stock = stock - " + quantity).last("AND stock >= " + quantity),执行 update 方法后再判断影响条数。
事务还有一个重要配置:@Transactional 默认遇到 RuntimeException 才回滚,如果你在业务逻辑里自己 throw new Exception(受检异常),事务不会回滚。我一开始不知道这点,写了个 try-catch 把库存不扣的 bug 藏了起来,后来直接把自定义异常类继承 RuntimeException,这个问题才彻底解决。这个细节值得写进论文的“系统测试与问题解决”章节。
5. 部署上线:从本地跑通到随身演示
5.1 本地开发环境与启动顺序
部署文档是标题里明确带的交付物,也是真正实用的大件。很多同学本地能跑项目,但换个电脑就不会了,这其实就是没理解“环境依赖”和“启动顺序”。
我整理的部署文档是这样分层的。第一步列环境清单:JDK 1.8 或更高、Maven 3.6+、Node.js 14+、MySQL 5.7 或 8.0。第二步是数据库准备:用 Navicat 执行 SQL 脚本,脚本里包含建库、建表、插入测试数据。第三步是后端启动:IDEA 打开后端工程,等待 Maven 依赖下载完成,修改 application.yml 里的数据库账号密码,运行启动类;看到 “Started Application in xxx seconds” 就说明启动成功。第四步是前端启动:VSCode 打开前端工程,执行 npm install(这一步最慢,要等),再执行 npm run dev,访问 http://localhost:8080 就能看到前台页面。
部署文档里最容易遗漏的部分是测试账号。用户端至少准备一个普通用户(user / 123456),后台准备一个管理员(admin / admin123),方便答辩老师直接演示。另外测试数据尽量丰富一点,手机品牌型号、价格、库存、图片都填全,一个空荡荡的商城演示起来完全没冲击力。
5.2 打包成可交付资料的完整流程
毕业设计最后要提交的是源码包、数据库脚本、论文、部署文档,也就是标题里说的“源码+数据库+论文+部署文档”四件套。打包流程也有说法。
后端打包:IDEA 右侧 Maven 面板执行 package 命令,target 目录下会生成 jar 文件。打包之前先确认 application.yml 里用的是本地 MySQL 还是在线数据库,如果是为了答辩演示,最好本地数据库,避免答辩现场网络不稳。
前端打包:执行 npm run build,会生成一个 dist 目录。把 dist 里的所有文件拷贝到一个任意目录,后面的部署方式有两种。一种是让 SpringBoot 把这个目录放进 static 资源路径,jar 内置前端页面,访问一个端口全搞定,适合只在本机演示的场景;另一种是用 Nginx 托管前端,反向代理转发 API 请求到后端,这是更符合生产环境的方案,部署文档里我会把这个方案作为主要写法,因为“前后端分离部署”本身就是论文的亮点。
数据库脚本的交付要注意一点,SQL 文件不要只导表结构,测试数据必须带进去。建议用 Navicat 的“转储 SQL 文件”功能,包含结构加数据,一劳永逸。
5.3 部署阶段的经典报错与排查思路
部署是最容易出问题的地方,列几个常见错误帮大家提前排雷。
后端启动失败,端口被占用,报错 “Port 8080 was already in use”。用 netstat -ano | findstr 8080 查占用进程,任务管理器结束进程,或者改 application.yml 里的端口。但注意,如果改后端端口,前端 Vite 的代理配置也要同步改。
前端启动失败,npm install 报网络错误。国内网络环境建议先把镜像源切到淘宝镜像(npm config set registry https://registry.npmmirror.com),再执行安装命令。如果 node_modules 已经装坏了,干脆删除重装,等半天也比调试那些半残依赖强。
前端页面能打开但接口 404 或 200 了没有数据。先打开浏览器开发者工具看请求路径对不对,然后看后端的请求日志。最常见的是 Vite 代理没配好,在 vite.config.js 里写 proxy 配置,把 /api 开头的请求转发到 http://localhost:8080;另一种是跨域配置没生效,刷新后端配置重新启动。
数据库连不上,报错 “Access denied for user”。检查三步:账号密码对不对、MySQL 服务有没有启动、application.yml 的 URL 和账号是不是配的新的本地环境。我用 Navicat 先测试连接,能连上就说明后端配置的问题,省去很多无谓的排查时间。
如果时间允许,演示之前一定要自己从零走一遍部署流程,用一台“干净”的电脑模拟答辩现场环境。我认识不少同学,平时在 IDEA 里点运行很溜,一旦现场忘了启动 MySQL,或者前端依赖没装,直接卡在首页,讲再好的 PPT 都补不回来。
6. 论文写作与答辩准备的实操建议
6.1 论文各章节怎么写才不踩空
毕设论文一章一章卡着写的滋味不好受,但如果说项目代码是骨架,那论文就是血和肉。根据这套商城的实际功能,我给你一份可以直接落地的章节框架。
需求分析这章要跳出“用户能登录、能下单”这种话,改用用例图来说明参与者与功能的交互。我从充值系统的用例推过来的思路是:画一个用户用例图(注册、登录、浏览、购物车、下单、查看订单)和管理员用例图(登录、商品管理、分类管理、订单管理、用户管理),再配合功能需求表列每一项的优先级和验收标准。系统设计这章写总体架构图(前后端分离)、功能模块图、技术选型的原因,重点是讲清楚“为什么这样选”,比如为什么用 JWT 而不用 Session,为什么用逻辑删除而不用物理删除。数据库设计这章不用多解释了,放表结构图、字段说明表、E-R 图,我把 9 张表逐表拆解,每张表的字段名、类型、含义、是否空、默认值列成表格,这一章内容量已经很大。
系统实现这章按模块逐个写,每个模块分三块:页面展示截图、核心代码片段、功能流程说明。截图要清晰,关键代码要加注释,核心流程(比如下单、支付)能用文字加步骤描述。系统测试这章写测试用例表,包括测试项、输入数据、预期结果、实际结果、是否通过,再补上几条异常测试(库存不足、登录密码错误、非法 Token 访问),证明你做了基本的功能测试和容错处理。
6.2 演示路线与答辩问答的预案
答辩演示不要按管理员功能页面一个个点,那样太散。我的建议是走一条完整的业务主线:管理员登录后台,新增一个手机商品和对应 SKU,设置为上架状态;前台切换普通用户注册登录,在商品列表里搜索刚才那个手机,进详情页加入购物车,去结算选地址提交订单;回到订单列表看到订单状态是待付款,点击支付进入模拟支付页,确认支付后状态变待发货;切回管理员后台,在订单列表找到这笔新订单,点击发货填物流单号;再切回前台用户视角,确认收货,订单状态变已完成。这条线走完,整个系统的核心功能全部演示到,老师看着也直观。
答辩问答题大概率集中在三个方向。第一类是设计问题:为什么选这个技术栈、表结构为什么这么设计、某个字段为什么冗余、事务怎么保证数据一致性。第二类是扩展问题:如果用户量大了怎么办、怎么对接真实支付、怎么防止脚本刷单。这类问题不用真的实现,讲思路就行,比如“可以用 Redis 做缓存热点商品”“可以对接口做限流”“支付对接第三方平台”,但最好能画出大致的架构方向,别只说“用微服务”。第三类是坑题:让说一下项目里最难解决的一个 bug。这个我有现成的素材,就是下单并发导致库存超卖的问题,虽然最后只是用 SQL 条件更新解决的,但讲清楚排查过程和数据库层面的方案,就能体现你是真做了项目而不是抄的。
6.3 时间规划与工作量评估
最后给想照着做一遍的同学一个时间参考。如果你 SpringBoot 和 Vue 都已经会基本用法,大概是:数据库设计和建表用 2 到 3 天;后端核心模块(用户、商品、购物车、订单、支付)用 5 到 6 天;前端页面开发加联调用 5 到 7 天;写论文用 5 到 7 天;部署文档和整体自测用 2 天。整个周期压在 20 到 25 天左右是合理的。
如果时间只剩十天,砍模块优先级也明确:支付可以直接做成模拟支付,后台统计图表可以不做,收货地址可以简化为用户表单里的一个字符串字段,这些砍法不会影响整体流程演示。
我个人做完这个项目的最大体会是,毕设的真正价值不在于功能有多花哨,而在于你亲手把一个完整的系统从需求分析做到部署交付,中间每一个环节都踩过坑、填过坑。论文里写“采用 Redis 缓存”容易,但真正把 Redis 集成进来并解决缓存与数据库的一致性,才是有含金量的活。等你答辩结束回头再看,这套项目里的每一行代码、每一个表字段、每一段部署命令,都能讲出当初为什么这么做,那这二十多天就没有白熬。