ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

SpringBoot+Vue个性化图书推荐系统:从协同过滤到管理平台全解析

SpringBoot+Vue个性化图书推荐系统:从协同过滤到管理平台全解析 每年到了毕设选题的时候总有同学在“管理系统”“XX商城”这类题目里挑花眼。如果你既想用上主流技术栈又想让项目有点算法上的说头我强烈建议看看 SpringBoot Vue 的个性化图书推荐系统。这个项目以 JavaMySQL 做数据支撑SpringBoot 提供后端接口Vue 搭建前端管理平台核心卖点不是简单的增删改查而是围绕用户的阅读行为做“个性化推荐”——这在答辩时是一个非常容易讲清楚、也容易出彩的切入点。无论你是准备毕业设计、课程设计还是单纯想学前后端分离开发这个项目的知识密度都很合适。我这几年前前后后带过不少学生做类似课题也亲手搭过好几个版本的图书推荐系统。说实话这类项目最大的优点在于“麻雀虽小五脏俱全”用户体系、图书管理、行为采集、推荐算法、数据可视化全都能覆盖而且每一个模块都可以单独深挖。接下来我就以一套可运行的源码为例把整个系统的设计思路、推荐算法落地、数据库表结构、前后端联调经验以及那些容易让新手卡住的坑一次性讲透。1. 个性化图书推荐系统到底在解决什么问题1.1 为什么图书推荐系统是毕设/课设的“安全牌”先聊选题。很多同学担心毕设题目太简单显得没工作量又怕题目太难做不出来。图书推荐系统正好卡在“既不会太简单也不会做不完”的甜蜜点它本质上是一个带推荐功能的业务系统技术栈主流数据模型清晰推荐算法可以讲得很深也可以实现得很轻。从技术覆盖面来看这个项目能练到的东西非常全后端有 SpringBoot 的接口开发、业务分层、ORM 操作前端有 Vue 的组件化开发、路由管理、状态管理、HTTP 请求交互数据库有 MySQL 的表设计、索引优化、多表查询算法部分还要写相似度计算、评分预测这样的核心逻辑。一个项目下来你对“前后端分离开发”的全链路会有一个很扎实的理解。另外“个性化推荐”这个关键词本身就是加分项。同样是图书管理系统如果你只做图书增删改查答辩老师很难找到亮点但如果你能说清“系统如何通过用户的评分行为计算相似用户再把你可能喜欢的书推荐给你”那项目的技术含量立刻不一样了。哪怕最终实现的推荐算法不算复杂这份“从业务问题到算法方案”的思考过程也很有价值。1.2 别忽略标题里的“管理平台”四个字标题写的是“管理平台源码”不是纯粹的“推荐网页”这说明系统必须包含一个管理后台。我在很多初学者的设计方案里看到的问题是用户端做得很热闹但后台只有一个图书列表连用户都管不了。这种设计在毕设里很容易被挑刺——推荐系统的数据需要维护用户行为数据需要查看后台不完善整个系统就不闭环。一个合格的管理平台至少要包含三块内容图书管理新增、编辑、上下架、分类维护、用户管理查看用户列表、禁用异常账号、重置密码、推荐管理查看推荐日志、调整算法参数、统计数据。其中“推荐管理”是本项目的亮点模块比如可以设置推荐列表的长度、相似用户取几个、是否过滤已读图书等。有了这些后台功能系统才能叫“管理平台”而不是“一个推荐页面”。把用户端和管理端分开来看你会发现每个端都有自己的业务逻辑用户端强调流畅的浏览体验和个性化结果管理端强调数据维护效率和可配置性。两部分用同一套后端接口支撑前端使用 Vue 分别构建页面这就是典型的前后端分离架构。如果你能把这个架构的利弊在答辩时讲清楚评委对你的评价会高不少。2. SpringBoot、Vue、MySQL 这三驾马车是怎么协作的2.1 这个技术组合为什么被反复使用SpringBoot 在 Java 后端领域已经是事实标准它简化了 Spring 的配置内嵌 Tomcat能快速构建 RESTful API而且和 Spring Security、MyBatis/JPA 等生态结合得非常好。Vue 则是目前最容易上手的前端框架之一组件化写法和 React 相比门槛更低中文资料也多适合学生快速做出漂亮界面。MySQL 更不用说开源、稳定、使用面广几乎所有中小型业务系统都可以用它来存储数据。这三者组合起来的最大优势是“招聘市场上最常用、学习资料最丰富”。你随便搜一个系统项目大概率就是这套组合。这意味着你在开发中遇到的绝大多数问题都已经有人踩过坑网上能找到对应的解决方案。另外SpringBoot 之间版本差异、Vue 的生态工具、MySQL 的导入导出都有成熟的教程这对时间紧张的毕设来说是实实在在的好处。从项目结构上说SpringBoot 负责提供接口和数据Vue 只负责展示和交互MySQL 负责持久化存储。三者角色分明让开发者能分别启动前后端项目通过 HTTP 接口调试。实际开发时你可以先用 Postman 测通后端接口再开发前端页面减少联调阶段的返工量。如果你在简历上写“熟练使用 SpringBootVueMySQL 开发前后端分离应用”面试官也不会质疑这个技术栈的含金量。2.2 从点击按钮到出现推荐结果一次请求经历了什么我给你画一个生活化的过程用户在前端页面点了一下“为你推荐”就像在餐厅点菜。Vue 是服务员把用户的需求记下来axios 是传菜员端着订单往后厨跑SpringBoot 的后端就是厨房Controller 负责接单Service 负责做菜Mapper 负责去仓库MySQL拿食材最后做好的菜JSON 数据再由传菜员端回桌面Vue 把菜摆好盘展示给用户。具体到代码层面一次完整请求是这样的前端路由/recommend上的页面组件在挂载时调用axios.get(/api/recommend/list)请求到达 SpringBoot 的RecommendController。Controller 不做具体业务它把请求转给RecommendServiceService 内部先查当前用户的行为数据再调用推荐算法计算候选图书 ID最后用这些 ID 去 MySQL 查出图书详情打包成 JSON 返回。前端拿到 JSON 后循环渲染成卡片列表。这里要注意一个细节Controller、Service、Mapper 三层的职责一定要分清楚。我发现不少同学的代码把 SQL 直接写在 Controller 里或者让 Service 直接操作 HttpServletRequest这种写法前期很爽后期改一个功能就牵一发而动全身。按规范分层写不仅代码好读答辩时你说“项目分层清晰”也有底气。2.3 项目目录怎么组织最顺手后端建议用 Maven 标准的 SpringBoot 工程包名按业务模块划分。我常用的结构是com.example.bookrec ├── controller // 接口层 ├── service // 业务逻辑层接口实现 ├── mapper // MyBatis 的数据访问层 ├── entity // 数据库实体 ├── dto // 前后端交互的数据对象 ├── config // 配置类如跨域、JWT 拦截器 ├── recommend // 推荐算法相关的核心类 └── utils前端我用 Vue CLI 或 Vite 创建工程一般会长这样src ├── api // 封装 axios 请求模块 ├── assets // 静态资源 ├── components // 公共组件 ├── views // 页面级组件 ├── router // 路由配置 ├── store // Vuex/Pinia 状态管理 └── utils // 工具函数前端的api目录和后端controller接口保持对应关系比如api/book.js里封装getBookList、getBookDetail那么后端 Controller 里就应该有对应的GET /api/book/list和GET /api/book/{id}。这样做的好处是前后端对照接口文档开发时不容易漏接口也方便后续维护。3. 推荐算法怎么落地从数学公式到可运行的 Java 代码3.1 先搞清“个性化”三字的算法内涵市面上推荐算法很多但适合毕设/课设阶段实现的主要是三类基于内容、基于协同过滤、Hybrid 混合。基于内容的推荐简单说就是分析图书本身的属性分类、作者、标签和用户历史上喜欢的图书属性找相近的图书推荐基于用户的协同过滤UserCF核心是“和你兴趣相似的人喜欢的书你也可能喜欢”基于物品的协同过滤ItemCF核心是“和你看过的书相似的书也可能对你胃口”。在图书推荐场景里我建议优先实现基于用户的协同过滤因为它最容易解释也最能体现“个性化”的意思。比如两个用户都喜欢《三体》和《球状闪电》算法会认为他们是“相似用户”当其中一个用户给《流浪地球》打了高分系统就会把这本书推荐给另一个用户。这种推荐结果带有很强的“人以群分”色彩比单纯按分类推荐要聪明得多。当然协同过滤也有代价它依赖用户行为数据新注册用户没有任何记录时算法就“巧妇难为无米之炊”。所以我的建议是做一个混合策略用户有足够行为数据时走协同过滤数据不足时走基于分类的热门推荐两者结合既能体现算法深度又能保证新用户登录后也能看到推荐内容。3.2 用 Java 实现一个简易版“基于用户的协同过滤”在动手写代码前先理清算法步骤。假设我们已经有一张评分表rating里面记录了每个用户对图书的 1~5 分评价。推荐过程分四步第一步构建“用户-图书评分矩阵”第二步计算目标用户与其他用户的相似度第三步找到最相似的前 N 个用户第四步用这些相似用户的评分加权预测目标用户对未读图书的评分取 TopK 推荐。下面这段代码是计算两个用户评分的余弦相似度也是个示例核心片段public double cosineSimilarity(MapLong, Double userRatings, MapLong, Double otherRatings) { // 求两个用户都评过分的图书集合 SetLong commonItems new HashSet(userRatings.keySet()); commonItems.retainAll(otherRatings.keySet()); if (commonItems.isEmpty()) { return 0.0; } double dotProduct 0.0; double normUser 0.0; double normOther 0.0; for (Long itemId : commonItems) { dotProduct userRatings.get(itemId) * otherRatings.get(itemId); } for (double rating : userRatings.values()) { normUser rating * rating; } for (double rating : otherRatings.values()) { normOther rating * rating; } return dotProduct / (Math.sqrt(normUser) * Math.sqrt(normOther)); }这段代码逻辑并不复杂但要注意userRatings和otherRatings是Map图书ID, 评分在调用前需要从数据库把用户的所有评分查出来。若两个用户之间没有共同评分的图书相似度直接就返回 0因为没有任何证据表明他们口味相同。这个“共同评分”条件是协同过滤的关键很多同学写出来之后推荐结果很烂多半是因为这里没有处理好——比如把没评过分的数据也当成 0 分参与计算这会严重拉低相似度精度。拿到所有相似度之后排序取 TopN然后计算候选图书的预测评分。最简单的预测方式是加权平均double predictScore 0.0; double totalSimilarity 0.0; for (User u : similarUsers) { Double score u.getBookScore(bookId); if (score ! null) { predictScore similarityMap.get(u.getUserId()) * score; totalSimilarity similarityMap.get(u.getUserId()); } } predictScore predictScore / totalSimilarity;最后把预测分最高的几本还要过滤掉用户已经读过的书然后返回。3.3 冷启动问题和课设里的取舍策略协同过滤最怕冷启动新用户没有评分怎么推荐新书没有被评过分怎么推荐给别人这是推荐系统领域真实存在的难题也是答辩老师最爱追问的点。我的建议是不要强行用一个复杂模型解决它而是用“兜底策略”把逻辑讲圆对新用户直接返回当前评分最高的热门图书按借阅次数或平均分排序对没有评分的新书则利用图书的分类标签找同分类下最热门的书补进去对已登录且有一定行为数据的用户才真正调用协同过滤。你在论文里可以这样写系统采用混合推荐策略协同过滤负责“个性化”热门榜负责“冷启动”。这个小设计看着简单但能表明你想过真实场景中的问题而不是只会调包。如果你想让算法部分再硬核一点还可以同时实现 UserCF 和 ItemCF然后做一个简单的加权融合最后在测试集上对比两者效果。不过对大多数课设/毕设来说把 UserCF 做好做清晰已经足够拿高分了。4. 数据库设计与核心业务模块推荐系统也能有“五脏六腑”4.1 表结构怎么设计才不会后续返工数据库是整个项目的地基。图书推荐系统至少要包含五张核心表用户表、图书表、评分表、收藏表、浏览记录表再加上管理员表。凡是涉及“用户行为”的地方都要记录用户 ID、图书 ID、行为时间这是以后算推荐的原材料。用户表可以精简设计CREATE TABLE user ( user_id INT NOT NULL AUTO_INCREMENT, username VARCHAR(50) NOT NULL, password VARCHAR(100) NOT NULL, nickname VARCHAR(50) DEFAULT NULL, avatar VARCHAR(255) DEFAULT NULL, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (user_id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;图书表要有标题、作者、分类、ISBN、封面、简介、出版日期以及一个“平均评分”字段用来做热门排序。分类字段建议单独建一张分类表而不是直接在图书表里写字符串否则以后你想做分类筛选和基于内容推荐时数据会非常难维护。评分表是推荐算法的核心设计上要加唯一约束CREATE TABLE rating ( rating_id INT NOT NULL AUTO_INCREMENT, user_id INT NOT NULL, book_id INT NOT NULL, score TINYINT NOT NULL COMMENT 1-5分, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (rating_id), UNIQUE KEY uk_user_book (user_id, book_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;用UNIQUE KEY保证一个用户对一本书只能有一条评分记录后端的 Service 层再做一次幂等处理比如“如果已经评过分就改成更新操作”。收藏表和浏览记录表结构类似浏览记录还可以记录浏览次数用来反映用户对某本书的兴趣程度。但注意不要把所有行为都揉进一张表评分、收藏、浏览是三个不同强度的行为分开存储更灵活。4.2 后端的核心模块怎么拆后端大致分成四块用户模块、图书模块、行为模块、推荐模块。用户模块负责注册登录。密码千万不能明文存储至少用 BCrypt 加密。登录成功后我习惯签发 JWT前端把 token 存到 localStorage每次请求在拦截器里带上Authorization头。这样后端不用维护 Session符合前后端分离的开发方式。图书模块很常规就是分页查询、关键词模糊搜索、按分类筛选、查看详情。需要注意分页查询最好用 MyBatis 的分页插件 PageHelper或者写一个简单的 Page 参数自己 LIMIT。这个小点也能体现你对数据量增长的考虑。行为模块是为推荐服务的“原料供应商”。用户给图书打分时写一条rating记录用户点收藏写一条favorite用户打开详情页写一条browse_history。代码逻辑不复杂但一定要让前端配合好什么动作调用什么接口由后端来定义接口语义。比如评分接口应该是POST /api/rating/{bookId}body 里传 score而不是前端传一个“我评分了”这种模糊信号。推荐模块是整个系统的技术核心但代码量不一定最大。它可以拆成三个类数据加载器把评分矩阵读进内存、相似度计算器、推荐执行器。这三个类的职责足够清晰测试也方便。实际开发时你甚至可以写一个RecommendRunner在项目启动后通过定时任务离线计算每个用户的推荐结果然后存到一张recommend_result表用户请求推荐时直接查表返回性能会好很多这也是我给课设推荐的实现方式。4.3 管理后台的功能设计直接影响项目评分管理后台绝不是简单的“第二个前端”它体现的是系统完整度。图书管理页至少要支持图书的新增和编辑表单里的字段要能对应数据库表用户管理页要能看到用户列表和他们的行为数据统计比如评分次数、收藏数推荐管理页可以做成参数配置和结果预览比如管理员设置“相似用户TopK5”点击保存后能看到重新计算出的推荐结果。这里说个实操建议管理后台不一定重新写一套页面可以复用用户端的很多组件只是进入管理页面之前加一个权限判断。Vue Router 的全局前置守卫非常适合干这件事如果当前路由是/admin开头而且管理员没登录就跳转到管理员登录页。这样代码量增加不多但在演示时你能够说清楚“这个系统有前后台两个角色权限控制是做了的”。5. Vue 前端页面与联调细节让推荐结果“看得见、摸得着”5.1 页面规划与组件划分Vue 前端页面建议按两个角色分开。用户端主要包含登录注册页、图书列表页、图书详情页、推荐页、个人中心。管理端包含仪表盘、图书管理、用户管理、评分管理、推荐设置。这里有个小技巧把公共的图书卡片列表抽成一个BookCard组件用户端的“图书列表”“推荐结果”“猜你喜欢”都可以复用。推荐页是整个项目的门面设计时要比普通图书列表更有“推荐感”。我习惯在每本书的卡片上显示一行预测评分比如“预测你很喜欢4.7 分”并给一个“为什么推荐”的小标签像“因为你看过《三体》”这样的解释。这个解释其实来自算法结果中相似图书的共同标签不需要额外再做复杂推理但用户体验和答辩效果都会明显提升。页面路由方面用户端和管理端建议分开前缀用户端是/、/books、/recommend管理端是/admin/books、/admin/users。路由懒加载记得开用() import(/views/BookList.vue)这样首次加载更快也显得你懂性能优化。5.2 封装 Axios联调的第一步前后端联调最容易崩的地方就是请求层没有统一处理。我的做法是在前端建一个api/request.js封装好 axios 实例import axios from axios const request axios.create({ baseURL: /api, timeout: 10000 }) // 请求拦截器自动带上 token request.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers[Authorization] token } return config }) // 响应拦截器统一拆包和错误提示 request.interceptors.response.use( response { const res response.data if (res.code ! 200) { alert(res.message) return Promise.reject(new Error(res.message)) } return res.data }, error { alert(网络异常请稍后再试) return Promise.reject(error) } ) export default request这里后端接口的返回结构我建议统一成{ code: 200, message: success, data: ... }这样前端拦截器才能统一处理。很多同学前后端各写各的后端返回一堆散字段前端到处.catch开发效率和体验都很差。开发环境下跨域是绕不开的问题。一种方式是在 SpringBoot 里配置全局跨域写一个实现WebMvcConfigurer的配置类允许所有来源访问另一种方式是在 Vite/Vue CLI 里配置proxy把/api转发到http://localhost:8080。我比较推荐用代理方式这样浏览器请求的始终是同源地址不会踩到 Cookie 携带的坑。5.3 推荐结果的前端展示与交互推荐结果返回的数据结构我建议设计成{ bookId: 12, title: 《百年孤独》, author: 加西亚·马尔克斯, coverUrl: https://..., predictedScore: 4.7, reason: 因为你看过《霍乱时期的爱情》 }前端拿到这个列表后用v-for循环渲染即可。注意 predictedScore 保留一位小数如果连续多次推荐结果相同还可以加一个“换一批”按钮前端把当前列表的最后一本书 ID 传给后端后端从推荐列表的后续位置开始返回。这个小交互虽然简单但会让人感觉系统是活的不是死的。另外图书详情页要支持“评分”操作评分后要重新拉取一次推荐页数据否则“个性化”无从体现。我在测试时经常能遇到用户评完 5 本高分书后推荐列表立刻出现同类书籍这种即时反馈在答辩演示时杀伤力很强比嘴上讲算法原理直观多了。6. 踩坑与调试这些坑我替你踩过了6.1 环境配置最容易卡住的三个地方第一个坑是 JDK 和 SpringBoot 版本匹配。SpringBoot 3.x 默认要求 JDK 17而很多学校的机房或学生自己的电脑还停留在 JDK 8。我建议直接用 SpringBoot 2.7.x 配 JDK 8兼容性最好网上资料也最多。如果你非要用 SpringBoot 3.x那就要适应 Jakarta EE 的包名变化比如javax.servlet变成jakarta.servlet很多老教程会失效。第二个坑是 MySQL 8.0 的连接配置。连接 URL 里必须要加时区否则启动时会报ServerTimezone异常。我的完整写法是jdbc:mysql://localhost:3306/book_recommend?useSSLfalseserverTimezoneAsia/ShanghaicharacterEncodingutf8useSSLfalse是为了避免本地开发环境没有证书时报“SSL 连接错误”characterEncodingutf8是为了防中文乱码。这串参数我建议直接背下来几乎每个 JavaWeb 项目都能用上。第三个坑是前端 npm 依赖安装太慢甚至安装失败。如果用的是 vue-cli 创建项目记得先设置 npm 镜像源为国内镜像再执行安装。否则一个项目装半小时心态直接崩。实际开发中我还遇到过 Node 版本过旧导致 Vite 无法启动的问题实在不行就装一个 Node 16 以上的 LTS 版本省心。6.2 为什么推荐结果几乎永远一样一个经典的逻辑错误不少同学把协同过滤写完之后发现推荐列表跟热门列表没区别或者只推荐同一作者的书完全体现不出“个性化”。我排查过的案例里最常见的原因是相似用户的计算被“空数据”污染了。比如没有做“共同评分”过滤导致两个评分向量里的多数元素都是 0余弦相似度几乎全被拉平又比如计算完预测评分后没有把用户已经读过的书过滤掉用户会反复看到自己读过的高分书。排错思路可以参考这条链路第一先查数据库里rating表有没有足够的真实用户行为数据第二写一个单元测试单独调用相似度计算打印两个已知用户的余弦值看是否在合理范围第三打印推荐候选的前 50 个结果观察是不是所有用户的候选集都一样第四检查排序时有没有把predictedScore当成字符串排序。另外提醒一句如果你的测试环境只有一两个账号那推荐结果不理想是正常的。演示前最好准备 5 个以上的测试账号每个账号都对十几本书打分并且打分偏好有明显差异。这样协同过滤才能展现出效果。一个只有三两个用户的推荐系统再好的算法也白搭。6.3 前端联调时的高频问题清单第一个是跨域。后端没配跨域时浏览器控制台会出现No Access-Control-Allow-Origin header is present。解决办法是在 SpringBoot 里加一个配置类或者更简单地在 Controller 上加CrossOrigin。但如果使用了拦截器做登录校验要注意跨域配置要允许 OPTIONS 请求直接通过否则前端连预检请求都过不了。第二个是 404。Vue 使用 history 模式路由时刷新一个非根路径的页面会变成后端 404。因为刷新时浏览器直接把地址发给了服务器但服务器并没有对应的静态文件。解决办法要么把路由模式改成 hash即 URL 里带#要么在 Nginx/后端做 history 路由回退。我这里推荐直接用 hash 模式毕设演示时不用额外配置省去很多麻烦。第三个是前后端字段不一致。Java 后端返回的是bookId前端却写了bookID页面数据就全空了。建议前后端约定好接口文档用 Swagger 或者直接写好 Markdown 接口说明。前端拿到响应后先console.log看结构再绑数据能省掉很多瞎猜的时间。7. 怎么把这套系统做成高分项目进阶方向与答辩建议7.1 增加可视化和数据统计让“推荐效果”看得见很多推荐系统项目做完答辩现场只能靠嘴说“推荐效果不错”。我建议你增加一个可视化页面用 ECharts 展示高频借阅榜、用户评分分布、相似用户图谱。数据来源可以直接用后端统计接口不需要额外接入大数据组件但视觉冲击力会非常大。比如画一个“图书热度 Top10”柱状图再配一个“用户-图书评分热力图”评委一看就知道你的系统不只是 CRUD。如果时间充裕还可以把推荐结果的前后端链路打点记录一次请求从发出到响应用了多少毫秒然后在页面上展示。这个“性能监控”小功能不用多复杂后端 Filter 记一下开始时间前端在控制台打印就能作为你考虑过性能优化的证据。7.2 选两个优化方向缓存、实时推荐、算法对比想让项目有深度的同学可以从三个方向里至少挑一个做加码。第一个是缓存方向把推荐结果放到 Redis 里设置 10 分钟过期过期后重新计算。这个优化思路很常规但能明显提升接口响应速度也能展示你理解“热点数据需要缓存”这个点。第二个是实时推荐方向用户每次评分后不是立刻全量重算而是只更新用户和相似用户的计算产生增量推荐。这个偏工程化代码会复杂一些我建议课设慎选别把自己坑进去。第三个是算法对比方向实现基于内容推荐和基于协同过滤推荐然后在评分数据集上留出测试集计算 RMSE 或者准确率做一个柱状图对比。这一步是论文里非常闪亮的“实验验证”部分很多硕士论文也就是这么干的本科阶段能做出这个对比含金量直接拉满。7.3 论文与答辩的实战建议论文结构上别套模板但要包含几个关键内容引言里说明为什么图书推荐有价值需求分析里给出用例图总体设计画一张系统架构图文字描述清楚也行详细设计里写清数据库表结构和推荐算法公式测试章节能给出功能测试用例和非功能性测试。重点是算法章节一定要贴公式、贴核心代码片段用数据或图标说明推荐效果。答辩演示时请不要一开场就展示管理端的增删改查。我建议的演示顺序是先用一个新注册的空白账号登录展示冷启动状态下的热门推荐然后给几本高分书评分再切换到一个有行为数据的账号刷新推荐页让评委看到列表显著变化最后点进图书详情展示评分和收藏功能收尾再快速展示管理后台。整个过程不超过五分钟但已经把“个性化”的变化讲得很直观。还有一个小提醒答辩前一定要清理测试环境把数据库里乱七八糟的测试数据删掉注册几个干干净净、行为轨迹清晰的账号。遇到老师问“为什么这两个用户收到的推荐不一样”你就能很自然地解释协同过滤的相似度计算过程。做这类项目我的体会是先别急着追求算法复杂度先把基础功能跑通让数据流动起来再逐步加入推荐逻辑。当你看到不同账号在评分后推荐结果真的发生变化时那种“系统活了”的感觉非常奇妙。希望这篇分享能帮你少走弯路把这个经典的 SpringBootVue 图书推荐系统做成属于你自己的高分项目。
返回列表