SSM商店管理系统毕业设计:从选型到答辩的完整指南 1. 为什么“SSM 商店管理系统”总是摆在毕设选题列表第一名1.1 这个题目到底想考你什么每年一到毕业季总有同学私信问我“师兄我在选题系统里又看到了 SSM 商店管理系统还带源码和论文这东西到底好不好做”说实话单看名字它很普通但它在本科阶段的 Web 项目里属于“恰到好处”的难度。它不像“图书管理系统”那样一眼到底也不像“分布式电商平台”那样脱离课程实际。它有用户、有商品、有订单、有库存、有统计报表刚好能把 Java 基础、数据库设计和 Web 框架全部串起来。尤其对于 2026 届的同学来说SSM 组合依然是学校教学里最常讲的 Spring 生态雏形。Spring 负责对象管理SpringMVC 负责请求路由MyBatis 负责数据库操作整套技术栈的学习曲线相对平缓。商店管理系统则提供了足够多的业务场景商品分类、库存预警、订单结算、会员积分、营业统计甚至还可以扩展出权限管理、Excel 导出、条形码生成。这些功能听起来不难但每一个背后都对应着明确的数据库表设计和接口逻辑老师一看就知道你有没有真正动手写过代码。我也见过不少同学觉得“这个题太老”。但毕业设计的核心评价标准从来不是技术多么新而是你能否完整地实现一个可用系统并且能说清楚里面每一步的原理。SSM 商店管理系统是少有的“老但不过时”的组合它在代码量、业务复杂度、论文篇幅之间找到了平衡。如果你能把这套题吃透不管是答辩还是后续自学 Spring Boot底子都会很扎实。1.2 一套 SSM 里到底藏了哪些东西很多非科班或者基础不牢的同学听到“SSM”会下意识觉得它是个大框架。实际上它就是三个开源框架的组合各管一段。我们拿商店收银的例子来打比方顾客进店下单前台的收银员接待顾客这相当于 SpringMVC 的 Controller 层负责接收页面请求并返回结果后厨和仓库调配货物这相当于 Spring 管理的 Service 层和 DAO 层负责处理业务流程仓库管理员记录进出账这相当于 MyBatis 持久层负责把数据落到数据库里。而 Spring 容器本身则像是整个门店的运营制度把所有员工和岗位统一管起来。在实际代码里Spring 的 IOC 让你不再通过 new 来创建对象而是用注解把对象交给容器管理AOP 又允许你在执行某些方法前后统一记录日志或开启事务。SpringMVC 接收前端传来的参数通过注解映射到处理方法然后把业务数据和视图名称一起返回。MyBatis 则让你把 SQL 写在 XML 或注解中避免手动写大量的 JDBC 代码。这三块拼起来正好形成一个完整请求链路页面发请求 - DispatcherServlet - Controller - Service - Mapper - 数据库再反向封装返回 JSON 或 JSP 页面。我这里给基础薄弱的同学一个建议不要在还没有理清请求链路时就去死磕源码实现。你只需要记住一次完整的登录操作经过了哪几个方法、每个方法的职责是什么这比背诵任何八股文都管用。1.3 选型时最常见的几个误区第一类误区是“一上来就换成 Spring Boot”。如果你准备时间充足改用 Spring Boot MyBatis 自然更省事它内置了 Tomcat、自动配置搭建时间少一大半。但问题在于很多学校的大纲和答辩评审还是按 SSM 的架构来提问。你可以在项目中引入 Spring Boot然后说它是 Spring 的快速封装但必须能解释清楚底层和 SSM 的对应关系。如果你连基础配置都说不清反而容易被追问到尴尬。第二类误区是完全依赖图形化工具生成代码。现在很多代码生成器能直接生成 Mapper、Controller、前端页面。生成的代码确实能跑可如果答辩时老师让你现场改一个需求比如把“单商品库存扣减”改成“批量库存扣减”你如果对着代码无从下手那问题就出在“没理解”。我不是反对用工具而是建议你先手写一遍核心的 Controller 和 Service然后用工具去补齐重复的 CRUD这样既节省时间又能保证自己hold住代码。第三类误区是把论文和系统完全分开做。很多同学先把代码写完最后三天憋出一篇论文结果系统里的表名和论文里的图对不上。正确做法是先确定功能模块再按模块同时推进代码和文档至少要保证数据库设计、核心流程图、界面截图这三部分是从项目里真实提炼出来的。后面我会专门说论文怎么写这里先记住一个原则论文是系统的说明书不是独立的文学作品。2. “商店管理系统”的需求远不止写几个 CRUD2.1 干需求之前先回答四个问题做毕设最容易犯的毛病就是拿到题目就建表。建表前你得先问自己四个问题这个商店卖什么谁来使用系统用户需要被区分成几种角色每天的订单量和数据量大概有多大这四个问题直接决定了表结构、权限逻辑、分页方案和统计报表怎么写。以最常见的超市便利店场景为例角色通常分为管理员、收银员、仓管员。管理员负责员工账号、商品上下架、查看营业报表收银员负责前台开单、收款、退货仓管员负责入库、出库、库存调整。这三个角色对应的是不同菜单和不同按钮权限而不是简单用一个 isAdmin 字段区分。你可以在用户表中加一个 role_id再在菜单表中用角色关联菜单或者更简单一点在拦截器或过滤器里按角色名写判断逻辑。毕业设计不要求做到细粒度权限但要能拦住普通收银员访问管理员页面。至于卖什么很多人会写成“商品信息管理”实际上商店商品一般有两种方式一种是固定 SKU比如每瓶饮料有自己的条码、进价、售价另一种是称重或按件计费需要临时改价。如果你选了生鲜超市作为背景最好在商品表中增加一个 goods_no货号、bar_code条码字段这样论文场景会更有说服力。2.2 把功能列表拆成“能演示”的样子需求阶段不要只顾着罗列功能而是要想清楚答辩时怎么演示。我习惯把功能分成三类基础 CRUD、核心业务、加分亮点。基础 CRUD 包括商品增删改查、分类管理、供应商管理、客户管理核心业务包括商品入库出库、库存变动、订单创建、订单结算、退货退款加分项包括库存预警、月度销售统计、会员积分、Excel 导入导出。三级划分的好处是答辩时间不够时你至少能把核心业务完整走一遍。商店系统的关键词里“库存”“订单”“统计报表”通常权重最高。建议把这些功能做深而不是做多。比如库存预警不能只是查询时显示一下库存低于多少而应该在商品列表页用颜色标出低库存商品或者在登录首页做一个待处理提醒模块。很多同学喜欢堆功能页面做了十几个但每个页面都只有一个简单的表格这样反而显得浅。下面是一个我给同学做需求梳理时常用的功能对照表大家可以直接拿来做选题分析功能模块包含页面/操作对应角色是否为核心必做登录与权限账号密码登录、修改密码、退出登录全部必做商品分类分类树维护、上下级分类管理员必做商品管理商品列表、新增、编辑、上下架管理员、仓管员必做库存管理入库、出库、库存调整、预警仓管员必做订单管理创建订单、订单列表、订单详情、退款收银员、管理员必做会员管理会员开卡、积分累计、等级折扣收银员加分统计报表日/月营业额、TopN商品、分类占比管理员加分系统管理用户管理、角色管理管理员加分2.3 页面设计要提前想好别等后端写完很多同学后端的接口写得很顺利到了前端开始卡壳。SSM 项目最常用的前端方案是 JSP JSTL Bootstrap也有用 Vue 前后端分离的。如果是传统 JSP 方案每个页面都要写好表单和表格列表页注意翻页、搜索条件、操作按钮三个区域要固定存在。新增和编辑可以做成模态框也可以在同一个 jsp 里用 if 判断区分新增编辑模式。推荐使用模态框因为这样页面数量少演示时也更流畅。如果选了 Vue 分离式开发记得把静态页面先放在前端项目中通过 Axios 调后端接口。不过要提醒一句许多实训基地和答辩现场只提供内网环境端口配置容易出错所以前后端分离项目一定要提前采购并使用 Vite 或 Webpack 打包后的 dist 文件并配置好后端的静态资源映射。这块内容看似和 SSM 无关却往往是项目跑不起来的原因。3. 数据库设计是最容易被低估的部分3.1 核心表怎么拆分直接决定了代码难不难写商店管理系统的数据库一般不少于 8 张表。我见过的最精简版本有 5 张表用户、商品分类、商品、订单、订单明细。如果选这个精简版代码会写得很痛苦因为供应商、库存日志、权限这些功能全部要往现有表里塞外键或字段。建议至少拆到 10 张表但又不要为了加表而加表每一张表都必须有明确的业务含义。下面是核心表的基本拆法sys_user 用户表user_id, username, password, real_name, role_id, status, create_time。密码不要直接明文存哪怕毕设也应该用 MD5 加盐或 BCrypt 加密。答辩老师看到明文密码会非常减分。category 商品分类表category_id, parent_id, name, sort_order, status。product 商品表product_id, category_id, product_no, bar_code, name, price, stock, sale_count, status, create_time, update_time。supplier 供应商表supplier_id, name, contact, phone, address。stock_log 库存流水表log_id, product_id, change_type, change_count, before_stock, after_stock, remark, operator_id, create_time。这张表强烈建议保留它是“库存操作留痕”的关键论文里也能单独写一节。member 会员表member_id, name, phone, points, level, balance, create_time。order 订单表order_id, order_no, member_id, user_id, total_amount, pay_amount, discount_amount, pay_type, status, create_time, pay_time。order_item 订单明细表item_id, order_id, product_id, product_name, price, count, amount。3.2 订单明细为什么必须单独建表很多新手写订单时喜欢在订单表里放一个 goods_ids 字段用逗号拼接商品 ID或者干脆只保存总金额明细不落库。这两种做法在毕业设计中都会给答辩带来麻烦。单独建立 order_item 表后每张订单对应多条明细不仅符合数据库第一范式的直觉而且方便统计商品的销售数量后续做“热销商品排行榜”时直接按 product_id 分组求和效率很高。订单表里的 order_status 建议用整型表示状态比如 0 表示待付款1 表示已付款2 表示已发货/已完成3 表示已取消4 表示已退货。不要用字符串像“未支付”“已支付”这样在 Java 代码里一堆中文硬编码很容易出错。前后端的字典值可以用状态枚举类统一管理或者在前端页面用 JSTL 的 c:if 判断。3.3 外键、索引和软删除毕设里如何取舍理论上外键能保证数据一致性但在 SSM MyBatis 项目中大量外键反而会影响开发效率因为删除主表数据时总是被外键约束拦住。我的建议是在表结构中保留逻辑关联但不一定都建物理外键核心业务表之间的关系用索引和业务代码来保证。比如商品表的 category_id既然不会随便改可以建一个普通索引用于按分类查询。而在代码层面删除一个分类前必须先查该分类下是否有商品如果有则提示“分类下还有商品不能删除”。软删除也很重要。商品表不要直接 DELETE而是加一个 status 或 is_deleted 字段0 正常1 删除。这样库存流水和历史订单在查询时不会因为商品被删而丢失关联。很多系统在演示时删掉一个商品再翻历史订单发现商品名称空了就是因为没有软删除再加上外键没有做冗余存储。3.4 给出可直接套用的建表参考下面这段 SQL 是商品表和库存流水表的最小可用版本你可以直接拿去做原型验证。注意我给时间字段加了默认值Java 里就可以不用每次手动塞时间。CREATE TABLE product ( product_id INT NOT NULL AUTO_INCREMENT COMMENT 商品ID, category_id INT DEFAULT NULL COMMENT 分类ID, product_no VARCHAR(32) NOT NULL COMMENT 商品编号, bar_code VARCHAR(64) DEFAULT NULL COMMENT 条码, name VARCHAR(100) NOT NULL COMMENT 商品名, price DECIMAL(10,2) NOT NULL COMMENT 零售价, cost_price DECIMAL(10,2) DEFAULT NULL COMMENT 进价, stock INT NOT NULL DEFAULT 0 COMMENT 当前库存, warn_stock INT NOT NULL DEFAULT 10 COMMENT 库存预警阈值, status TINYINT NOT NULL DEFAULT 1 COMMENT 1上架 0下架, create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (product_id), KEY idx_category (category_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT商品表; CREATE TABLE stock_log ( log_id INT NOT NULL AUTO_INCREMENT, product_id INT NOT NULL, change_type TINYINT NOT NULL COMMENT 1入库 2出库 3盘盈 4盘亏 5销售扣减, change_count INT NOT NULL, before_stock INT NOT NULL, after_stock INT NOT NULL, remark VARCHAR(255) DEFAULT NULL, operator_id INT DEFAULT NULL, create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (log_id), KEY idx_product (product_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT库存流水表;这里强调一点库存流水表里要同时存 before_stock 和 after_stock而不是只存一个 change_count。这在复盘问题时非常有用学员后面问“为什么库存不对”你一看流水就知道是哪一步加减出了问题。4. 后端核心逻辑登录认证、库存扣减与订单事务4.1 登录认证到底该不该用 SessionSSM 项目最常见的登录方案是使用 HttpSession。用户登录成功后把 user 对象放入 session然后通过 SpringMVC 拦截器判断用户是否登录以及当前访问的 URL 是否在权限范围内。这种方案实现简单而且和 JSP 的 session 作用域天然契合。但如果使用了前后端分离Session 方案需要配置跨域携带 Cookie相对麻烦。这时候可以改用 Token 方案登录成功后生成一个 UUID 或 JWT 返回给前端前端每次请求放在请求头里后端通过拦截器解析。我个人的建议是如果你用的是 JSP Bootstrap无脑选 Session。因为答辩老师最常问的就是 Session 和拦截器的关系。代码里只需要一个配置文件再写一个实现 HandlerInterceptor 的拦截器类表示没有登录时重定向到 login.jsp。这里注意 SpringMVC 中放行登录接口和静态资源的配置否则会出现登录后刷新页面 JS 和样式全丢失的现象。4.2 库存扣减的一条 SQL 胜过“先查再改”现在到了商店管理系统最关键的一道坎创建订单时如何扣库存。初级写法是先根据商品 ID 查出库存判断库存是否充足然后 UPDATE 商品表 set stock stock - count。这种写法在并发量低时没问题但它不是原子操作。如果两个请求同时读到 stock5各自都认为库存够结果都去执行 set stock stock - count在极端情况下会出现超卖。虽然毕设演示没有并发压力但我一直建议直接用原子更新。对应的 MyBatis Mapper 方法可以写成这样Update(UPDATE product SET stock stock - #{count} WHERE product_id #{productId} AND stock #{count}) int reduceStock(Param(productId) Integer productId, Param(count) Integer count);这段 SQL 返回受影响行数 affected。如果 affected 等于 0说明库存不足或者商品不存在Service 层直接抛异常并提示用户。这样既不回退库存也不需要加锁逻辑非常干净。同理增加库存也直接用 stock stock #{count}配合库存流水表记录变更原因。4.3 一个订单从创建到落库的事务控制订单业务同时要操作多张表插入订单主表、插入订单明细、扣减商品库存、记录库存流水、计算会员积分。这些操作要么全部成功要么全部失败所以 Service 方法上要加 Transactional。下面是一个简化版代码Service public class OrderServiceImpl implements OrderService { Resource private ProductMapper productMapper; Resource private OrderMapper orderMapper; Resource private OrderItemMapper orderItemMapper; Resource private StockLogMapper stockLogMapper; Override Transactional(rollbackFor Exception.class) public Order createOrder(OrderDTO dto) { // 1. 创建订单主记录状态为待付款 Order order new Order(); order.setOrderNo(generateOrderNo()); order.setMemberId(dto.getMemberId()); order.setUserId(dto.getUserId()); order.setTotalAmount(dto.getTotalAmount()); order.setStatus(0); orderMapper.insert(order); // 2. 遍历商品明细扣减库存并插入明细 ListOrderItemDTO items dto.getItems(); BigDecimal total BigDecimal.ZERO; for (OrderItemDTO item : items) { int affected productMapper.reduceStock(item.getProductId(), item.getCount()); if (affected 0) { throw new RuntimeException(商品ID item.getProductId() 库存不足); } Product product productMapper.selectById(item.getProductId()); OrderItem orderItem new OrderItem(); orderItem.setOrderId(order.getOrderId()); orderItem.setProductId(product.getProductId()); orderItem.setProductName(product.getName()); orderItem.setPrice(product.getPrice()); orderItem.setCount(item.getCount()); orderItem.setAmount(product.getPrice().multiply(BigDecimal.valueOf(item.getCount()))); orderItemMapper.insert(orderItem); // 3. 写库存流水 int afterStock product.getStock() - item.getCount(); stockLogMapper.insert(buildStockLog(product, 5, item.getCount(), afterStock)); total total.add(orderItem.getAmount()); } // 4. 最后更新订单总金额 order.setTotalAmount(total); orderMapper.updateAmount(order.getOrderId(), total); return order; } private String generateOrderNo() { // 一般取时间戳 随机数或者用雪花算法 return System.currentTimeMillis() String.valueOf((int)((Math.random() * 9 1) * 100000)); } }注意 Transactional 默认只在抛出 RuntimeException 时候回滚所以你可以在 Service 方法里直接 throw new RuntimeException(库存不足)这样事务会回滚。如果你们习惯用自定义业务异常记得设置 rollbackFor Exception.class避免某些检查异常没有被回滚。4.4 列表查询和分页别手写 Limit商品列表、订单列表这些页面几乎必然需要分页。SSM 项目里最简单的方式是引入 PageHelper 插件在 MyBatis 配置文件里注册插件然后查询前调用 PageHelper.startPage()。它的原理是拦截即将执行的 SQL自动拼接 LIMIT 语句并且用 PageInfo 包装查询结果方便前端拿到总条数和页码。PageHelper.startPage(pageNum, pageSize); ListProduct list productMapper.selectProductList(dto); PageInfoProduct pageInfo new PageInfo(list);这里有个容易翻车的细节PageHelper 是线程本地变量所以 startPage 必须紧跟紧接着的 Mapper 查询语句中间不能插入别的查询。如果你在两个查询之间调用了一个无关的 Mapper分页会被第二个查询吃掉。我见过不少同学调试半天发现 List 数据总是多出来就是因为这个原因。5. 从源码结构到论文组织一条线走通5.1 一份能过查重又能落地的源码结构拿到“源码论文”这种题目时最忌讳的是你只会在 IDE 里启动项目论文却不知道代码为什么这么分层。SSM 项目的标准分层通常长这样src/main/java com.example.shop controller -- 接收请求参数校验 service -- 业务接口 service.impl -- 业务实现 mapper -- MyBatis 接口 entity -- 实体类 dto -- 前端传参封装 vo -- 页面显示值对象 interceptor -- 登录/权限拦截器 config -- 配置类 src/main/resources mapper -- Mapper XML 文件 spring -- 或 applicationContext.xml springmvc.xml jdbc.properties src/main/webapp WEB-INF views -- JSP 页面 web.xml static -- 静态资源这种分层最大的好处是代码职责清楚。Controller 里只做参数接收和调用 Service不要写业务 SQLService 实现类里写事务逻辑Mapper 只做单表或常用多表查询。很多源码下载包里的代码Controller 里直接注入 Mapper甚至把多条 SQL 逻辑写到了 Controller看起来能跑但答辩时会被老师问“业务逻辑都堆在控制层你怎么测”。所以拿到源码后如果发现这种问题第一件事是重构而不是改个名字就提交。5.2 论文的章节不要复制网上的目录论文结构不用太创新但一定要和你自己的系统对应。常见的毕业设计论文章节是绪论、相关技术、需求分析、系统设计、系统实现、系统测试、总结。重点在系统设计和系统实现这两章要把实际表结构和功能模块展开写。我建议论文里的每个功能模块配一张“页面截图 核心代码片段”代码不要整页贴只贴关键方法。比如第四章“商品库存预警模块设计”里可以先描述需求当库存低于预警阈值时首页统计栏显示异常数量商品列表用红色背景标出。然后贴一段对应的 Service 方法再贴一张实际页面截图。这样评审老师读起来会很轻松也会认为你的工作量真实。系统测试不要只写“功能测试通过”六个字。要写出测试用例表比如用例编号、测试步骤、预期结果、实际结果。哪怕只是手工测试一张 10 行的用例表也比一句话强得多。性能测试可以写“使用 JMeter 模拟 50 个并发请求登录接口平均响应时间 120ms”但这部分必须在你真实跑过之后才写不然答辩一问具体数据你就露馅。5.3 页面设计里最容易提升观感的几个点商店管理系统最容易给人“普通 CRUD”的感觉是因为界面只有表格和按钮。想提升观感不需要你精通前端只需要做好几件小事统一列表页的搜索条件放在搜索栏里新增编辑按钮放在右上角操作按钮用不同颜色商品价格用 Decimal 格式化金额列保证两位小数当前选中菜单高亮表格空数据要显示友好的空状态。还有一个性价比很高的功能首页仪表盘。登录后默认展示今日订单数、今日营业额、库存预警数、会员总数下面配一个按最近 7 天销售额生成的柱子图。做这种图不一定要引入 ECharts 系列你可以在 JSP 里用 Chart.js引入一个 JS 文件写一个 ajax 请求获取统计数据再渲染 canvas 即可。就一个首页统计答辩时整个项目的感觉都不再是“普通管理系统”。6. 运行部署和调试时那些没人提前告诉你的坑6.1 环境版本不匹配是头号杀手SSM 是老牌组合对版本很敏感。最常见的组合是 JDK 1.8、Maven 3.6、Tomcat 8/9、MySQL 5.7。如果你用了 JDK 17 且没有处理模块化相关设置实际项目会抛出 IllegalAccessError如果 MySQL 驱动用了 8.x而你的 jdbc.properties 里还写着 com.mysql.jdbc.Driver就会提示找不到驱动类。现在的正确写法是jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/shop_db?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai jdbc.usernameroot jdbc.passwordyourpassword很多同学第 1 次启动就卡在数据库连接不上。先把 MySQL 服务启动然后用命令行连接一下数据库最后再启动 Tomcat。千万不要直接跳过去看浏览器报错页面Tomcat 的报错日志通常只告诉你数据库连接异常而真正的根因在控制台完整堆栈的第一行。6.2 前端 404 和中文乱码的排查路径SpringMVC 静态资源 404 是非常经典的问题。如果你把 JS、CSS、图片放在 webapp/static 下面需要在 springmvc.xml 里配置放行mvc:resources mapping/static/** location/static//同时前端 JSP 页面里引用静态资源最好使用带项目名的绝对路径比如link href${pageContext.request.contextPath}/static/css/style.css relstylesheet script src${pageContext.request.contextPath}/static/js/jquery.min.js/script这样不会因为双击打开页面或者跳转到子路径导致资源路径错乱。中文乱码则要看三个地方MySQL 连接 URL 是否带 characterEncodingutf8后端过滤器的编码是不是 UTF-8数据库表的字符集是否为 utf8mb4。三个地方有一个漏了就会乱码。6.3 拿着源码跑通后一定要自己动手改三个地方不管你是自己从零写的还是参考了某个开源版本我强烈建议跑通之后立刻做三件改造第一把超级管理员账号的密码改成加密存储并修改默认密码第二把订单号生成逻辑改成时间戳加随机数的形式第三给商品列表加一个“库存预警”查询条件。这三处改造小但能说明你真正看懂了代码就算答辩老师现场问你也能答上来。我辅导过不少同学他们一开始拿到的参考代码里管理员密码是明文 123456登录后甚至可以直接在 URL 上访问 /admin/product/add。这些安全上的问题在代码审阅时都会被放大。你不需要做成银行级别的安全系统但至少不能有低级漏洞。7. 答辩前一天的检查清单与我的几点体会7.1 答辩演示时的“保命顺序”第七天答辩第六天晚上你还不知道怎么演示才不会翻车这是常态。我的建议是准备一份“演示剧本”按照下面顺序走先打开首页统计面板展示今日营业额和库存预警然后进入商品管理添加一件商品把库存设为 1去库存管理中做一次入库回到商品列表确认库存更新创建一笔订单选择两件商品确认支付打开订单明细检查库存流水最后给会员增加积分并导出 Excel 报表。这趟流程覆盖了 90% 的功能还特别能说明事务、库存、订单之间的联动关系。答辩时少讲“我的系统用了什么技术”多讲“我的核心业务流程是怎么设计的”。比如描述库存预警时说清楚预警阈值在哪张表、查询时如何统计、列表如何标红这比念 PPT 上的技术介绍强一百倍。7.2 遇到不会的问题我的兜底话术老师常问的三件套是登录校验怎么做、事务控制加在哪、数据库为什么这么设计。万一被问到没做过的点比如“你们怎么防止并发超卖”不要直接说“没做”。你可以说我在扣减库存时使用了原子更新的 SQL 和受影响行数判断这已经保证了数据一致性在更极端的高并发场景下还可以引入 Redis 预减库存或用数据库悲观锁但毕设的重点是先保证核心逻辑可靠。这个回答既诚实又展示了你的延伸思考。7.3 我个人在整套实践里最大的收获最后说点实在的。我带过的学生里真正把 SSM 商店管理系统做完的人往往并不是代码写得最花哨的而是愿意按“需求—表结构—核心流程—页面—测试”这条线一步步走的人。一开始他们也会在分页插件和事务注解上卡很久但这些问题恰恰是毕业后工作的常见问题。你只要把这一套逻辑吃透之后学 Spring Boot 时你会发现大量知识是平移的只是配置方式变简单了。所以我真心建议拿到这个题目的同学不要急着把选题目录里的“源码论文”当作终点。你要做的不是交一份作业而是借这个机会完整地思考一遍一个真实商店的信息流如何运转。等你自己能讲清楚商品从入库、上架、下单到出库的全过程这个毕设就已经值回票价了。