每年到毕业季,总有人问我同一个问题:Java方向的毕设到底选什么题比较稳?我通常都会推荐类似“基于SpringBoot + Vue的贫困山区农产品供销服务系统”这种题目。这个题目表面看业务范围很宽,实际上拆开就是一套标准的前后端分离“供需撮合+电商交易”平台,既能覆盖Spring Boot、Vue、MyBatis这些主流技术,又能把权限控制、订单流转、数据可视化这些亮点串起来,对后面写论文、做答辩、甚至找工作都很有帮助。
这个系统能做什么?一句话讲清楚:把偏远山区的农户、采购商、平台管理员放到同一个系统里,农户发布农产品信息,采购商或消费者在线浏览、下单,管理员负责审核商品、维护数据、看运营统计。它解决的核心痛点是信息不对称——山区的好东西找不到销路,外地的采购商找不到稳定货源,中间环节多、信息不透明。对做毕设的同学来说,它解决的则是“选题怎么定、功能怎么做、论文怎么写、演示怎么录、答辩怎么过”这一整条链路。
下面我就按项目主线把整套东西捋一遍:从需求拆解、技术选型,到数据库设计、核心功能实现,再到前后端联调、打包部署,最后把论文写作、演示视频和答辩高频问题的经验也一并写完,把我实际动手过程中的细节和坑都放进去,方便你直接照着做。
1. 项目设计与技术选型:为什么SpringBoot+Vue是这个题目的最优解
1.1 先理清业务:供销系统到底在解决什么问题
做系统最忌讳一上来就写代码,先把业务闭环想明白,后面所有功能都顺了。这个项目的核心业务是“帮山区的农产品找到买家”,涉及的实际场景有三个:
- 农户/合作社:手上有货,没渠道、没议价能力,需要一个可以展示自己产品的窗口。
- 采购商/消费者:想买产地直供的农产品,但对源头信息不了解,需要一个可信、可追踪的信息平台。
- 平台管理员:负责审核上架的农产品是否真实、价格是否合理,同时通过订单数据和销售统计掌握平台的运营情况。
所以系统功能上就要分成三条线:农户端的产品管理和订单处理,采购端的浏览、下单和支付(一般做模拟支付),管理端的审核、用户管理和数据看板。这正好对应了三类角色、三套菜单、三组接口,也在答辩时形成了一个非常清晰的“三角结构”:需求分析讲业务、系统设计讲模块、系统实现讲代码,每一层都有东西可讲。
1.2 技术选型逻辑:从前端到后端到数据库的通盘考虑
这个项目的技术栈现在基本已经固定成了“标准答案”,我列一下每个选择的理由:
- 后端用SpringBoot:内置Tomcat,省掉大量XML配置,开发效率高。更重要的是,SpringBoot在毕业设计里几乎成了“默认选项”,网上资料多、遇到报错好搜,对时间紧的同学非常友好。
- 前端用Vue + Element UI(或者Element Plus):Vue上手学习曲线比较缓,组件化开发适合做管理后台。配合Element的表单、表格、弹窗组件,可以快速拼出完整的管理界面,这样的前端界面在演示视频里视觉效果好。
- 持久层用MyBatis或MyBatis Plus:直接用SQL控制查询逻辑,调优方便;MyBatis Plus更是连单表CRUD都帮你封装好了,写代码可以集中精力在业务逻辑上。
- 数据库用MySQL:免费、稳定、资料多,配合Navicat或DataGrip建库导数据都方便。
- 鉴权用JWT:无状态、前后端分离友好,比Session更适合配套Vue使用。
这里我想多说一句:为什么不建议继续用JSP + Servlet那种老一套?因为现在答辩老师对技术栈的“新鲜度”是有预期的。前后端分离本身就是论文里的一个独立亮点,可以单独写一节“前后端分离架构的优势”,这也是工作量的一部分。如果你时间充裕,还可以加Redis缓存热点商品数据,但这个不是必须,做不好反而增加风险。
1.3 模块划分与工作量评估
按我的经验,这个题目建议把系统拆成几个模块去开发,方便掌控进度:
| 模块 | 主要功能 | 涉及角色 |
|---|---|---|
| 用户模块 | 注册、登录、个人信息、密码修改 | 农户、采购商、管理员 |
| 商品模块 | 发布商品、商品列表、商品详情、审核上下架 | 农户、管理员、采购商 |
| 交易模块 | 购物车、订单创建、订单支付、发货、确认收货 | 农户、采购商 |
| 供销管理模块 | 供应信息、采购信息、供需匹配 | 农户、采购商、管理员 |
| 数据看板模块 | 销售统计、订单趋势、商品分类占比 | 管理员 |
| 公告模块 | 平台公告发布与查看 | 管理员、所有用户 |
你拿着这个表去估算时间:用户模块和公告模块基本是模板代码,商品模块是核心工作量,交易模块是最需要细心的地方,数据看板模块主要是接口和图表配置。这样拆完,你就知道哪些地方可以快、哪些地方必须慢。
2. 核心功能模块拆解:从商品发布到订单完成的完整链路
2.1 用户角色与权限设计
权限设计是这个题目里必写、必讲、也必考的点。我自己习惯的做法是在用户表里用一个role字段区分角色,登录接口返回用户的角色信息,前端根据角色渲染不同的菜单,后端接口再用拦截器或Spring Security做校验。
| 功能/角色 | 农户 | 采购商 | 管理员 |
|---|---|---|---|
| 注册登录 | 支持 | 支持 | 不支持注册,内置账号 |
| 商品发布 | 支持 | 不支持 | 不支持 |
| 商品审核 | 不支持 | 不支持 | 支持 |
| 下单购买 | 不支持 | 支持 | 支持(模拟) |
| 订单发货 | 支持 | 不支持 | 不支持 |
| 数据看板 | 查看自己 | 查看自己 | 查看全平台 |
| 用户管理 | 不支持 | 不支持 | 支持 |
权限这块有个细节很容易忽略:即使前端隐藏了菜单,后端接口也必须做权限校验。你可以用一个简单的注解,也可以用拦截器判断请求路径和角色。我在项目里给每个接口都挂了@RequireRole("ADMIN")这类注解,或者在Controller层统一用拦截器按路径匹配。这样做不是为了炫技,而是答辩时如果老师问“前端限制有什么用?别人直接调接口怎么办”,你能答得出来,这就是区分度。
2.2 商品发布与审核机制
商品模块是用户看得见摸得着的核心功能。农户端“发布商品”的表单至少需要以下字段:商品名称、商品分类、单价、单位(斤/箱/件)、库存数量、产地、图片、描述。其中图片上传往往是最容易出问题的地方,我后面会专门讲。
这里我想强调一个很多人忽略的设计点:商品一定要有“审核状态”。不要一发布就上架,而是先进入“待审核”状态,管理员审核通过后才在前台展示。为什么?一方面是从平台运营角度,需要防止虚假信息;另一方面是给系统增加一个完整的状态机,论文里的“系统设计”章节就有了丰富内容——待审核、上架、驳回、下架、售罄这些状态可以画一张状态图,答辩时能讲的东西立刻多了一倍。
商品列表查询还需要支持关键词搜索、分类筛选、价格排序。前台用分页加载数据,后端用MyBatis Plus的Page对象或者手写SQL都行。做这块的时候建议把查询条件封装成一个查询对象,不要直接在Controller里接收一堆零散参数,后面维护起来会舒服很多。
2.3 订单交易与库存联动
交易模块是整个系统的核心难点,也是答辩老师比较喜欢追问的地方。我推荐的流程是:采购商把商品加入购物车 → 购物车结算生成订单 → 模拟支付 → 农户发货 → 采购商确认收货 → 订单完成。这里面的关键设计有两个:
第一个是订单状态流转。我常用tinyint类型存状态码:0待付款、1待发货、2待收货、3已完成、4已取消。每个状态之间的流转必须在代码里做校验,比如只有“待付款”状态才能调到“已取消”,“待发货”才能调到“待收货”,不能让用户随便跨状态跳。
第二个是库存扣减。我建议在用户提交订单的那一刻就锁定库存,而不是等到支付成功才扣。代码上就是把“创建订单”和“扣减库存”放在同一个事务里,只要有一个环节失败就全部回滚。这一点非常重要,你可以写进论文的“系统实现”里,答辩时直接讲“我用@Transactional保证数据一致性”,老师一听就知道你不是只抄了代码。
2.4 数据看板:让系统有“智慧”的亮点模块
数据看板是这个项目性价比很高的一块,因为用ECharts就能实现,但视觉冲击力很强,演示视频里加分比较多。管理员看板可以放这些图:近7天订单量折线图、商品分类销售占比饼图、各产地销量柱状图、待处理事项列表。农户看板则聚焦自己的商品发布量、订单量、累计销售额。
后端只需要提供几个统计接口,比如按日期分组统计订单数,按商品分类统计销量,前端用ECharts渲染成图形。写SQL的时候注意用GROUP BY配合DATE_FORMAT处理日期分组,按月份统计就DATE_FORMAT(create_time, '%Y-%m'),按天统计就是'%Y-%m-%d'。这个模块不算难,但能直接提升项目的完整度和演示效果。
3. 数据库设计:核心表结构与字段规划实战
3.1 数据表全景与关联关系
数据库表设计决定整个项目的“底子”。我强烈建议先画E-R图再建表,把实体、属性、关系都理清楚,后面写论文直接截图用。这个项目至少需要这几张核心表:
| 表名 | 用途 | 关键外键 |
|---|---|---|
| user | 用户表 | 无 |
| category | 商品分类表 | 无 |
| product | 商品表 | farmer_id → user.id,category_id → category.id |
| cart | 购物车表 | user_id → user.id,product_id → product.id |
| orders | 订单表 | buyer_id → user.id,seller_id → user.id |
| order_item | 订单明细表 | order_id → orders.id,product_id → product.id |
| notice | 公告表 | 无 |
| address | 收货地址表 | user_id → user.id |
关联关系就是典型的“用户-商品-订单”三件套:一个农户可以发布多个商品,一个商品属于一个分类;一个订单属于一个采购商,包含多个订单明细;一个订单明细对应一个商品。这些关系在论文的系统设计部分用E-R图表示,一张图就能讲完整个核心逻辑。
3.2 核心表字段设计:user、product、orders、order_item
我直接把我常用的建表SQL写出来,你根据实际情况改字段名即可。用户表:
CREATE TABLE `user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `username` varchar(50) NOT NULL COMMENT '登录账号', `password` varchar(100) NOT NULL COMMENT '密码(加密存储)', `nickname` varchar(50) DEFAULT NULL COMMENT '昵称', `role` varchar(20) NOT NULL DEFAULT 'BUYER' COMMENT '角色:FARMER/BUYER/ADMIN', `phone` varchar(20) DEFAULT NULL COMMENT '手机号', `avatar` varchar(255) DEFAULT NULL COMMENT '头像地址', `status` tinyint(4) NOT NULL DEFAULT 1 COMMENT '状态:1正常 0禁用', `create_time` datetime DEFAULT CURRENT_TIMESTAMP, `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_username` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';商品表:
CREATE TABLE `product` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `farmer_id` bigint(20) NOT NULL COMMENT '农户用户ID', `category_id` bigint(20) DEFAULT NULL COMMENT '分类ID', `name` varchar(100) NOT NULL COMMENT '商品名称', `price` decimal(10,2) NOT NULL COMMENT '单价', `stock` int(11) NOT NULL DEFAULT 0 COMMENT '库存', `unit` varchar(20) DEFAULT '斤' COMMENT '单位', `origin` varchar(100) DEFAULT NULL COMMENT '产地', `image` varchar(255) DEFAULT NULL COMMENT '商品图片地址', `description` text COMMENT '商品描述', `status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '状态:0待审核 1已上架 2已驳回 3已下架', `create_time` datetime DEFAULT CURRENT_TIMESTAMP, `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_farmer_id` (`farmer_id`), KEY `idx_category_id` (`category_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品表';订单表和订单明细表:
CREATE TABLE `orders` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `order_no` varchar(32) NOT NULL COMMENT '订单编号(业务唯一)', `buyer_id` bigint(20) NOT NULL COMMENT '采购商ID', `seller_id` bigint(20) NOT NULL COMMENT '农户ID', `total_amount` decimal(10,2) NOT NULL COMMENT '订单总额', `status` tinyint(4) NOT NULL DEFAULT 0 COMMENT '状态:0待付款 1待发货 2待收货 3已完成 4已取消', `remark` varchar(255) DEFAULT NULL COMMENT '订单备注', `pay_time` datetime DEFAULT NULL COMMENT '支付时间', `ship_time` datetime DEFAULT NULL COMMENT '发货时间', `finish_time` datetime DEFAULT NULL COMMENT '完成时间', `create_time` datetime DEFAULT CURRENT_TIMESTAMP, `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `uk_order_no` (`order_no`), KEY `idx_buyer_id` (`buyer_id`), KEY `idx_seller_id` (`seller_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表'; CREATE TABLE `order_item` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `order_id` bigint(20) NOT NULL COMMENT '订单ID', `product_id` bigint(20) NOT NULL COMMENT '商品ID', `product_name` varchar(100) NOT NULL COMMENT '商品名称快照', `product_image` varchar(255) DEFAULT NULL COMMENT '商品图片快照', `price` decimal(10,2) NOT NULL COMMENT '成交单价', `quantity` int(11) NOT NULL COMMENT '购买数量', `amount` decimal(10,2) NOT NULL COMMENT '小计金额', PRIMARY KEY (`id`), KEY `idx_order_id` (`order_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单明细表';这里有三个设计细节我特别说一下:
- 订单表里一定要有
order_no唯一业务编号,不要直接用自增主键去和用户沟通。生成方式可以是时间戳+随机数,或者“日期+自增序列”,论文里可以说“采用业务单号保证可追溯性”。 - 金额字段必须用
decimal(10,2),不要用float或double,浮点数会产生精度误差,这是做电商系统的基本功。 order_item里的product_name、product_image、price是“快照字段”。商品名称和价格以后可能会改,但订单历史记录必须保留下单那一刻的信息,这也是答辩时可以主动讲出来的亮点。
3.3 建表SQL与存储引擎规范
上面建表SQL我统一用了InnoDB和utf8mb4,这俩是必选项。utf8mb4支持完整Unicode字符,能存emoji和生僻字;InnoDB支持事务和外键约束,订单操作跨表时必须依赖事务。另外养成习惯:所有表都有create_time和update_time,查问题、写论文、做数据统计都用得上,这个习惯我建议你从一开始就建立起来。
4. 关键功能实现与前后端联调:从登录到下单的代码实战
4.1 登录鉴权:JWT + 拦截器 + 路由守卫
登录是整个系统第一个要写的功能,也是最容易在答辩时被追问“安全性怎么保证”的地方。我用JWT的实现思路如下:用户提交账号密码 → 后端校验通过 → 生成Token返回前端 → 前端把Token存在localStorage → 每次请求在请求头带上Authorization: Bearer <token>→ 后端拦截器校验Token。
后端先生成Token:
public class JwtUtils { private static final String SECRET = "your-secret-key"; private static final long EXPIRE = 7 * 24 * 60 * 60 * 1000L; public static String generateToken(Long userId, String role) { return Jwts.builder() .setSubject(String.valueOf(userId)) .claim("role", role) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() + EXPIRE)) .signWith(SignatureAlgorithm.HS256, SECRET) .compact(); } public static Claims parseToken(String token) { return Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody(); } }再写一个拦截器统一校验除登录、注册之外的接口。前端的配合也很重要:axios请求拦截器加Token,响应拦截器遇到401状态码就跳回登录页。我在做前端路由守卫时习惯在router.beforeEach里判断目标页面是否需要登录,需要但没有Token就直接跳转登录页,这样刷新页面也不会丢失登录状态。
这一步属于“看起来简单但细节多”的环节。你写完这套之后,论文的“系统安全设计”章节就有东西可以写了——Token过期时间、密码加密存储(BCrypt)、接口权限校验,都是安全性的具体体现。
4.2 商品图片上传与静态资源映射
图片上传是这个项目里比较容易踩坑的地方。最稳妥的方案是把图片保存到服务器本地的一个外部目录,然后通过Spring Boot的静态资源映射把该目录暴露成URL访问。我常用的配置如下:
spring: servlet: multipart: max-file-size: 5MB max-request-size: 20MB web: resources: static-locations: file:D:/upload/,classpath:/static/上传代码用MultipartFile接收文件,文件名用UUID重新生成,防止重名覆盖:
String originalName = file.getOriginalFilename(); String ext = originalName.substring(originalName.lastIndexOf(".")); String fileName = UUID.randomUUID().toString().replace("-", "") + ext; file.transferTo(new File(uploadDir, fileName));这里有个教训分享给你:不要直接把图片传到项目的src/main/resources/static下面。毕设项目经常要重新打包,而mvn clean package会把resources目录清掉再重新生成,你传的图片就全没了。把文件放在项目外的目录,再通过静态资源映射访问,一条路径就能同时解决“文件被清”“URL访问”两个问题。另外上传接口注意限制文件类型和大小,答辩时老师对这块的严谨度有预期。
4.3 下单扣库存:事务与状态流转的核心代码
订单创建是整个系统复杂度最高的地方,核心逻辑分四步:查商品 → 校验库存 → 扣库存 → 生成订单。这段代码必须加事务,我用@Transactional实现:
@Transactional(rollbackFor = Exception.class) public OrderVO createOrder(OrderCreateDTO dto) { // 1. 查询商品,判断状态是否上架 Product product = productMapper.selectById(dto.getProductId()); if (product == null || product.getStatus() != 1) { throw new BusinessException("商品不可购买"); } // 2. 判断库存是否充足 if (product.getStock() < dto.getQuantity()) { throw new BusinessException("库存不足"); } // 3. 扣减库存(乐观锁或直接update) int rows = productMapper.deductStock(dto.getProductId(), dto.getQuantity()); if (rows == 0) { throw new BusinessException("库存扣减失败"); } // 4. 生成订单号和订单明细 Order order = new Order(); order.setOrderNo(generateOrderNo()); order.setBuyerId(dto.getBuyerId()); order.setSellerId(product.getFarmerId()); order.setTotalAmount(product.getPrice().multiply(new BigDecimal(dto.getQuantity()))); order.setStatus(0); orderMapper.insert(order); // 后续插入order_item,省略 return orderVO; }这里我特别说一下扣库存的写法:不要先select出来在内存里减,再update回去,那样并发时会出问题。正确做法是写一条带条件的UPDATE语句:UPDATE product SET stock = stock - #{quantity} WHERE id = #{id} AND stock >= #{quantity},受影响行数为0说明库存不够,直接抛异常。这个写法在答辩时讲出来非常加分,因为它体现了对并发场景的基本认知。
订单状态的流转方法按顺序写好:用户支付、农户发货、采购商确认收货。每个方法先查订单状态,再判断能不能进行下一步操作,不符合规则就抛异常。这套逻辑不复杂,但要把每个状态的前置条件写清楚。
4.4 跨域配置与接口联调避坑
前端工程默认跑在8081端口,后端跑在8080,不同端口就产生了跨域问题。解决方式是在后端加一个全局跨域配置:
@Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOriginPatterns("*") .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*") .allowCredentials(true) .maxAge(3600); } }联调时最常见的问题有三类:后端接口地址写错、请求方式不对(POST写成了GET)、参数名对不上。我的建议是先用Swagger或在线接口文档工具把后端接口全部列出来,再对照着写前端请求。如果前端报404,先看后端控制台有没有收到请求;如果报400,十有八九是参数类型或字段名不匹配,比如后端用orderNo,前端传order_no。排查顺序对了,问题解决速度就上去了。
5. 毕设四件套:论文(LW)、演示视频、部署与打包全流程
5.1 论文框架与图表画法
标题里提到的LW我理解就是毕业论文/设计文档。很多同学代码跑通了,论文却不知道怎么凑字数。按我的经验,这个项目的论文按这个框架写最省力:
| 章节 | 写什么 | 工作量参考 |
|---|---|---|
| 摘要 | 系统背景、技术栈、核心功能、意义 | 300~500字 |
| 绪论/背景 | 山区农产品销售现状、系统开发意义、国内外类似平台分析 | 800~1000字 |
| 需求分析 | 角色分析、功能性需求、非功能性需求、可行性分析 | 1000~1500字 |
| 系统设计 | 架构图、功能模块图、E-R图、数据库表结构、接口设计 | 1500~2000字 |
| 系统实现 | 每个模块截图 + 核心代码 + 实现说明 | 2000~2500字 |
| 系统测试 | 功能测试用例表、测试结论 | 500~800字 |
| 总结展望 | 项目收获、不足、改进方向 | 300~500字 |
论文里图表是“工作量可视化”的关键。你需要准备这几类图:系统架构图(前端Vue → 后端Controller → Service → Mapper → MySQL)、功能模块图、用户用例图、数据库E-R图、订单状态流转图、核心功能时序图。不需要画得多专业,用画图工具或在线绘图工具画清楚就行,重点是图和代码、表结构能对上。每年答辩现场被老师抓出“图和实现不一致”的案例挺多的,一定要自查。
5.2 演示视频录制要点
演示视频的目的不是展示所有功能,而是让看视频的人快速了解“这个系统是完整的、能跑的”。我建议按角色脚本录制:先管理员登录,审核一条商品;再农户登录,发布商品、处理订单;最后采购商登录,搜索商品、加入购物车、下单、确认收货。整个过程控制在8到12分钟,按模块分段录,方便后期剪辑。
录屏的几个小技巧:提前把要演示的数据准备好(商品图片、用户账号、测试数据);屏幕分辨率调成横向比较舒服的尺寸;旁白讲“我在做什么”而不是“我在点什么”;出现弹窗报错时不要慌,直接说明这个异常是演示数据导致的。我自己录过很多次项目视频,最深的体会是“演示路径要提前走两遍”,第一遍按正常流程走,第二遍检查有没有点错、有没有数据没准备好。
5.3 本地部署与打包发布:从开发环境到效果展示
部署说明要写得让导师或者评审老师照着能做出来。按步骤写就清楚了:
- 安装JDK 1.8+、MySQL 5.7+、Node.js 14+、Maven 3.6+。
- 在MySQL中新建数据库,导入项目提供的
farm_supply.sql脚本。 - 修改后端
application.yml中的数据库账号密码、文件上传目录。 - 在项目根目录执行
mvn clean package,打出来的jar包放到一个目录,执行java -jar xxx.jar启动后端。 - 前端在源码目录执行
npm install安装依赖,然后npm run build打包出dist目录;本地调试就直接npm run serve。 - 访问前端地址,默认管理员账号登录,完成功能验证。
我的习惯是把后端默认端口设为8080,前端开发服务器设为8081,并在Vue的vue.config.js里配置代理,把/api开头的请求转发到后端。这样前端代码里直接写相对路径,等上线时再让后端把dist目录放到static下,或者用Nginx做反向代理,整个过程比较平滑。部署完记得把后端启动日志里明显报错的部分清理掉再截图,演示效果会好很多。
6. 常见问题排查与答辩准备:踩坑实录和高频问答
6.1 环境与部署问题排查
这个项目的运行环境问题基本集中在这几个地方,我整理了一份排查表,对应现象和解决办法都列出来:
| 问题现象 | 常见原因 | 解决办法 |
|---|---|---|
| 启动报端口占用 | 后端口被其他程序占用 | netstat -ano查占用进程,换端口或结束进程 |
| 数据库连接失败 | 账号密码错误、数据库没建、时区问题 | 检查application.yml;连接串加serverTimezone=Asia/Shanghai |
| Maven依赖下载超时 | 默认源慢 | 换成阿里云镜像仓库,重新mvn clean install |
| 前端依赖安装失败 | Node版本过高或网络问题 | 用Node 14/16版本,删除node_modules后重装 |
| 图片无法访问 | 上传目录不对、静态资源映射没生效 | 确认目录存在,检查映射配置 |
这里提醒一下:时区问题特别常见,MySQL 8.0默认时区是UTC,不改的话插入时间会差8小时。连接串里带上serverTimezone=Asia/Shanghai,一次解决。
6.2 前后端联调问题排查
联调阶段最考验耐心。我的排查思路是:先看前端Network面板,请求有没有发出、返回什么状态码;再看后端控制台日志,异常有没有打印;最后检查两端字段名和类型是否一致。如果接口报401,大概率是Token没带上或已过期,先清浏览器缓存重新登录;如果报404,先确认后端接口路径和前端请求路径完全一致;如果数据能返回但前端不显示,多半是字段名对不上(createTime和create_time)。
把前后端联调通之后,建议把关键接口的请求和响应各截图几张,后面论文的“系统实现”章节直接能用,演示视频里也可以放一两个接口调试画面,显得项目真实、有深度。
6.3 答辩高频问题与应对思路
答辩环节是整个毕设的临门一脚。我根据这个题目总结几个出现频率比较高的提问,以及对应的回答思路:
| 老师可能会问 | 思路和准备方向 |
|---|---|
| 为什么选择这个课题? | 从山区农产品信息不对称的实际痛点切入,说明系统有真实应用价值 |
| 前后端分离的好处? | 开发效率、并行开发、职责分离、接口复用 |
| 登录安全怎么做的? | 用户密码BCrypt加密存储、JWT设置有效期、后端拦截器统一校验、管理端接口单独限制角色 |
| 订单和库存的一致性怎么保证? | 创建订单和扣减库存放在同一事务中;扣库存使用stock >= quantity条件更新保证并发安全 |
| 核心表有哪些,关系是什么? | 用户-商品-订单-订单明细,讲清晰一对多关系,强调订单明细里的快照字段 |
| 系统测试做了哪些? | 功能测试用例表、角色操作流程测试、兼容性和异常场景说明 |
| 如果用户投诉商品质量怎么办? | 可以扩展售后流程、用户评价体系、原因说明,体现你对系统演进有思考 |
我建议你在答辩前自己照着这些问题过两遍,重点不是背答案,而是真正理解每一行代码背后的逻辑。老师喜欢问“为什么这样设计”,而不是“这段代码怎么写的”,所以你在做项目时每做一个决定,都要问自己一句“为什么”,这本身就是最好的答辩准备。
最后再分享一个个人经验:我在经手很多个毕设项目后发现,源码能不能跑通只是起点,真正拉开差距的是“你能不能把这个系统讲清楚”。像库存一致性、订单状态机、审核流程、Token过期策略,这些点你只要自己亲手敲过一遍、调过一遍,答辩被问到的时候根本不用背,顺口就能说清楚。项目做完之后,我建议你再花半天时间把表结构、接口清单、核心业务流程整理成一页纸,答辩前对着这页纸过两遍,基本就稳了。后面如果想继续扩展,App端适配、对接真实支付、接入物流查询这些都还有很大的空间,但核心链路打通了,扩展就都是加分项。