ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

SpringBoot南京美食商城系统毕业设计实战与避坑指南

2026/10/8 8:54:35 拓冰建站 浏览量
SpringBoot南京美食商城系统毕业设计实战与避坑指南 1. 这个项目的真实定位不只是“又一个电商系统”每年毕业设计季Java SpringBoot 商城系统几乎是最高频的组合题。我前后带过不少学弟学妹也帮人看过很多从网上下载的“源码”说实话真正能顺利跑起来、论文能自圆其说、答辩不被问倒的不到三分之一。问题往往不出在“不会写代码”而在于从一开始就没搞清楚这个题目到底在考察什么、要做到什么程度才算完成。“基于SpringBoot框架的南京特色美食小吃商城系统”这个题目乍看跟满大街的“XX商城系统”没区别都是商品、购物车、订单、支付那一套。但稍微多想一层就会发现它有几个隐藏的加分点一是“南京特色美食小吃”这个主题天然自带丰富的数据分类和商品形态盐水鸭、鸭血粉丝汤、桂花糖芋苗、牛肉锅贴、汤包……每个品类都有规格、口味、包装方式的差异这直接决定了你的数据库表和商品模块不能做得太简陋二是它是“毕业设计实战”意味着不光要能跑还要有论文、有答辩代码和文档必须互相印证。如果你也是在为毕业设计选题目或者已经拿了类似题目但还没理清思路这篇博文就是把从零搭建、核心业务落地、部署避坑、论文答辩这一整条链路拆开给你看。它不是复制粘贴某个现成源码的教程而是教你怎么把一个“看起来普通的电商后台”做成“看起来有思考、有工作量、答辩能打”的完整项目。1.1 选题热度背后老师的真实评分逻辑先聊点实际的毕业设计这东西答辩老师不会一行行读你的代码他们判断一个项目好坏主要看三样东西——项目完整度、业务复杂度、技术点密度。完整度指的是模块是否闭环。只做了后台管理没有前台购物不行能下单不能查订单不行订单状态改来改去没有流程不行。一个合格的项目至少要覆盖前台用户注册登录、商品浏览、加入购物车、提交订单、模拟支付、订单查询后台管理员登录、商品管理、分类管理、订单管理、用户管理。这套闭环做完及格线就到了。业务复杂度则看你的表设计和逻辑有没有“故事”。同样是商城只写一张商品表、一张订单表和设计了商品规格表、购物车表、订单明细表、配送方式、优惠券表给人感觉完全不一样。“南京特色美食小吃”这个主题恰恰适合把复杂度做上去比如鸭血粉丝汤有大小碗之分、辣度可选这个“规格”的建模如果不拆一张SKU表后面写购物车和订单明细时会很别扭。技术点密度指的是你用了哪些“可说”的技术。SpringBoot是框架MyBatis-Plus是ORM这两个只能算基础盘。如果想拿高分得有几处“加分点”比如用拦截器实现登录鉴权、用乐观锁处理库存扣减、用Redis缓存热门商品如果环境允许、用定时任务处理超时未支付订单、用支付宝沙箱真实调用支付接口。这些点不用全上挑两三个做出深度答辩时就能讲得头头是道。1.2 明确需求边界做到什么程度算“完成”很多同学拿到题目第一反应是“我要做的功能越多越好”然后陷入功能膨胀最后连基本的登录都做得不稳固。我的建议正好相反先圈定核心链路再做两三个亮点最后补上边角功能。核心链路就一条用户在商城浏览美食商品 → 搜索或分类筛选 → 查看详情 → 加入购物车 → 提交订单 → 选择地址和配送方式 → 模拟支付或沙箱支付 → 生成订单并扣减库存管理员在后台对商品和订单进行全生命周期管理。亮点功能根据精力选做推荐位/首页轮播图管理、优惠券发放与核销、销量排行、订单超时自动取消、Excel导出订单列表、图片上传到本地目录或OSS。至于那些花里胡哨的功能——秒杀、拼团、直播带货、积分商城——建议都放一放一是实现复杂度高容易翻车二是论文里讲不清楚反而扣分。2. 技术选型与工程结构先把版本坑填平技术选型是整件事的定海神针很多项目跑到一半跑不起来不是代码逻辑问题而是环境问题——JDK版本不对、SpringBoot版本太高导致依赖冲突、Maven仓库拉包失败。这里直接给一套我反复验证过、最稳的组合。2.1 JDK、SpringBoot、核心依赖的版本搭配先说结论再解释为什么。JDK8搭配SpringBoot 2.7.xSpringBoot2.7.18这是2.x系列的最后一个版本稳定且资料多MyBatis-Plus3.5.xMySQL8.0前端方案Thymeleaf Bootstrap 5或者 Vue 3 Element Plus权限方案登录拦截器 Session或者 JWT项目构建Maven为什么我不建议直接上SpringBoot 3.x因为3.x强制要求JDK 17很多学校机房、答辩演示机器的JDK版本还是8你本地写得好好的拿到演示机一启动就报UnsupportedClassVersionError当场血压拉满。而且MyBatis-Plus、一些老的教程、第三方依赖对3.x的支持也出现过不少坑。SpringBoot 2.7.18足够完成这个项目等到答辩时还可以说一句“考虑到兼容性选用了成熟稳定的2.x版本”反而显得你有工程判断力。数据库驱动方面MySQL 8.0 的 JDBC 驱动是com.mysql.cj.jdbc.Driver现在很多教程还在写老版的com.mysql.jdbc.Driver连上就报错。连接字符串建议写成jdbc:mysql://localhost:3306/nanjing_food?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8allowPublicKeyRetrievaltrueserverTimezone一定要显式指定否则遇到The server time zone value й׼ʱ的乱码报错新手特别容易懵。2.2 前后端不分离还是分离给出明确选择这个决策直接影响你后续的开发和论文篇幅。我的建议是默认选Thymeleaf Bootstrap除非你有过硬的Vue经验否则不要逞强走前后端分离。理由很实在前后端分离意味着你要同时维护前端工程Vue/React、处理跨域、联调接口、打包部署工作量至少增加三分之一而且答辩演示时要从两个服务跑起来。Thymeleaf是SpringBoot官方模板引擎服务端渲染页面上直接用th:each、th:if循环展示数据一个应用就搞定部署也简单。当然如果你确实想用Vue做前端可以单独开一个工程后端只提供JSON接口。这种情况下建议明确使用API统一返回体比如RT类Data public class RT { private Integer code; private String msg; private T data; public static T RT ok(T data) { RT r new R(); r.setCode(200); r.setMsg(success); r.setData(data); return r; } public static T RT fail(String msg) { RT r new R(); r.setCode(500); r.setMsg(msg); return r; } }这个类在论文里也可以重点提一下统一了前后端交互协议方便前端对状态码进行统一处理。作为毕业设计的设计亮点完全拿得出手。2.3 工程结构规划包结构决定代码下限包结构这东西平时看起来无所谓但论文的“系统设计”章节要画架构图答辩时老师会翻你的项目结构。我建议采用以下分包方式com.nanjing.food ├── controller // 控制层接收请求 ├── service // 业务层核心逻辑 │ └── impl ├── mapper // 持久层数据库操作 ├── entity // 实体类User, Product, Order... ├── dto // 数据传输对象接收前端参数 ├── vo // 视图对象返回前端数据 ├── config // 配置类拦截器、跨域、静态资源映射 ├── common // 通用类统一返回R、异常处理、常量 └── util // 工具类订单号生成、文件上传等注意entity和vo一定要分开。很多同学直接把实体类返回给前端把密码、状态码、内部字段全暴露了答辩时被问“这里为什么返回了用户密码”就直接尬住。处理办法是建VO类只封装需要展示的字段。3. 数据库建模南京小吃的商品形态关键在SKU数据库设计是整个项目最值得花时间的部分。我见过太多初版代码商品只有一张表接口写起来倒是简单一遇到“鸭血粉丝汤要分大碗小碗”“盐水鸭要选整只还是半只”这类需求就彻底卡壳。问题的核心在于你缺了一张商品规格表。3.1 核心表结构设计与关键字段完整表结构我按通用范式整理如下你可以根据实际需求裁剪表名说明关键字段user用户表id, username, password, nickname, phone, avatar, role, create_timecategory商品分类表id, name, parent_id, sort, statusproduct商品表id, category_id, name, subtitle, main_image, detail_image, price, stock, sales, status, recommend, descriptionproduct_sku商品规格表id, product_id, spec_name, price, stock, imagecart购物车表id, user_id, product_id, sku_id, quantity, checkedaddress收货地址表id, user_id, receiver, phone, province, city, district, detail, is_defaultorders订单表id, order_no, user_id, address_id, total_amount, freight_amount, pay_type, status, remark, create_time, pay_time, finish_timeorder_item订单明细表id, order_id, product_id, sku_id, product_name, spec_name, product_image, price, quantitycoupon优惠券表id, name, type, amount, condition_amount, stock, start_time, end_timeuser_coupon用户领券表id, user_id, coupon_id, status, get_time, use_time, order_id为什么product表要有price和stock同时product_sku表也有price和stock因为有些商品没有规格比如“一盒梅花糕”展示价格直接用商品表的价格而“鸭血粉丝汤”分小碗12元、大碗16元那商品表的price存最低价用于列表展示详情页根据选中的SKU显示具体价格库存以SKU表为准。这种设计在论文里可以展开写价格双轨策略一个用于营销展示一个用于交易结算。注意结算时不能读商品表的价格必须读SKU表的价格否则改价逻辑会出错。3.2 订单状态机的设计状态清晰才能讲得明白订单状态是答辩高频考点。我设定如下整数状态码简单直观0待支付1已支付待发货2已发货配送中3已完成4已取消5已退款为什么不用字符串因为整数存数据库更节省空间查询比较更快状态流转在代码里用常量或枚举管理可读性也不差。建议建一个OrderStatusEnumpublic enum OrderStatusEnum { UNPAID(0, 待支付), PAID(1, 已支付), SHIPPED(2, 已发货), FINISHED(3, 已完成), CANCELED(4, 已取消), REFUNDED(5, 已退款); private final Integer code; private final String desc; // 构造函数、getter... }状态流转的控制逻辑放在OrderService的统一入口比如cancelOrder(orderNo, userId)、confirmReceipt(orderNo, userId)不要散落在各个Controller里。这样答辩时你可以整体画出状态图老师会认为你有软件工程意识。3.3 用乐观锁防超卖让库存扣减经得起追问商城系统最常见的追问就是“高并发下库存怎么不超卖”哪怕你只是毕业设计也要有一个拿得出手的思路。最简单有效的是在商品表加一个version字段使用MyBatis-Plus的乐观锁插件Configuration public class MybatisPlusConfig { Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return interceptor; } }实体类字段加上Version注解更新时MyBatis-Plus会自动带上版本号校验。扣减库存的核心片段boolean success productService.lambdaUpdate() .setSql(stock stock - 1) .eq(Product::getId, productId) .eq(Product::getStock 0) .update();配合乐观锁之后即使两个人同时下单也只有一个能成功扣减另一个拿到影响行数为0再去提示“库存不足”。这个设计在论文“系统实现”里可以单独写一节题目就叫“基于乐观锁的库存并发控制”名字一放老师印象分就上来了。4. 南京特色美食场景下的业务建模细节这个题目区别于普通商城的关键就是业务场景绑定在“南京特色美食小吃”上。场景设定得越贴近真实你的项目就越有说服力。4.1 商品规格建模辣度、份量、配料怎么落地南京小吃里“鸭血粉丝汤”你得分小碗/大碗辣度要选不辣/微辣/中辣/特辣“盐水鸭”要选整只/半只/前脯/后腿“汤包”要选鲜肉/蟹黄。这些需求本质上是一回事一个商品下挂多个SKU。我的建议是导航到product_sku表用spec_name字段存放规格描述例如“小碗 微辣 鸭肠加量”。规格和价格、库存绑定之后购物车、订单明细的product_name和spec_name都要在生成订单那一刻“快照”下来。什么意思就是订单明细表里不仅要存商品ID还要冗余一份当时的商品名称、规格描述、单价。因为下单后商家可能改商品名、改价格如果订单表只存ID历史订单显示就会错乱。快照是电商系统的常识写在论文里也很加分。4.2 配送与自提本地小吃的两种履约方式南京美食商城如果完全照抄通用电商的“快递发货”会显得场景割裂。更好的是同时支持两种履约方式同城配送计算配送费设置起送价如满30元起送配送费5元。到店自提免运费可设置“预计自提时间”。实现上很简单orders表加一个delivery_type字段1表示配送2表示自提再根据类型展示不同的费用和提示语。如果要做细地址表里加一个shop_id关联对应的线下门店这样自提场景下用户可以选择具体门店。这部分在论文需求分析中非常出彩因为你抓住了“本地美食小吃商城”和“通用电商平台”的差异点——前者的履约半径短形态灵活。答辩时可以回答“为什么不做跨省物流”因为场景定位就是同城消费这个回答很站得住脚。4.3 优惠券与满减让订单总价计算不露怯优惠券也是商城标配。不要小看这个模块很多同学的订单计算逻辑就是“商品总价运费”一加优惠券就乱了。我建议至少支持两类优惠券满减券满30减5、满50减10无门槛券新客立减3元用户领券后进入“我的卡券”页面下单时勾选可用优惠券计算逻辑是应付金额 商品总金额 配送费 - 优惠券抵扣 实付金额 应付金额大于0才允许支付注意一个边界情况优惠券的condition_amount判断应该基于商品总金额不含配送费否则会出现“用5元券把单子减到负数的”尴尬。这个细节在代码注释里写明白论文系统设计里也能提一笔。4.4 首页推荐与主题分类让项目有“美食味”同样是商品列表页“南京特色美食小吃商城”的首页应该有自己的辨识度。建议做几个东西轮播图Banner管理后台可配置前台首页展示“招牌盐水鸭”“秋季滋补汤包”等促销图。分类导航热菜卤味、汤羹粉丝、甜品糕点、小吃面点、零食伴手礼。推荐商品recommend字段标记推荐位首页固定展示8个左右。这些功能看起来简单但能把项目从“裸奔的商品列表”提升到“像样子的商城首页”。更重要的是它们需要建Banner表和推荐位字段论文的系统设计部分又多了一章可写的内容。5. 核心接口实现与前后端交互的几个关键点这一章说说真正写代码时那些“绕过不去的坎”以及我推荐的最佳实现路径。5.1 登录鉴权拦截器比Shiro更适合这个项目很多教程一上来就是Spring Security、Shiro但对毕业设计来说这些框架配置繁琐且难以讲清楚内部原理。我的建议是用拦截器 Session实现登录控制代码量不大逻辑一眼就能看懂。先写一个LoginInterceptorpublic class LoginInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { Object user request.getSession().getAttribute(loginUser); if (user null) { // 判断是否AJAX请求 String requestedWith request.getHeader(X-Requested-With); if (XMLHttpRequest.equals(requestedWith)) { response.setContentType(application/json;charsetUTF-8); response.getWriter().write({\code\:401,\msg\:\未登录\}); } else { response.sendRedirect(/login); } return false; } return true; } }然后注册到WebMvc配置中并放行登录页、静态资源、商品列表等公开接口Configuration public class WebMvcConfig implements WebMvcConfigurer { Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LoginInterceptor()) .addPathPatterns(/**) .excludePathPatterns( /login, /register, /product/**, /category/**, /css/**, /js/**, /images/**, /error ); } }这样用户访问/cart、/order等需要登录的页面时会自动跳转登录页而商品列表、详情这类公开页面游客也能看。为什么这样设计因为商城让游客浏览是本分但购物车和订单必须登录这是业务边界问题。顺便说一下密码存储。别用MD5直接存建议用BCryptPasswordEncoder加盐哈希Spring Security虽然没整体引入但单独引spring-security-crypto包也能用String encoded new BCryptPasswordEncoder().encode(rawPassword); boolean matches new BCryptPasswordEncoder().matches(rawPassword, encoded);答辩时有人问“密码怎么存储”你就可以答使用BCrypt加盐哈希即使数据库泄露明文密码也无法被直接还原。这个意识非常加分。5.2 购物车与订单提交的事务边界购物车接口相对简单难点在于“提交订单”。这个操作涉及多个表必须开启事务Transactional(rollbackFor Exception.class) Override public String createOrder(OrderCreateDTO dto) { // 1. 遍历购物车选中项校验商品状态与库存 // 2. 计算商品总金额、配送费、优惠券抵扣 // 3. 生成订单号插入订单表 // 4. 插入订单明细表 // 5. 扣减SKU库存、增加商品销量 // 6. 删除对应购物车记录 // 7. 核销优惠券 // 8. 返回订单号 }订单号生成要单独说一句。不要用时间戳随机数这种简单方案并发场景容易重号。我推荐“日期 用户ID 随机数”拼接再加一个数据库唯一索引兜底。示例public static String generateOrderNo(Long userId) { String date LocalDate.now().format(DateTimeFormatter.ofPattern(yyyyMMdd)); String random String.format(%04d, ThreadLocalRandom.current().nextInt(10000)); return date String.format(%06d, userId % 1000000) random; }这样生成的订单号长度固定便于打印在订单页和论文截图里。5.3 图片上传与本地存储的踩坑笔记商城后台必然要上传商品图片。最稳妥、演示不依赖外网的方案是本地目录存储file: upload-path: D:/nanjing-food-upload/ access-path: /upload/**配置类里把本地目录映射到访问路径Override public void addResourceHandlers(ResourceHandlerRegistry registry) { String uploadPath fileProperties.getUploadPath(); registry.addResourceHandler(/upload/**) .addResourceLocations(file: uploadPath); }这里有几个坑要注意。第一个Windows路径末尾要加file:前缀Linux路径同理第二个上传时重命名文件不要用用户上传的原始文件名否则中文名、特殊字符会引发乱码或安全风险建议用UUIDString ext originalFilename.substring(originalFilename.lastIndexOf(.)); String newName UUID.randomUUID().toString().replace(-, ) ext;第三个上传接口要限制文件类型和大小SpringBoot默认单文件上传上限1MB可以在配置里放开spring: servlet: multipart: max-file-size: 10MB max-request-size: 20MB光放开还不够代码里还是要校验扩展名只允许jpg、png、webp等图片格式。原因很简单防止用户上传一个exe或者jsp文件虽然本地演示一般没事但这个安全意识要写进代码里。5.4 支付模块沙箱支付与模拟支付的取舍支付是商城项目的核心但也是很多毕业设计的“翻车重灾区”。最靠谱的两种做法一种是不接真实支付做一个模拟支付页面展示订单金额点击“确认支付”后直接把订单状态从0改成1同时记录支付时间。这样项目闭环完整又避免申请沙箱账号的流程。适合时间紧、不想折腾的同学。另一种是接入支付宝沙箱环境。支付宝开放平台有沙箱环境用测试账号能真实走一遍下单、跳转支付宝、异步回调的流程。这个做法的好处是论文里能写“接入支付宝V3异步通知验签机制”含金量完全不同。但要注意沙箱账号有效期、公钥私钥配置、回调地址必须能被外网访问内网穿透或者部署到云服务器这一步很容易卡住人。如果工期有限我的建议是先做模拟支付保证闭环有余力再替换沙箱支付。答辩时实话实说“为演示便捷当前使用模拟支付但接口层已预留支付宝沙箱对接能力”比硬着头皮说接了沙箱却现场失败强得多。6. 开发期高频报错与排查思路接下来的内容是我在指导这个项目过程中遇到最多的运行期问题按“现象—归因—方案—验证”的方式写你照着排查基本一两小时内能解决。6.1 应用启动失败Bean注入、端口占用、数据库连不上先分清报错类型。如果是Field xxxMapper in com... required a bean of type...这类错误通常是Mapper层没有扫描到。解决方案启动类加MapperScan(com.nanjing.food.mapper)或者每个Mapper接口加Mapper注解。注意包路径必须正确否则代码里看似没问题启动就崩。如果是Port 8080 was already in use说明端口被占。Windows下执行netstat -ano | findstr 8080查出PID后taskkill /F /PID 进程号嫌麻烦也可以改端口server: port: 8081如果是Access denied for user rootlocalhost那就是数据库账号密码不对或者MySQL服务没启动。一个隐蔽的坑是MySQL 8.0的认证插件问题连接串里加allowPublicKeyRetrievaltrue能解决大部分类似Public Key Retrieval is not allowed的报错。6.2 Thymeleaf模板报错页面里写错了表达式用Thymeleaf时最常见两类错一类是变量不存在th:text${product.name}但后台没有传product另一类是语法错误比如${product.isRecommend}而实体类字段名为recommendMyBatis-Plus驼峰映射虽然能处理但Thymeleaf解析时短路了。排查思路很简单看控制台异常栈里的行号然后检查对应HTML片段。一个建议是如果某个商品详情页加载特别慢很可能是详情大图没压缩本地文件还在可接受范围。页面展示图片路径要写成相对路径/upload/xxx.jpg不要写成D:/nanjing-food-upload/xxx.jpg否则部署到其他电脑后路径全断。6.3 前后端分离的跨域问题如果你最终选了Vue SpringBoot分离方案跨域几乎是必然遇到的。SpringBoot处理CORS最简单的方式是加一个配置类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); } }注意allowCredentials(true)时allowedOriginPatterns不能用*要写全匹配模式否则部分浏览器会直接拦截响应。另外如果用了拦截器OPTIONS预检请求会先被拦截需要在拦截器里放行OPTIONS方法否则前端报“CORS error”且控制台看不到真实原因。6.4 Maven依赖缺失IDEA里爆红怎么办刚克隆一个项目或导入源码时IDEA里一片红色是常态。处理顺序确认Maven仓库路径正确settings.xml里的镜像源可以换成阿里云镜像解决依赖下载慢或失败。在IDEA右侧Maven面板点一次Reload All Projects。如果某个依赖版本号标红打开pom.xml检查依赖坐标是否写错以及版本是否与SpringBoot版本兼容。检查lombok是否使用了IDEA插件支持。Lombok版本与JDK版本不匹配时Data注解不生效实体类就是一堆编译错误。顺带提醒不要一股脑把所有依赖都加进来。每加一个spring-boot-starter-*都想想是不是真的需要。依赖越多启动越慢冲突概率越大论文中技术栈部分也越难讲清楚。7. 论文结构、源码管理与答辩应答策略代码跑通了项目只算完成一半。毕业设计的另一半是论文和答辩。这里我把论文怎么写、答辩怎么答的实战经验一并交代清楚。7.1 论文目录怎么安排才跟代码呼应标准软件工程类论文目录可以这样定绪论背景与意义、国内外研究现状、论文组织结构相关技术介绍SpringBoot、MyBatis-Plus、Thymeleaf、MySQL各一段重点说为什么选它系统分析可行性分析、功能性需求分析用例表、非功能性需求分析系统设计总体架构、功能模块划分、数据库设计E-R图、表结构、接口设计系统实现按模块贴关键代码和截图每个模块配一段说明系统测试功能测试用例表、测试结果、缺陷修复记录总结与展望这里要特别提醒论文里的每张图、每段代码都要能从你的项目里找到出处。答辩老师最敏感的就是“图文不符”。比如数据库设计章节贴的表结构必须和你项目里的建表SQL一致系统实现章节贴的功能截图必须是你刚刚在现场跑出来的效果。建议开发过程中顺手截图存档写论文时按图索骥效率翻倍。7.2 UML图怎么画才不算“照搬教材”需求分析阶段至少要有三张图用例图、实体关系图E-R图、系统架构图或功能结构图。不用太复杂把角色和功能权限画清楚就行。用例图建议包含两个角色游客/用户和管理员。用户用例包括注册登录、浏览商品、搜索商品、加入购物车、下单支付、查看订单、收货评价管理员用例包括登录、商品管理、分类管理、订单管理、用户管理、优惠券管理、轮播图管理。这样一张用例图画下来工作量和业务边界一目了然。E-R图里把用户、商品、分类、SKU、购物车、订单、订单明细、优惠券这些实体以及它们的联系画出来重点体现orders与order_item的一对多关系、product与product_sku的一对多关系。画好这张图数据库设计章节基本就稳了。架构图的话画一个三层的表现层Thymeleaf页面/JSON接口→ 业务层Service→ 持久层Mapper / MySQL。不用画成微服务那种花哨的老老实实分“表现层-业务层-数据层”就是最安全的。7.3 答辩时的高频问题与应答思路答辩问题通常围绕“为什么”和“怎么办”展开。我把高频问题及答案思路整理成一张表高频问题应答思路为什么选择SpringBoot简化配置、内嵌容器、自动装配、生态丰富对比传统SSM需要大量XML配置提高开发效率IoC和AOP是什么在你的项目里用在哪IoC是控制反转对象创建交给容器管理AOP是面向切面编程我用在事务管理和日志记录上数据库为什么这样设计业务上围绕“商品—SKU—购物车—订单—订单明细”这条链路建模订单明细做了数据快照保证历史订单稳定订单超时未支付怎么处理方案一定时任务扫描超时订单并自动取消方案二使用延时队列或RabbitMQ延迟消息。毕设中可用Spring Scheduled定时扫描库存并发超卖怎么解决使用乐观锁版本号控制每次更新校验版本号进一步可引入Redis预扣减但明确说明毕设选用乐观锁简单可靠支付安全性怎么保证模拟支付说明自己预留沙箱对接能力如已接沙箱则回答使用了异步通知验签机制防止伪造通知测试用例怎么设计按业务模块设计正常流程、异常流程、边界值用例现场演示几个典型用例注意事项回答时不要背概念要结合自己的代码说。比如被问到AOP就说“我在订单提交时使用Transactional声明式事务以及我把日志切面抽出来统一记录用户操作”这种回答一听就是亲手写过的。7.4 源码管理从第一天就养成好习惯最后说说源码和论文打包这件事。很多同学到交项目时才把整个文件夹用微信传一遍文件名是“新建文件夹(3)”,里面既有target目录、又有.idea目录答辩老师看着都头大。建议做好三件事第一项目一开始就放进Git仓库。本地用Git或Gitee建个私有仓库每次改完关键功能就commit写论文时翻提交记录能回忆起每个阶段的实现细节。第二写README.md把项目简介、技术栈、运行步骤导入数据库、改配置、启动、默认账号密码写清楚。这一步看起来不起眼但对答辩演示的老师来说非常友好也让你的项目看起来像一个规范的工程。第三精简交付包删掉target目录和.idea目录附上数据库SQL脚本和一个“部署说明.docx”这就是一份完整、体面的源码包。我个人在实际操作中的体会是毕业设计最怕的不是技术难而是“想做太多”和“没有留痕”。把核心链路做闭环挑两三个亮点做深从第一天就同步写文档和截图到最后答辩时会非常从容。这篇博文覆盖了从技术选型、数据库建模、核心业务落地的完整链路如果你照着搭完跑通了后面遇到的大部分问题也都能在文中的排查思路里找到答案。