1. 苗木交易互助网站:这个毕设选题到底在做什么
每年到毕设季,Java方向的学生扎堆做电商系统,餐厅点餐、二手交易、服装商城这类题已经被做烂了。苗木交易互助网站这个题能拿出来说,是因为它把"电商交易"和"社区互助"拧在了一起,既不是纯粹的商城,也不是单纯的论坛,而是两条业务线并行——苗农可以开店卖苗木,买家可以按品种、规格筛选下单,同时网站提供求购信息发布、种植经验交流的互助板块。这个组合在毕业设计里很有优势:功能覆盖面够宽,涉及的技术点足够撑起一篇完整的论文,而且业务逻辑比普通商城多了一层社区属性,答辩时不容易被问倒。
先把这个系统的核心角色说清楚。整个平台包含三类用户:苗木采购商(个人买家或工程采购方)、苗农/供应商(发布商品、处理订单)、平台管理员(审核商品、管理用户、处理举报)。围绕这三类角色,系统要解决的核心问题是:苗木作为一种非标品(同品种不同规格价格差异巨大,而且必须看实物图判断品相),如何让买卖双方高效撮合,同时通过互助社区沉淀种植技术、求购信息,降低交易决策成本。
实际操作中,这个项目的业务功能可以拆成四条线:
- 商品交易线:苗木商品发布、多规格管理(高度、米径、冠幅)、购物车、订单生成、订单状态流转、收货评价
- 互助社区线:发帖提问、回复交流、求购信息发布、收藏点赞
- 用户与权限线:注册登录、个人中心、地址管理、供应商入驻申请、管理员后台
- 运营支撑线:商品分类管理、公告发布、数据统计(交易量、活跃用户等)
我见过不少学生做这个题,最后都做成了"换皮商城"——把商品图换成树苗,其他逻辑和普通电商一模一样,互助模块就是一个没人看的留言板。这种做法答辩时很吃亏,因为评委一看就知道你没有真正理解这个业务场景。苗木交易里最核心的痛点是规格沟通成本和信任建立,做这个系统时不把这两点落实到功能设计里,项目就只是一个CRUD堆砌的壳子。
2. 技术选型:SpringBoot + MyBatis-Plus + Vue 3这套组合的底气和陷阱
选型是每个做毕设的人第一道坎。Java方向首选SpringBoot是共识,但"SpringBoot版本太高"这个坑几乎每年都有人踩——选了当前最新的3.2.x,结果发现很多老教程里的代码跑不通,因为Spring Boot 3.0开始强制要求Java 17,javax包名全部换成了jakarta,一些第三方组件的兼容性也没跟上。
我给你的建议是:做毕设老老实实选SpringBoot 2.7.x + JDK 8/11,理由有三点。第一,网上能找到的资料和现成代码绝大部分基于这个版本,遇到问题搜得到答案;第二,它和MyBatis-Plus、MySQL 5.7/8.0的配合已经非常稳定;第三,答辩时老师更关心你的业务逻辑和设计思路,而不是你用了多新的框架版本。如果你的学校规定必须用较新的版本,那就直接上SpringBoot 3.2.x + JDK 17,但所有依赖都要选兼容版本,比如MyBatis-Plus要用3.5.5以上,Knife4j接口文档要用4.x版本。
完整的后端技术栈清单大概是这样的:
| 技术 | 选型 | 作用 |
|---|---|---|
| 核心框架 | SpringBoot 2.7.14 | 项目骨架与自动装配 |
| ORM框架 | MyBatis-Plus 3.5.3 | 单表CRUD免写SQL,分页插件 |
| 数据库 | MySQL 8.0 | 数据持久化 |
| 权限认证 | Sa-Token 或 JWT + 拦截器 | 登录态管理与接口鉴权 |
| 接口文档 | Knife4j 4.x | 生成Swagger文档,方便自测 |
| 文件存储 | 本地磁盘存储(或阿里云OSS) | 商品图、帖子图上传 |
| 前端 | Vue 3 + Element Plus | 后台管理页面与前端构建 |
| 构建工具 | Maven | 依赖管理与打包 |
这里有一个很重要的思路:MyBatis-Plus可以在项目启动时根据Java实体类自动生成建表SQL,这是热词列表里提到的"根据实体类生成创表SQL"。它的底层原理是实体类上的注解(@TableName、@TableId、@TableField)携带了表名、主键策略、字段映射信息,MyBatis-Plus内置的自动建表能力会解析这些元数据,拼装出CREATE TABLE语句并在应用启动时执行。常见的做法有两种:一是配置文件开启相关能力,框架自动检测实体并建表;二是在项目里通过自定义初始化逻辑调用相关API生成SQL文件。对毕设来说,我更推荐把建表SQL手写保存成sql/init.sql,一方面方便答辩时展示数据库设计,另一方面也避免自动建表在字段类型映射上某些细节不可控(比如decimal精度、text类型长度、索引建立等)。
前端这块,Vue 3生态已经相当成熟,Element Plus组件库套一个后台管理界面是效率最高的方式。我建议前端用Vite作为开发构建工具,因为它的热更新速度比Webpack快非常多,改一行代码浏览器刷新几乎无感,对调试体验的提升是巨大的。Vite 4 + Vue 3 + Element Plus这套组合,网上模板很多,你不需要从零搭,拿一套现成的后台管理模板改就行——但我强调一句,不要只拿模板改改就直接用,你必须能讲清楚每个页面的数据流走向,这是答辩的加分项。
3. 数据库设计:苗木SKU和订单状态机是核心中的核心
数据库设计是毕设评审的重点,也是拉开差距的地方。苗木商品和普通电商商品最大的不同在于同一品种有多套规格维度,买一棵桂花树,得区分地径、高度、蓬径、土球大小,而且不同植物的规格维度还不一样——乔木看胸径/米径,灌木看冠幅、高度,草坪按平方计价。设计时不能用一个固定的"规格"字段应付,应该专门建一张product_spec规格表。
我按实际开发经验给你整理一份核心表清单:
用户相关
member:用户表(用户ID、手机号、密码、昵称、角色类型、头像、状态)supplier_info:供应商信息表(审核状态、营业执照号、苗圃地址、简介)member_address:收货地址表(收货人、电话、省市区、详细地址、默认标记)
商品相关
product_category:苗木分类表(乔木、灌木、草本、藤本、盆景等,支持多级分类)product:商品主表(SKU公共信息:标题、主图、详细描述、上架状态、审核状态)product_spec:规格表(品种规格维度:米径、高度、冠幅、土球直径、价格、库存)
交易相关
cart:购物车表(用户ID、商品ID、规格ID、数量)order:订单主表(订单号、用户ID、供应商ID、总金额、状态、收货信息快照)order_item:订单明细表(商品快照:标题、规格、单价、数量、图片)refund_record:退款记录表(原因、金额、处理结果)evaluation:评价表(评分、内容、图片、回复)
社区相关
post:帖子表(标题、正文、图片、浏览数、点赞数、发布者ID)post_reply:回复表(楼层、内容、回复对象、点赞数)purchase_demand:求购信息表(求购品种、预算、数量、联系人、截止时间)message:站内私信表(发送者、接收者、内容、已读标记)
运营相关
notice:公告表(标题、内容、发布时间、状态)admin_log:操作日志表(管理员ID、操作类型、操作详情、IP、时间)
两张表重点说一下。order订单表里一定要有一个订单状态字段,而且状态流转要设计严谨。我推荐用整型状态码,0待付款、1待发货、2待收货、3已完成、4已取消、5退款中、6退款完成。每个状态之间的流转必须通过Service层的具体方法控制,不能允许前端任意拼请求修改状态——这是答辩时老师最爱问的"业务闭环"问题。比如只有订单状态为1(待发货)时才允许供应商发货,一旦状态变为2(待收货),系统需要自动往用户手机号发一条通知(哪怕是模拟的)。
product_spec表则是苗木交易友好性的关键。开发和答辩时怎么体现"对业务有思考"?就是这张表。每次下单时商品详情页会列出该品种所有可选的规格(比如桂花:米径5cm/8cm/10cm),每个规格有独立的库存和价格,用户选择规格后加入购物车,订单明细记录的是规格快照而不是简单的商品ID。这样设计的好处是订单生成后即使供应商改了价格或删了规格,历史订单依然能完整还原。
关于自动生成SQL这个话题我再补充一个实际场景。MyBatis-Plus的"根据实体类生成建表SQL"方案,本质上是通过TableInfoHelper读取实体类元数据,把Java类型映射为MySQL类型。但这种映射有几个容易出问题的地方:Java的String默认映射为VARCHAR(255),存长文本必须显式加@TableField(typeHandler = ...)或用Longtext类型的字段在实体里标注;BigDecimal映射没问题,但如果要做decimal(10,2)的精度控制,有些版本映射出来是decimal(10,2)精确,有些是decimal(19,2)带太多位,虽然不影响功能但答辩时抠细节容易露怯。我的建议永远是:实体类注解用来配合MyBatis-Plus做ORM,而建表SQL手写并放在项目sql目录下,给导师看数据库设计文档时也更正规。如果你确实想体验自动建表能力,可以做一个"初始化模式":当配置项custom.init-db=true时,自动执行sql/schema.sql初始化脚本,再配合DataInitializer写入演示数据。这样既保证了可控性,又能在答辩时展示"项目内置自动初始化能力"这个亮点。
数据库设计的向下兼容还有个细节:所有表都要带create_time、update_time字段,MyBatis-Plus的FieldFill.INSERT和FieldFill.INSERT_UPDATE注解可以自动填充,这个属于基本功了,不赘述。重点提醒一下索引:order表的supplier_id、member_id和order_no(唯一索引),product表的category_id和supplier_id,post表的member_id,这五个索引务必加上。数据量小的时候感觉不到差距,答辩演示时一旦有人往数据库里灌了几万条测试数据,有没有索引的查询性能差异会直观呈现。
4. 商城交易链路实现:从商品上架到订单确认的完整思路
这一段是整个系统的核心,我把从供应商上架商品到买家最终收货的完整链路拆开讲,每一环都对应明确的数据库操作和状态变更。
4.1 商品上架与规格管理
供应商登录后台后进入"苗木管理",点击新增商品,需要填写的信息包括:商品标题、分类(从后台管理配置的多级分类里选)、封面图(支持本地上传,服务器存到指定目录并返回访问URL)、详情描述(可用富文本编辑)、以及一组规格项(规格名称如"米径"、规格值如"5cm"、单价、库存、是否默认规格)。
这里有个交互细节,前端做规格录入时应该是动态添加行的,而不是固定几个输入框。Vue 3里可以用v-for渲染规格列表,每次点击"添加规格"就往数组push一个空对象,删除就splice。提交时把规格列表作为JSON数组传给后端,后端在createProduct方法里用@Transactional同时插入product表和product_spec表——这里一定记得加事务注解,否则出现商品主信息有了但规格没插入的数据脏状态,排查起来非常闹心。
提示:图片上传这块建议用本地存储方案,在application.yml里配置
file.upload-path,上传接口接收MultipartFile后生成UUID文件名,保存后返回/images/xxx.jpg这样的访问路径。如果你是前后端分离部署,记得配一个静态资源映射,把/images/**映射到磁盘目录,否则图片加载不出来。
4.2 购物车与下单操作
购物车的标准实现就是一张cart表,字段是用户ID、商品ID、规格ID、数量。这里有一个我自己当初踩过的坑:同一用户、同一商品、同一规格重复加入购物车,应该合并数量而不是新增两行。所以在addCart方法里要先查一下是否已有对应记录,存在就执行UPDATE SET quantity = quantity + #{num},不存在才执行INSERT。
从购物车生成订单是整个系统里最容易出并发问题的地方。假设两个买家同时在抢同一个供应商最后一批某种规格的苗木,如果不加库存保护,两个订单都可能扣减成功,结果发货时发现库存不够,这就是典型的超卖问题。毕设项目虽然不需要做到秒杀级别的并发处理,但思路必须对。最朴素的方案是乐观锁——在product_spec表里加一个version字段,扣库存时执行:
UPDATE product_spec SET stock = stock - #{num}, version = version + 1 WHERE spec_id = #{specId} AND stock >= #{num} AND version = #{version}如果这个UPDATE影响行数为0,说明库存不足或版本冲突,下单失败并提示"苗木规格库存已更新,请刷新后重试"。这种写法在MySQL单机上已经足够应付毕设演示,而且答辩时你可以很自信地说"考虑了并发安全,用乐观锁避免了超卖问题"。
下单的核心流程我写成伪代码,这个逻辑是论文里"核心功能设计"章节的素材:
@Transactional(rollbackFor = Exception.class) public OrderVO createOrder(OrderDTO dto) { // 1. 从dto中获取选中的购物车项列表(前端传cartId集合) // 2. 遍历购物车项,查询商品与规格,校验上下架状态 // 3. 计算总金额(注意用规格表中的实时价格,不信任前端传入价) // 4. 调用乐观锁扣减库存(每个明细项分别扣减) // 5. 生成订单主记录(订单号用时间戳+用户ID+随机数,状态=0待付款) // 6. 插入订单明细记录(冗余商品名称、图片、规格描述、单价快照) // 7. 删除对应购物车记录 // 8. 返回订单VO(内含订单号和待支付金额) }4.3 模拟支付与订单状态流转
毕设不需要对接真实支付,做一个"模拟支付"页面即可:用户在订单详情页点击"确认支付",弹窗显示支付金额,点击确定后后端把订单状态从0改为1(待发货)。之所以单独做这一步,是为了让整个交易链路在答辩演示时看起来更完整,也方便你讲状态机设计。
供应商端的订单管理页面按状态分Tab展示(待发货、待收货、已完成等),点击"发货"时弹窗填写物流公司和运单号,后端更新订单状态为2(待收货)并在order表冗余一个shipping_time字段。买家端看到订单变为"待收货"后,点击"确认收货"(也可以做倒计时自动确认),状态变为3(已完成),此时允许发起评价。整个状态流转里,改状态的所有入口都必须校验当前状态是否合法,比如状态已经是3(已完成)的订单就不能再调发货接口,否则逻辑上就穿帮了。
订单号生成也是一个经常被问到的细节。不要用数据库自增ID当订单号展示给用户,会直接暴露平台日单量。我用的方式:时间戳(14位)+ 用户ID后四位 + 三位随机数,组成类似202503201012345678123的21位订单号,代码实现是:
String orderNo = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + String.format("%04d", userId % 10000) + String.format("%03d", new Random().nextInt(1000));这个方案虽然简单,但答辩时有理有据——"唯一性通过时间戳+随机数保证,安全性通过不暴露自增ID实现",老师会觉得你想过这个问题。
4.4 评价闭环
订单完成后,买家可以对这个订单里的商品逐项评价,评分1-5星,可以传图片。评价写入evaluation表,同时更新product表里的综合评分(avg_score字段)和评价次数。商品详情页展示评分星星和评价列表——这个闭环一定要做完整,因为它是"互助与信任"主题的支撑点。苗木交易中最值钱的就是口碑,一个供应商评分高、买家秀多,其他用户才会信任他的苗圃。做完评价系统后,你可以再补一个逻辑:评价列表按"有图优先、评分从低到高优先"排序,低分评价置顶展示,这种设计在答辩时说出来也是加分项——"让差评前置,反而能筛选出真正靠谱的供应商"。
5. 互助社区模块:发帖、回复、求购信息的功能落地
互助社区是这个项目区别于普通电商的差异化卖点,但很多学生做这块时只是机械地做出"发帖+评论",完全没有社区运营的概念。设计和实现上,我建议把社区拆成经验交流帖和求购信息两类内容,分别处理。
5.1 帖子发布与列表
发帖的字段很简单:标题、正文(支持SSE富文本或Markdown)、图片(最多9张)、所属话题分类(种植技术、病虫害防治、苗木行情、求购/出售等)。为了防止XSS攻击,前端提交的富文本内容在后端要过滤一遍script标签——这个安全细节一定要处理,否则答辩时评委稍微专业一点就会指出漏洞。
帖子列表页的分页查询可以用MyBatis-Plus的Page对象完成:
Page<PostVO> page = new Page<>(current, size); LambdaQueryWrapper<Post> wrapper = new LambdaQueryWrapper<>(); wrapper.eq(StringUtils.hasText(category), Post::getCategory, category); wrapper.orderByDesc(Post::getIsTop).orderByDesc(Post::getCreateTime);列表里需要展示帖子的标题、作者昵称和头像、封面图(取第一张)、浏览数、点赞数、回复数。browse_count、like_count这些统计字段别用count(*)实时查,直接在post表里冗余字段,操作时UPDATE post SET like_count = like_count + 1即可,对毕设级别的并发量完全够用,而且查询效率高。
5.2 帖子详情与回复
详情页是互动最密集的页面:左侧帖子正文和图片,下方是按楼层排列的回复列表。回复表设计时我加了一个parent_id字段,支持二级回复(回复某楼的评论),这样当有人问"桂花树冬季落叶正常吗"时,下面可以形成追问和答主再回复的对话链,比只能回一楼要自然得多。
另外点赞功能建议做成"一人一赞"控制。用一个post_like表记录谁给哪个帖子点了赞,联合主键(member_id,post_id),点赞时先尝试插入,插入成功则post.like_count = like_count + 1,取消赞则相反。这个方案比用Redis做计数器更适合毕设——虽然Redis方案性能更好,但"用户维度唯一点赞"这个数据要落库,写进论文里逻辑更完整。
5.3 求购信息:苗木交易的另一只手
求购信息(purchase_demand表)是这个项目的点睛之笔。需求很简单:买家发布"求购:米径8cm的紫薇,50棵,预算3000,江西境内可送货",填写品种、规格要求、数量、预算、期望的交货时间、联系方式、备注,发布后进入求购列表。供应商可以根据求购条件筛选,找到匹配的求购单后可以在详情页点击"我要应标",填写报价和备注,这条应标记录自动推送到发布者的站内消息列表里——这就是"互助"这个词的精髓,平台不只是货架,还是一个供需撮合的信息中转站。
实现时,应标表demand_bid记录(求购单ID、供应商ID、报价、电话、备注、时间、联系电话、状态),状态包括"待确认""已接受""已拒绝"。发布者进入"我发布的求购"页面,可以看到每一条求购单下有多少人应标,选择接受某一条应标后,系统给对应供应商发送一条站内信,并把这条求购单的状态改为"已完成"。这个撮合逻辑写好后,是在论文的"系统创新点"部分非常好写的一笔:你说它不是单纯的B2C商城,而是一个C2B反向交易+社区互助的混合模式,这个概念一出来,系统立意就提升了。
5.4 站内消息通知机制
为了配合上面这些业务动作(接受应标、订单发货、回复提醒、审核结果),还需要一张message站内信表。消息触发的时机包括:
- 帖子被别人回复时,通知楼主
- 求购单被应标时,通知发布者
- 求购单接受应标时,通知应标供应商
- 商品被管理员下架时,通知供应商
- 订单退款状态更新时,通知买家
实现上不需要做WebSocket实时推送,最简单的方案是:用户进入"消息中心"页时,通过接口查询未读消息列表,已读状态的只显示数量角标。表设计时加一个is_read字段,未读消息数用SELECT COUNT(*) FROM message WHERE receiver_id = ? AND is_read = 0统计。如果你想让评论区回复的通知实时一点,可以前端每30秒轮询一次——撑起演示完全没问题,答辩时你可以说"考虑了实时性需求,用轮询方式实现,如果要提升体验可以替换为WebSocket长连接",这样既诚实又展示了扩展思路。
6. 实战踩坑记录:图片上传拦截、SpringBoot版本兼容、MyBatis-Plus字段映射问题
做这个项目的过程中,下面这几个坑几乎每个复现者都会遇到,我挑最有代表性的写出来,配套排查思路,你在开发时可以少走弯路。
6.1 图片上传404/被拦截
前端上传图片后,后端返回了访问路径,但浏览器打开直接404。排查思路分三步走:第一步,先确认文件是否真的保存到了目标目录(看磁盘上有没有文件);第二步,看返回的路径是否是http://localhost:8080/images/xxx.jpg这种格式;第三步,如果在SpringBoot里直接对外访问这个路径,必须配置WebMvcConfigurer接口的addResourceHandlers方法,否则SpringBoot默认不会把/images/**映射到本地磁盘目录。
@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/images/**") .addResourceHandler("/images/**") .addResourceLocations("file:" + uploadPath + "/"); } }这个配置漏掉的可能性极高,尤其是前后端分离项目里,前端项目通过Vite代理访问后端时,/images路径可能没被代理到,也需要在Vite的server.proxy配置里加上对应路径。很多学生排查半天,最后发现是Vite没配代理。
6.2 SpringBoot版本升级后的javax/jakarta问题
如果你用了SpringBoot 3.x,javax.servlet、javax.annotation这些包已经迁移到jakarta.*命名空间了。网上很多老代码里写的是import javax.servlet.http.HttpServletRequest,直接复制过来编译就报错,因为JDK 17 + Jakarta EE 9里没有这个包了。排查思路就是全局搜索javax替换成jakarta,同时确保pom.xml里的依赖版本都是兼容SpringBoot 3.x的新版。这个坑其实很好判断,只要你发现编译时报"程序包javax.servlet不存在"或者NoClassDefFoundError,第一反应就查版本兼容。
顺带说一个SpringBoot 3的连带问题:像springfox-swagger2这样的老的接口文档库在SpringBoot 3下是用不了的,必须换knife4j-openapi3-jakarta-spring-boot-starter,这个库的OpenAPI 3风格和Swagger 2有差异,注解也变了(@Api换成@Tag),你在配置接口文档时如果发现页面不显示分组,多半就是这个原因。
6.3 MyBatis-Plus实体类字段与SQL关键词冲突
有一张表叫member,字段里有一个order或者desc之类的名字,数据库里这些词是SQL保留字,执行查询时直接报语法错误。排查时错误信息会指向某条SQL语句,提示syntax error at or near "order"。解决方案有三个:一是给保留字字段加反引号(不推荐,每个查询都要手动注意);二是用@TableField(value = "order")注解强制转义;三是直接换个字段名,比如sort_no、content。对于毕设来说,最简单靠谱的是一开始建表时就避开所有SQL保留字,建表前花两分钟把字段名过一遍,比后面改代码省事多了。
6.4 事务不生效:自调用导致@Transactional失效
这是Spring面试里考烂了的经典问题,但在毕设里依然普遍存在。比如在一个Service类里,createOrder()方法内部直接调用了同一个类的deductStock()方法,deductStock()上标了@Transactional,但实际上这个事务不会生效,因为Spring事务是基于AOP代理的,类内部自调用绕过了代理对象,注解形同虚设。排查办法很直观:检查报错或日志里是否有Transaction相关输出,如果没有,就说明根本没走代理;解决方案是事务注解加到createOrder()这个对外方法上,或者把deductStock()挪到另一个Service类里,用@Autowired注入后调用。
我在写这个项目时的一个体会是:事务粒度宁大勿小。把整个下单流程(校验→扣库存→插订单→插明细→删购物车)放在一个@Transactional方法里,任何一个环节出错全部回滚,数据就不会出现"订单生成了但库存没扣"这种状态不一致。毕设阶段不用过度设计,把事务用对、用到位,已经超过很多人了。
6.5 富文本XSS过滤与全局异常处理
这是最后补的两个工程化细节。帖子正文如果支持富文本直接入库,那<script>标签就会原样存进数据库,前端渲染时如果没有做转义——答案是Vue默认会转义,但如果你用了v-html渲染,恶意脚本就可以执行(理论上)。最稳妥的做法是后端加一个简单的过滤:
public String cleanHtml(String content) { return content.replaceAll("<script.*?</script>", "") .replaceAll("<iframe.*?</iframe>", "") // 再保留基本的p、img、strong等安全标签 ; }全局异常处理建议单独写一个@RestControllerAdvice,统一捕获BusinessException和Exception。这样返回给前端的格式永远是{code, message, data},你可以在code上区分成功(200)、业务错误(400)、未登录(401)、无权限(403)、服务器异常(500)。这个设计虽然基础,但答辩环节老师很容易被"统一异常处理"吸引提问,你可以顺理成章地展示对工程结构的思考。
7. 论文结构、答辩演示与演示数据准备的实用建议
大部分学校对毕设论文的结构要求都差不多,但苗木交易这个题有它独特的论文展开方式。我建议论文的核心章节这样组织:
- 第三章"需求分析"里重点写:苗木交易的实际痛点(规格信息不对称、信任建立困难)、两类用户角色细分(采购商、供应商)、功能性需求与非功能性需求(并发扣库存、图片上传大小限制、数据安全)
- 第四章"系统设计"里重点写:整体架构图(前端Vue 3→后端SpringBoot→MySQL)、功能模块划分、E-R图设计(注意把
product_spec和order_item两张表画清楚)、数据库表结构说明 - 第五章"系统实现"里重点写:订单状态机的流转过程(画状态流转表)、商品规格管理的实现思路、社区互助功能的撮合流程、乐观锁防止超卖的代码片段
- 第六章"系统测试"里重点写:功能测试用例表(每个模块至少2-3个用例)、并发测试(用JMeter模拟10个线程同时抢购一件商品)、兼容性测试
答辩演示之前,一个特别容易被忽略的环节是演示数据的准备。很多学生为了演示临时在系统里录入数据,效果很差。我的建议是写一个DataInitializer,系统启动时自动往数据库插入一批仿真数据:
- 5-8个苗木分类(乔木类:香樟、桂花、银杏;灌木类:红叶石楠、金森女贞;草坪/地被类;果树类:柑橘、枇杷)
- 每个分类下2-3个商品,每个商品3-4个规格(如"香樟 - 米径10cm - ¥180"、"香樟 - 米径12cm - ¥260")
- 每个商品配1-2张真实可访问的图片(去图床找真实苗木图,别用卡通图)
- 2-3个用户(一个普通买家、一个苗农供应商、一个管理员),密码统一用
123456 - 若干条帖子数据里至少包含一条求购信息和一条高热度回复帖
为什么强调图片要用真实苗木照片?因为苗木交易的核心是"看品相",真实的图会让评委直观感知到你这个项目是真懂行业场景的。我见过有人用IDEA生成的全是灰色矩形占位图,答辩演示时整个页面氛围感全无,非常减分。
关于SpringBoot和MyBatis-Plus这类技术栈是否写进"创新点",我的建议是不要。创新点应该围绕业务设计展开:"面向苗木品类非标品特性的多规格SKU设计""C2B反向求购撮合与社区互助的双轮驱动模式""基于乐观锁的库存并发控制方案"。这三个点无论从业务价值还是技术含量上都站得住脚,而且比"使用了SpringBoot框架"高了好几个档次。
另外,答辩之前把项目的部署环境准备好。演示用的电脑上启动前先确认端口没有冲突(8080后端、5173前端),MySQL服务已在运行并执行过初始化脚本。最好准备一个README.md,写明项目启动步骤、默认账号密码、技术栈版本号,这样不仅演示时方便,评委翻阅项目时也觉得规范。如果你愿意把项目打个Docker镜像部署到云服务器上,那演示效果会更稳,答辩时也不怕现场断网——这一步加分效果非常明显,值得提前两天就做。