
1. 项目概述1.1 核心需求解析先说结论springboot_ssm823烘焙美食爱好者分享网站这个标题一眼就能看出是典型的Java Web方向毕业设计或课程设计选题。项目编号后缀是常见选题列表里的排序不用特别在意。技术组合为Spring Boot SSMSpring、SpringMVC、MyBatis业务落点是一个面向烘焙人群的内容分享社区——用户可以在网站上发布自己的烘焙作品、浏览他人的配方教程、点赞评论互动同时管理员可以在后台对内容进行审核与管理。这类项目在毕业设计里出现频率极高因为它在“难度可控”和“完整性达标”之间找到了一个非常舒服的平衡点不是简单到像课设作业也不会难到让人在答辩前崩溃。从技术栈的角度看SSM是很多高校Java课程的核心内容Spring Boot又是当前企业招聘简历上出镜率最高的关键词之一。两者结合既能在论文里讲清楚框架原理又能在演示时流畅跑通属于评委喜欢、学生能做出来的务实组合。同时把业务领域选在“烘焙美食爱好者分享”而非泛泛的“内容分享平台”是一个值得肯定的决策。垂直领域意味着业务逻辑可以被细化出更多真实的功能需求用户需要一个作品库管理自己的烘焙记录需要按品类面包、蛋糕、饼干、甜品筛选内容需要记录配方、用料、步骤、耗时等结构化字段。这些字段让数据库设计有内容可写让论文第三、第四章有细节可展开也让答辩时应对“为什么这样设计”之类的提问更有底气。1.2 这个项目能解决什么问题从用户侧看烘焙爱好者最原始的需求是“记录与分享”做出一款满意的作品需要一个地方发布照片、写下方子、记录烤箱温度和时间然后等着其他同好来交流。这个项目解决的正是“分享内容的结构化沉淀”问题——不是朋友圈式的一闪而过而是可以分类检索、长期留存、形成个人页面的作品集合。从开发者侧看这个项目解决的是“完整走通一个Web业务系统”的训练问题。相比纯理论刷题做一个能跑起来的真实系统你会在开发过程中碰到数据库字段设计是否合理、图片上传后如何回显、分页查询性能如何优化、用户登录态如何保持这类教科书不会直接告诉你的实际问题。这些经历在找工作面试时比任何背诵的知识点都管用。适合什么人参考这份拆解正在准备选题的学生、拿到了类似题目但对整体实现路径不清晰的同学以及想快速了解SSM整合项目里“哪些功能最容易被问到、哪些环节最容易踩坑”的开发者。下面我按真实开发顺序把整个项目完整拆开讲每一步都尽量结合我实际写过的类似项目经验来说。2. 技术选型背后的取舍逻辑2.1 Spring Boot SSM究竟是怎样的组合严格来说SSM是指Spring SpringMVC MyBatis三件套而Spring Boot是在这三者之上的“胶水和加速器”。Spring负责对象管理和依赖注入SpringMVC负责HTTP请求的路由与分发MyBatis负责Java对象与数据库表之间的交互。Spring Boot则提供了自动配置能力把过去需要手写的一大堆XML配置收敛成了极简的配置项。用生活化的方式理解SpringMVC是前台接待员所有请求进来都由它负责引导到对应的处理人员手里Spring是后勤总管哪个处理器需要数据库操作对象哪个服务需要注入另一个服务都由它统一装配管理MyBatis是数据专员专门负责把Java里的对象信息写入数据库表里或者把表的记录查询出来组装成对象。Spring Boot的作用则像是给整个办公室装了自动化系统不需要你亲自去拉网线、配工位、装系统打开电源就能直接用。用Spring Boot整合SSM的技术路线核心优势有三个降低配置成本。数据库连接池、事务管理器、视图解析器这些传统SSM项目里需要手工配置的组件Spring Boot大多能自动装配只需要在application.yml里写几行数据源参数即可。方便内嵌服务器运行。传统SSM项目需要把应用打成WAR包扔进独立的Tomcat才能跑Spring Boot内置了Tomcat直接执行java -jar就能启动演示答辩时大大减少了部署环节翻车的概率。生态兼容性好。Spring Boot对SSM的整合有官方或社区成熟方案遇到问题搜索解决方案命中率高这一点对项目周期紧张的学生来说非常实际。也有同学问过为什么不直接用Spring Boot JPA或者干脆上微服务答案很简单课程里讲的是SSM答辩老师熟悉的是SSM网上面试问的也是SSM底层的IoC和AOP概念。JPA虽然写代码更少但知识体系与SSM差异较大很容易在答辩时被问住。微服务则完全超出这个项目的合理规模属于用八倍镜打蚊子还给自己添麻烦。2.2 为什么不选择前后端分离架构现在很多企业项目已经走前后端分离路线前端用Vue或React后端纯接口化。那这个项目为什么不建议这么做因为在毕业设计/课程设计的答辩场景里核心评价维度是“能否讲清楚一个完整系统的结构和原理”。单体架构下的前后端在一起部署、Session直接共享整个数据流转链路清晰直观论文里画架构图、时序图都非常好表述。如果拆成前后端分离你就得额外讲清楚跨域处理、Token鉴权、前端构建部署、Nginx反向代理这一堆内容。不是做不到而是对于以“分享网站”为核心的项目来说这些工作量会让论文重点偏移到非核心内容上而且答辩时多了一大片容易被追问的地带。前后端不分离也有一个实践上的好处调试简单。页面渲染由服务端模板引擎如Thymeleaf直接完成后端把数据塞进Model传给页面浏览器刷新就能看到结果。调试连接数据库的接口时不需要额外启动一个前端开发服务器也不用处理接口联调时的参数对齐问题。对一个人完成全部开发任务的场景来说单体结构能让你把精力集中在业务功能本身的实现上而不是消耗在前端脚手架的搭建上。2.3 开发环境与工具清单参考JDK版本建议JDK 8或JDK 11。这两个版本对Spring Boot 2.x支持最好网上能找到的问题解决方案也最多。JDK 17虽然也可以跑但某些老版本的MyBatis或连接池组件可能有兼容性小坑不必冒险。数据库MySQL 5.7或8.0均可。注意8.0的驱动类名和连接URL参数与5.7略有差异驱动要选mysql-connector-java或com.mysql.cj.jdbc.Driver对应的版本。IDEIntelliJ IDEA社区版或Eclipse都可以IDEA对Spring Boot的注解支持和自动补全更友好推荐优先选它。构建工具Maven。直接用Spring Initializr生成项目骨架减少手工维护依赖版本的工作量。前端模板Thymeleaf服务端渲染配合Bootstrap jQuery几行代码就能做出漂亮的后台界面且Bootstrap的栅格布局对响应式支持好演示时屏幕适配效果好。项目管理辅助Navicat或DataGrip用于查看数据库表结构、执行SQL脚本调试时比命令行直观得多。提示工具版本别追求最新。如果你用的是Spring Boot 2.3.x就别硬上Spring Boot 3.x的教程代码注解包路径都有变化照抄会踩到无用功的坑。3. 系统功能模块与数据库设计3.1 用户视角下的功能模块边界“分享网站”这个词听起来简单但实际展开后功能其实相当完整。按角色区分普通用户与管理员看到的内容完全不同。普通用户的功能边界游客浏览首页推荐作品、查看作品详情、按品类浏览、查看公告但无法点赞评论和发布内容。注册用户在游客能力之上增加评论、点赞、收藏、关注其他用户、发布新作品、编辑或删除自己的作品、修改个人资料、查看个人主页。一个有“作品数”和“获赞数”统计的用户主页是这个项目相较于普通CRUD系统最亮眼的地方答辩提问时此功能很容易引发关注。管理员的功能边界用户管理查看注册用户列表禁用/启用违规账号。作品管理对用户发布的作品进行审核、下架或删除置顶推荐优质作品。分类管理维护烘焙品类的增删改查面包类、蛋糕类、饼干类等。评论管理删除不当评论。公告管理发布和维护系统公告。功能域划分的原则是“信息隔离但数据打通”用户产生的作品、评论、点赞数据通过外键关联到同一套核心表上但管理端只读不修改用户创作内容下架从业务逻辑上删除前台展示而非物理删除记录保证数据的完整性和可追溯性。3.2 数据表设计是论文里的重头戏数据库设计决定了整个项目的上限。表设计不合理后面写SQL和MyBatis映射时会不断返工每一步都艰难。我建议直接按“用户、作品、互动、辅助”四大块来拆表。核心表至少要有这六张表名用途说明关键字段注意事项user用户信息表id主键自增username加唯一索引password存BCrypt加密串avatar存储头像图片路径status用0/1表示正常/禁用create_time记录注册时间category烘焙品类表id、name、description、sort_order控制显示顺序post作品/分享内容表user_id外键关联用户category_id外键关联分类title、content、cover_image封面图、images多图路径可用逗号分隔或另建图片表、difficulty难度等级1-3、duration耗时分钟数、like_count、comment_count冗余计数、status0待审核 1正常 2下架、create_time、update_timecomment评论表id、post_id、user_id、content、create_time组合索引(post_id, create_time)加速查询like_record点赞记录表id、post_id、user_id、create_time给(post_id, user_id)加唯一约束防止同一个人重复点赞notice公告表id、title、content、create_time、status要不要设计收藏表和关注表如果时间充足建议加。收藏表结构与点赞表类似字段多一个post_id user_id唯一约束关注表则是user_id粉丝与follow_user_id被关注者的组合唯一约束。加这两张表能让个人主页的数据丰富度显著上升论文功能模块部分也更有看头。但如果时间非常紧张可以像其他类似项目一样采取简化策略先保证核心流程完全跑通再扩充。数据库设计里最大的坑是“冗余计数与真实数据不一致”like_count字段在点赞记录插入时加1取消点赞时减1。这里必须用事务控制否则并发情况下计数很容易错乱。一个稳妥做法是在Service层把插入点赞记录和更新post.like_count放在同一个Transactional方法里任何一步失败都回滚。这个细节答辩时讲出来是有加分效果的。3.3 MyBatis映射与多表联查的边界SSM整合后MyBatis负责所有SQL操作。单表查询简单真正体现设计能力的是带条件的分页查询和一对多嵌套查询。作品列表页常见查询场景首页推荐SELECT * FROM post WHERE status 1 ORDER BY like_count DESC, create_time DESC LIMIT offset, size按分类筛选SELECT * FROM post WHERE category_id #{categoryId} AND status 1 ORDER BY create_time DESC LIMIT offset, size个人主页作品SELECT * FROM post WHERE user_id #{userId} ORDER BY create_time DESC LIMIT offset, size关键字搜索SELECT * FROM post WHERE title LIKE CONCAT(%, #{keyword}, %) AND status 1作品详情页则涉及三张表关联查询作品基本信息时联查用户昵称和头像user表查询评论区时联查评论者信息user表统计作品总获赞数可能还要聚合like_record表。在实际编码时需要注意MyBatis的resultMap里如果配置了嵌套collection用于加载评论列表会出现经典的N1查询问题先查1条主记录再根据外键逐条查N条关联记录性能较差。但如果评论数据量有限比如单个作品评论不超过几十条这个问题的实际影响并不大不需要为了性能硬拆两条查询语句。如果非要做得讲究一点可以在Service层先查作品列表、再根据作品ID集合查评论并手动组装到对象里这就是所谓的“手动分片组装”方式比MyBatis嵌套更可控。提示如果论文里写了“基于MyBatis实现了高效的数据访问”就一定要能在答辩时讲清楚自己是怎么处理多表查询的别只背概念。4. 核心功能实现与实操要点4.1 注册登录模块安全细节不能省注册模块看起来是最基础的CRUD但安全相关的细节一定要做对否则项目会被答辩老师一句话问穿。密码绝不能明文存储。这里使用Spring Security的BCryptPasswordEncoder不需要引入完整Spring Security框架只引spring-security-crypto依赖即可。注册时对明文密码做encode()登录校验时用matches()方法比对。BCrypt算法自带随机盐相同明文每次加密结果都不同这一点比MD5加固定盐更安全。某次答辩现场评委直接问“用户名密码在数据库怎么存的”回答“BCrypt加密”比“MD5加密”要稳妥得多。登录态保持可以用最简单的Session方案。用户登录成功后把用户ID和用户名塞进Session在后端写一个拦截器HandlerInterceptor对需要登录才能访问的接口路径做拦截校验未登录用户统一重定向到登录页。这个方案理解成本低、代码量少、答辩好讲述。不推荐在单体非前后端分离项目里为了显得高级强行使用JWT——既要自己处理过期和续期逻辑又无法利用Session天然的服务端失效机制属于吃力不讨好。注册页面的基础校验建议前后端都做前端用jQuery校验非空和格式后端再用Valid注解或手工校验兜底。后端的校验才是真正的安全防线前端校验只是优化体验。4.2 作品发布与图片上传最容易踩坑的环节图片上传堪称此类项目的头号事故高发区我见过太多因为图片问题导致演示翻车的案例。最常见的症状是本地上传成功换电脑跑项目后图片全部裂开或者部署到服务器后上传目录找不到、图片无法回显。解决方案是统一规范图片存储路径削除环境差异。建议在项目配置文件中约定一个外部存储目录比如Windows下的D:/upload/或Linux下的/usr/local/upload/不同操作系统下只改一行配置就能切换。上传时把图片写入这个目录数据库里存的是“文件相对路径”例如/images/post/2024/05/20/uuid.jpg页面通过自定义的/images/**静态资源映射来访问这个目录。设置图片大小限制也很关键。开发阶段可能觉得无所谓但上线或提交后换环境很容易出问题。Spring Boot默认上传文件最大1MB如果用户上传一张手机拍摄的3MB照片会被直接拒绝。所以务必要在application.yml里配置spring: servlet: multipart: max-file-size: 10MB max-request-size: 20MB文件命名上强烈推荐用UUID.randomUUID().toString()拼上原文件后缀避免中文文件名和重名覆盖问题。中文文件名在部分浏览器和Tomcat版本下会触发编码问题重名则会直接覆盖两个坑一次性规避。对应核心代码示意Controller层PostMapping(/publish) public String publish(RequestParam(title) String title, RequestParam(content) String content, RequestParam(categoryId) Integer categoryId, RequestParam(file) MultipartFile file, HttpSession session) { // 校验登录态 User user (User) session.getAttribute(loginUser); if (user null) { return redirect:/login; } // 保存图片 String fileName UUID.randomUUID().toString() .replace(-, ) getExt(file.getOriginalFilename()); String datePath new SimpleDateFormat(yyyy/MM/dd).format(new Date()); String filePath uploadDir / datePath / fileName; File dest new File(filePath); if (!dest.getParentFile().exists()) { dest.getParentFile().mkdirs(); } file.transferTo(dest); // 组装作品对象塞入数据库 Post post new Post(); post.setTitle(title); post.setContent(content); post.setCategoryId(categoryId); post.setUserId(user.getId()); post.setCoverImage(/images/ datePath / fileName); post.setStatus(1); // 默认审核通过 post.setCreateTime(new Date()); postService.addPost(post); return redirect:/post/detail/ post.getId(); }可以看到图片保存逻辑和作品入库逻辑都在同一个方法里如果数据库入库失败图片就会成为残留孤儿文件。严谨的做法是捕获异常后删除已写入的文件或者在投稿成功前只把图片暂存到临时目录。对于毕业设计级别的系统捕获异常后删除文件这一个加强点就值得写进论文里显摆一下了。4.3 评论与点赞模块业务逻辑的隐藏难点评论功能比较简单插入一条记录再更新post.comment_count即可。前端展示按时间正序排列符合浏览习惯。点赞功能要警惕的点是同一个用户对同一作品反复点赞导致的计数膨胀。用like_record表的唯一约束来保证业务逻辑正确性然后先查后插或者直接尝试插入遇到重复键异常就执行取消点赞逻辑代码见下Transactional public boolean toggleLike(Integer postId, Integer userId) { LikeRecord record likeRecordMapper.findByPostIdAndUserId(postId, userId); if (record null) { // 点赞 LikeRecord newRecord new LikeRecord(); newRecord.setPostId(postId); newRecord.setUserId(userId); newRecord.setCreateTime(new Date()); likeRecordMapper.insert(newRecord); postMapper.increaseLikeCount(postId); return true; } else { // 取消点赞 likeRecordMapper.deleteByPostIdAndUserId(postId, userId); postMapper.decreaseLikeCount(postId); return false; } }这段代码必须加Transactional否则“插入点赞记录成功但更新计数失败”这种半个成功半个失败的情况就会破坏数据一致性。另外取消点赞也可以做成物理删除记录因为用户无需查看自己的历史点赞记录保留反而会造成唯一约束冲突处理的复杂度上升。前端交互上点赞按钮点击后局部刷新点赞数可以用jQuery的$.post()异步调接口然后在回调里更新按钮样式和数字。这一点虽然只是个小优化但在用户体验上比整页刷新要舒服得多答辩演示时也显得专业。4.4 首页动态流与分页查询首页是整个网站的门面展示方式建议顶部一条轮播公告中间是分类导航下面是按发布时间倒序排列的最新作品瀑布流。瀑布流可以用Bootstrap的卡片式布局实现注意图片高度不一致时给卡片一个固定高度并设置object-fit: cover防止布局错乱。分页查询使用PageHelper插件非常合适引入依赖后在Service层直接调用PageHelper.startPage(pageNum, pageSize); ListPostVO list postMapper.selectLatestPosts(); PageInfoPostVO pageInfo new PageInfo(list);PageHelper通过拦截器自动在SQL语句后面拼接LIMIT返回值自动封装成带分页信息的PageInfo前端通过pageInfo.getList()和pageInfo.getPageNum()、pageInfo.getPages()等字段渲染分页条。这个插件简单易用、看着又很有技术含量论文里可以写“引入分页插件实现了高性能的分页查询”答辩时也能讲明白原理。需要注意一个坑在使用PageHelper时必须确保PageHelper.startPage()之后紧跟着的第一次查询就是要分页的那条SQL如果中间插了其他数据库查询分页参数就会被错误消费到另外的查询上导致分页失效。5. 论文撰写的思路与重点章节5.1 论文立意别写成流水账这篇论文的题目如果直接叫“基于Spring Boot和SSM的烘焙美食爱好者分享网站设计与实现”那么整篇论文的骨架建议围绕“垂直领域内容社区”这一特异性来组织。不是泛泛而谈做了一个网站而是聚焦于“如何围绕烘焙作品分享场景搭建一个具备内容发布、互动反馈、分类检索能力的社区系统”。论文的目录结构我推荐这样安排第一章 绪论背景与意义烘焙爱好者线上分享需求增长垂直社区的价值国内外研究现状一句话带过不要编造具体系统名称主要工作内容。第二章 相关技术介绍Spring、SpringMVC、MyBatis、Spring Boot、MySQL、Thymeleaf。这部分答辩最常见每个技术写清楚核心特性即可。第三章 系统需求分析与总体设计可行性分析、功能需求分析用例图配合文字说明、非功能需求分析、系统架构设计、功能模块划分、数据库设计ER图和表结构说明。第四章 系统详细设计与实现按“用户登录注册模块”“作品发布与图片上传模块”“评论点赞模块”“后台管理模块”逐一展开。每个模块要有“功能设计→流程设计→核心代码→实现效果截图”的结构。第五章 系统测试测试环境、功能测试用例表、测试结果分析。第六章 总结与展望做得好的地方一句话带过展望要写实际可行的功能扩展方向比如推荐算法、消息通知等。5.2 论文里必须重点展开的三个地方按答辩提问概率排序最需要写透的是三个点。第一数据库设计的合理性分析。每张表为什么这样设计、主外键关系如何维护、为什么用冗余计数而不用实时聚合、为什么给点赞表加联合唯一索引这些都是有话可说的细节。我建议在论文的第三章放一张完整的数据库表结构说明表包含字段名、类型、约束和说明这是工作量最直观的体现。第二图片上传存储方案的实现细节。从MultipartFile接收文件、UUID生成文件名、按日期分目录存储、静态资源映射到外部目录、数据库只存相对路径这样一个完整的链路讲下来技术深度已经完全超出平均水平。最好再把“本地上传目录与项目解耦”的设计意图说明白答辩老师很吃这一套。第三评论点赞模块的并发一致性思考。用唯一约束保证点赞幂等性用事务保证计数与记录的一致性必要时画一张点赞功能流程图或者时序图。可以坦率地说明单体本地事务已经满足该场景的一致性需求这样就显得既有技术思考又不过度设计。5.3 论文写作的节奏建议先写第三章和第四章因为这两章内容最实写起来心里有底。写完核心章节再回头补第一、二章最后写第五章测试。第一、二章如果放在最后写往往会因为前期素材充足而顺畅很多也能避免一开始就陷入抄概念的泥潭。论文配图多用自己系统运行时的截图比如首页轮播图效果、登录页面、作品发布页面、个人主页页面、后台管理页面。用图画说话最有说服力。系统架构图建议用Visio或draw.io画分层架构图从上到下依次是视图层、控制层、业务层、数据访问层清晰干净即可。注意论文里的核心代码不要大段贴ControllerMapper全部代码只贴关键方法的代码片段并配合文字解释逻辑即可。论文重点在于“设计思路”而非“代码搬运”。6. 常见问题与调试排错实录6.1 数据库连不上的问题新启动项目时报Cannot create PoolableConnectionFactory或者Access denied for user基本都是连接配置问题。逐一排查MySQL服务是否启动用户名密码是否正确数据库是否已创建CREATE DATABASE语句执行过连接URL中的characterEncodingutf8和serverTimezoneAsia/Shanghai是否配置齐全尤其是MySQL 8.0版本时区参数缺失会直接连接失败。6.2 页面样式丢失、静态资源404Thymeleaf模板页面能打开但CSS和JS全部失效多半是静态资源配置问题。Spring Boot默认会处理/static/目录下的静态资源页面中引用时注意路径写法是/css/style.css而不是css/style.css少了前导斜杠可能导致相对路径解析错误。另外如果配置了自定义拦截器一定要放行静态资源路径否则拦截器会先把CSS和JS请求拦住导致资源加载失败。6.3 图片上传后访问404这是一类非常常见的问题。先确认图片是否真的写入了磁盘目录再确认数据库存的路径是否正确最后确认自定义静态资源映射是否配置成功。Configuration public class WebConfig implements WebMvcConfigurer { Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler(/images/**) .addResourceLocations(file: uploadDir /); } }这里的uploadDir要保证末尾带斜杠并且是绝对路径。Windows下用file:D:/upload/Linux下用file:/usr/local/upload/。踩过最隐蔽的坑是路径中包含空格导致映射失败比如D:/My Project/upload/一定要用Path类或Paths.get()来拼路径减少字符串拼接的坑。6.4 中文乱码开发环境一切正常部署后页面中文变问号大概率是数据库连接URL缺少characterEncodingutf8参数或者数据库/表本身的字符集不是utf8mb4。创建表时建议统一CREATE DATABASE baking_share DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;同时IDEA里把项目编码、Tomcat运行参数-Dfile.encodingUTF-8也一并设置好。6.5 MyBatis懒加载异常如果配置了lazyLoadingEnabledtrue在Service层返回对象后又在Controller层访问关联属性容易抛LazyInitializationException原因是在Session关闭后尝试加载懒对象。解决办法有三个关闭懒加载在Service层方法上加Transactional确保Session存活或者干脆用一条联查SQL把需要的数据全部查出来。对毕业设计项目直接关闭懒加载或者用联查最省心。6.6 项目启动报端口被占用改application.yml里的server.port换一个端口或者执行netstat -ano | findstr 8080查出占用进程后结束。演示前务必确认当前端口没被占用否则现场启动失败会非常尴尬。7. 最后的几点个人体会烘焙美食爱好者分享网站在毕业设计里算是一个看起来很“软”但做起来很“硬”的选题。它不像纯后台管理系统那样功能直白也不像社交App那样对交互要求极高它处在中间位置既有足够丰富的业务场景让你把CRUD做得有层次又不需要在分布式、缓存、消息队列这些方向上硬凑技术。这种取舍对一个想扎实走完一遍开发流程的学生来说本身就是很健康的选择。我个人在带类似项目的过程中发现真正把时间消耗掉的地方往往不是功能本身的设计而是环境问题、上传文件路径问题、以及改代码后没有重启导致的“奇怪现象”。所以想给大家几个实在建议第一数据库连接参数一次配好后就别反复改动尤其是运行环境切换到别的电脑时优先检查这项配置第二图片上传模块的路径不要写死在代码里放进配置文件并写好注释避免换机器后抓瞎第三答辩前至少完整跑三遍全流程操作把“注册-登录-发布作品-评论-点赞-后台审核”这条主链路走到滚瓜烂熟确保现场演示不出岔子。最后分享一个小技巧如果你想让这个项目的论文答辩更好看在作品发布表单里加上“原料清单”字段——用户可以按行输入面粉、黄油、糖等原料和用量展示时用整齐的列表渲染出来。这一小改动在业务上非常贴合烘焙分享场景同时又只是在数据库加一张子表或者用JSON字段存储的简单实现但功能完整性和场景贴合度立刻上一个台阶。花半天时间换来的答辩效果提升很值。