ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Spring Boot + Vue 协同过滤电影推荐系统全栈开发指南

Spring Boot + Vue 协同过滤电影推荐系统全栈开发指南 Spring Boot 加 Vue 做协同过滤电影推荐系统这个技术栈组合在毕业设计里非常常见也很适合作为完整项目练手。它的核心价值不在于“推荐算法有多深”而在于把后端接口、前端页面、数据库设计和推荐逻辑完整串起来。这篇内容我会按实际开发顺序来拆解先搞清楚系统该做什么再准备环境和数据库然后写后端 Spring Boot 接口写前端 Vue 页面最后做联调测试、排查常见坑以及给毕设答辩留一些可扩展方向。我自己在带学生做类似项目时最常见的错误是先把推荐算法写得特别复杂结果前端页面和后端接口根本来不及完善。系统一启动就报错推荐结果也没法解释。所以这篇文章会重点强调一件事先用最简单的基于物品的协同过滤把链路跑通再去考虑增加用户特征、评分归一化、冷启动策略这些优化点。如果你是刚接触 Spring Boot 或者 Vue 的新手这篇文章的前半部分会比较友好。如果你已经有一定基础可以直接跳到协同过滤核心实现和联调排查部分。1. 先想清楚这个系统到底要解决什么问题电影推荐系统听起来很高大上但落到毕业设计里它其实就三件事用户能登录、用户能给电影打分、系统根据打分历史给用户推荐电影。Spring Boot 负责提供接口Vue 负责页面展示和交互协同过滤负责计算推荐结果。三者加起来一个完整的全栈项目闭环就出来了。1.1 为什么这个组合特别适合做毕业设计或简历项目先看技术覆盖面。Spring Boot 部分可以体现Spring MVC 请求处理、MyBatis 操作数据库、Service 层业务逻辑、RestController 前后端分离接口设计、跨域配置、异常处理。如果再加一点 Spring Security、JWT 登录鉴权、Redis 缓存那就是标准企业级开发套路。Vue 部分可以体现组件化开发、Vue Router 路由管理、Axios 请求封装、Element UI 或 Ant Design Vue 组件库、Vuex/Pinia 状态管理。这些也是实际前端项目中最常被问到的点。协同过滤部分可以体现基础算法理解、相似度计算、评分矩阵构建、推荐列表生成、用户冷启动处理。放到论文里就是“核心算法与系统实现”。这类项目最大优势是任何一部分出了问题都能单独排查。后端不想看前端时直接用 Postman 或 Apifox 调接口前端不想等后端时可以用 Mock 数据先画页面。这种前后端分离的调试方式和真实开发环境是一样的比单体 JSP 项目更能说明你有项目工程化能力。1.2 面向的读者和使用场景我写这篇内容的目标读者主要是有一定 Java 和前端基础但还没完整做过一个全栈项目的人。尤其是正在选毕业设计题目的计算机相关专业学生想用 Spring Boot Vue 作为简历项目、但不知道该从哪下手的初学者已经在做电影推荐系统、但推荐算法部分总是算不出合理结果的开发者想快速搭建一个前后端分离 Demo再逐步扩展功能的程序员如果你的最终目标是把这个项目写成论文那我建议你在理解这套实现之后重点关注协同过滤参数对推荐结果的影响例如用户相似度阈值取多少、最相似用户数取多少、评分归一化怎么做。这些内容既适合理论分析也适合做实验对比。2. 开发前准备环境、版本和项目结构一次性规划好很多人在项目一开始就犯一个错误不规划版本直接装环境。等代码写了一半发现 JDK 版本太高导致依赖不兼容或者 Node 版本和 Vue CLI 对不上再回头改就很痛苦。所以我会先花一小节专门讲环境准备。2.1 基础环境清单以下是我自己常用的开发组合不一定要求完全一致但版本互相兼容很重要。软件推荐版本说明JDKJDK 8 或 JDK 11Spring Boot 2.x 最稳妥如果打算用 Spring Boot 3.x建议 JDK 17 起Maven3.6用来管理后端依赖Node.js14.x 或 16.xVue CLI 和 npm 依赖对 Node 版本有要求太高或太低都可能出问题Vue CLI4.x 或 5.x快速创建 Vue 项目MySQL5.7 或 8.0存储用户、电影、评分、管理员数据IDEA2022 或更新版本后端开发用VSCode / WebStorm任意前端开发用Postman / Apifox任意接口测试必备这里最容易踩的坑是JDK 版本不要追求最新。很多毕业生一看机器上装了 JDK 21就直接用。结果 Spring Boot 2.3 根本不支持或者 MyBatis 插件编译报错。实际写毕业设计Spring Boot 2.7 JDK 8 是最稳的组合。如果你有额外精力再去尝试 Spring Boot 3.x 和 Jakarta EE 相关变化。2.2 后端项目结构规划后端建议按经典三层架构来组织src/main/java/com/example/movie ├── config # 配置类跨域、拦截器、WebMvc ├── controller # 控制层接收前端请求 ├── service # 业务层登录、注册、评分、推荐 │ └── impl ├── mapper # MyBatis Mapper 接口 ├── entity # 实体类User、Movie、Rating、Admin ├── dto # 请求/响应参数对象 ├── common # 统一返回结果、状态码、异常处理 └── MovieApplication.java这样的结构为什么重要因为在答辩或简历面试中面试官一定会问“你的项目是怎么分层的”。如果你把 SQL 写在 Controller 里把业务逻辑全堆在一个类里很难讲清楚。先按标准分层来写后面调试也方便很多。2.3 前端项目结构规划Vue 端建议用 Vue CLI 创建项目然后建以下目录src ├── api # 封装 axios 请求方法 ├── assets # 静态资源 ├── components # 通用组件导航栏、电影卡片 ├── router # 路由配置 ├── store # 状态管理Vuex/Pinia ├── views # 页面首页、登录、注册、电影详情、推荐页、个人中心 └── utils # 工具函数比如 request.js 封装有些同学会觉得“项目结构随便建能跑就行”。这话对个人 Demo 成立但对毕业设计和简历项目不成立。一个结构清晰的项目在答辩时只需要展示目录就能让老师快速看出你理解业务分层。3. 数据库设计先设计评分表再设计电影表电影推荐系统的核心不是电影表而是用户对电影的评分记录。因为协同过滤算法的输入就是“用户-电影-评分”三元组。没有评分记录用户打得分数再高算法也算不出推荐结果。3.1 四张核心表最少需要四张表用户表tb_user电影表tb_movie评分表tb_rating管理员表tb_admin可选但如果做后台管理系统就需要用户表CREATE TABLE tb_user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(100) NOT NULL, nickname VARCHAR(50), avatar VARCHAR(255), create_time DATETIME DEFAULT CURRENT_TIMESTAMP );这里要注意密码不能明文存储。毕业设计虽然没有生产环境那么严格但至少要会用 MD5 或 BCrypt 做哈希。如果能写一句“使用 BCrypt 加密存储”在答辩时就是一个小加分点。电影表CREATE TABLE tb_movie ( id INT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(255) NOT NULL, cover VARCHAR(500), director VARCHAR(255), actors VARCHAR(500), genre VARCHAR(100), -- 类型动作、科幻、爱情等 description TEXT, release_year INT, rating DECIMAL(3,1) DEFAULT 0.0, -- 豆瓣或其他来源综合评分 create_time DATETIME DEFAULT CURRENT_TIMESTAMP );电影的字段可以根据实际情况扩展。比如改成“地区、语言、片长、导演、主演、简介”。但不要做得太复杂字段一旦太多插入测试数据的成本就上来了。评分表CREATE TABLE tb_rating ( id INT PRIMARY KEY AUTO_INCREMENT, user_id INT NOT NULL, movie_id INT NOT NULL, score INT NOT NULL, -- 1-5 分或 1-10 分 rating_time DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY uk_user_movie (user_id, movie_id) );评分表是最关键的一张表。这里有几个设计点需要注意score用INT取值 1 到 5 或 1 到 10。推荐用 1 到 5因为协同过滤示例计算起来更方便。加唯一索引uk_user_movie保证一个用户对同一部电影只保留一条评分记录。如果用户重新评分走ON DUPLICATE KEY UPDATE更新分数而不是再插一条新记录。管理员表CREATE TABLE tb_admin ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(100) NOT NULL, role VARCHAR(20) DEFAULT ADMIN );管理员表是后台管理的基础。如果你想做“管理员可以维护电影信息、查看用户列表”的功能这张表就是必要存在的。3.2 测试数据怎么造数据库建好之后最头疼的问题是电影数据从哪里来这里不建议去爬第三方网站一方面是合规性问题另一方面是爬下来的数据格式很乱还要清洗。更稳妥的做法是手写 30 到 50 部电影覆盖动作、科幻、爱情、动画、悬疑等常见类型。每部电影除了标题尽量填写导演、主演、简介和类型。造 10 到 20 个测试用户。让每个用户给 10 到 30 部电影打分分数范围 1 到 5。测试数据要满足一个基本要求用户之间有共同的评分电影。比如用户 A 和用户 B 都看过《流浪地球2》和《哪吒之魔童降世》这样协同过滤才能计算出相似度。如果每个用户的评分电影完全没有交集推荐算法就会失去意义也不方便验证效果。如果觉得手写太麻烦可以用 Python 脚本生成测试数据再通过 Java 后端插入数据库。这个脚本后续在论文里也可以作为“数据准备”的一部分不会显得多余。4. 后端实现Spring Boot 搞定登录、评分和协同过滤推荐这一节是整个项目的核心。我会按从外到内的顺序来写先写接口返回格式再写实体、Mapper、Service最后重点解释协同过滤怎么算。4.1 统一返回结果设计前后端分离项目最怕接口返回结构不统一。有人写成功返回{ code: 200 }失败返回{status: 0}前端封装逻辑就会非常痛苦。我建议定义一个统一结果类public class ResultT { private Integer code; private String message; private T data; public static T ResultT success(T data) { ResultT result new Result(); result.code 200; result.message success; result.data data; return result; } public static T ResultT error(String message) { ResultT result new Result(); result.code 500; result.message message; return result; } }这样前端 axios 拦截器里只需要判断code是否等于 200不用每个接口单独处理错误结构。4.2 用户登录和 JWT 鉴权登录功能看起来简单但很能体现基本功。常规做法是前端把用户名和密码传给后端。后端用用户名查数据库比对密码。比对通过后生成 token返回给前端。前端把 token 存在本地存储中后续请求在 header 里带Authorization: token。后端写一个拦截器或过滤器拦截除登录、注册和电影列表之外的接口校验 token。JWT 的依赖通常是这样加的dependency groupIdio.jsonwebtoken/groupId artifactIdjjwt/artifactId version0.9.1/version /dependency注意如果你用的是 JDK 9 以上需要额外引入 JAXB 相关依赖否则会报ClassNotFoundException: javax.xml.bind.DatatypeConverter。这个坑很容易遇到。但这里有一个选择毕业论文的系统要不要做 JWT我的建议是做。因为不做 JWT你就要用 session而 Vue 和 Spring Boot 前后端分离项目里 session 处理比较麻烦还涉及到跨域 cookie 配置。用 JWT 反而更符合现代开发流程。不过如果你只是做本地 Demo先不做鉴权也可以跑通但面试时会被问到“用户登录状态怎么校验”这类问题。4.3 电影和评分接口接口设计建议按 RESTful 风格。不需要太标准但路径要清晰方法路径说明POST/api/user/login用户登录POST/api/user/register用户注册GET/api/movie/list分页获取电影列表GET/api/movie/detail/{id}获取电影详情GET/api/movie/search?keywordxxx搜索电影POST/api/rating/submit提交或修改评分GET/api/user/ratings获取当前用户的评分列表GET/api/recommend/{userId}为指定用户生成推荐评分提交接口是重点。前端传userId、movieId、score三个字段后端要做一次幂等处理。如果用户已经给某个电影评分直接更新分数如果没有则插入新记录。这个逻辑可以写在 Service 里SQL 用数据库的唯一索引兜底。4.4 协同过滤推荐算法怎么落地协同过滤在毕设里最常用的是两种基于用户的协同过滤UserCF和基于物品的协同过滤ItemCF。这两者的区别基于用户找到和我口味相似的用户把这些用户喜欢、我没看过的电影推荐给我。基于物品找到和我看过电影相似的电影把相似度高的推荐给我。在电影推荐网站场景中基于物品的协同过滤通常比基于用户的协同过滤更合适。因为用户数量增长之后计算用户相似度的代价会变大而电影数量相对固定物品相似度可以提前离线计算好。这个判断在论文里是可以展开讨论的。最小可实现的 ItemCF 思路假设评分范围是 1 到 5 分。第一步读取所有评分记录构建用户评分矩阵。比如用户A: { 电影1: 5, 电影2: 3, 电影3: 4 } 用户B: { 电影1: 4, 电影2: 2, 电影4: 5 } 用户C: { 电影2: 5, 电影3: 1, 电影5: 3 }第二步计算电影之间的相似度。对于电影 i 和电影 j找到同时给这两个电影评分的用户通过余弦相似度或皮尔逊相关系数计算相似度。余弦相似度公式是similarity sum(a_i * b_i) / (sqrt(sum(a_i^2)) * sqrt(sum(b_i^2)))其中a_i是用户对电影 i 的评分b_i是同一用户对电影 j 的评分。这个计算在 Java 中不需要引入额外包自己写一个工具类就行。第三步为目标用户生成推荐。对于用户U没看过的电影 m找到用户U评分过的电影集合 S计算推荐分predicted_score(m) sum(similarity(s, m) * rating(U, s)) / sum(|similarity(s, m)|)然后按预测分从高到低排序取前 10 条作为推荐结果。核心代码逻辑示例下面是一个简化的工具方法展示用户相似度计算思路。注意这是思路演示实际放在项目里要结合 Mapper 查询数据。public double calcCosineSimilarity(MapInteger, Double userRatings1, MapInteger, Double userRatings2) { SetInteger commonMovieIds new HashSet(userRatings1.keySet()); commonMovieIds.retainAll(userRatings2.keySet()); if (commonMovieIds.isEmpty()) { return 0.0; } double dot 0.0, normA 0.0, normB 0.0; for (Integer movieId : commonMovieIds) { double r1 userRatings1.get(movieId); double r2 userRatings2.get(movieId); dot r1 * r2; } for (double r : userRatings1.values()) { normA r * r; } for (double r : userRatings2.values()) { normB r * r; } if (normA 0 || normB 0) { return 0.0; } return dot / (Math.sqrt(normA) * Math.sqrt(normB)); }这段代码解决的问题是如何在两个用户的评分序列中计算相似度。如果两个用户没有共同评分电影直接返回 0。这里有一个很容易被忽略的细节共同评分电影的数量太少时相似度结果会非常不稳定。一般会设定一个最小阈值比如至少 3 部共同评分电影才计算相似度。这个阈值在论文和实测中都很值得写。推荐结果的输出推荐算法算完以后返回给前端的不能只是一串电影 ID。因为这样的话前端还要再查一次电影详情多一次请求。更合理的做法是后端直接把推荐电影的完整信息拼好返回。推荐接口返回结构{ code: 200, message: success, data: [ { id: 12, title: 星际穿越, cover: http://xxx/cover.jpg, genre: 科幻, director: 克里斯托弗·诺兰, description: ..., predictedScore: 4.6 } ] }这里的predictedScore就是协同过滤算出来的预测评分。前端展示时可以按它排序让推荐理由更清晰。4.5 用户冷启动怎么处理协同过滤有一个天然问题新用户没有评分记录算法没有办法计算相似度推荐结果为空。毕设里最简单的处理方法是如果用户评分记录为 0返回电影库中综合评分最高、或评论热度最高的 10 部电影。如果用户评分记录少于 5 条可以按电影类型偏好来推荐比如用户只给动作片打分就多推动作片。这种策略在论文里叫“冷启动处理”。不需要写得很复杂但至少要证明你意识到这个问题并且有方案。很多同学因为没写冷启动策略答辩时被问“新用户进来推荐什么”就直接卡住非常可惜。4.6 数据库访问层注意点Spring Boot 连接 MySQL 时常用的组合是 MyBatis 或 MyBatis-Plus。MyBatis-Plus 在毕业设计里真的很省事。自带的BaseMapper可以直接帮你完成单表 CRUD不用写一堆 XML。比如public interface RatingMapper extends BaseMapperRating { }然后 Service 里就可以直接QueryWrapperRating wrapper new QueryWrapper(); wrapper.eq(user_id, userId); ListRating ratings ratingMapper.selectList(wrapper);如果一个用户对某部电影评过分用selectCount判断一下即可。不过要注意如果使用 MyBatis-Plus需要在配置里设置主键生成策略和数据库类型例如spring: datasource: url: jdbc:mysql://localhost:3306/movie_db?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver如果用 Spring Boot 2.xMySQL 8 的驱动类名是com.mysql.cj.jdbc.Driver。如果用 5.x 版本驱动名不同而且会有时区报错需要在 URL 里加serverTimezoneAsia/Shanghai。这是很常见的启动报错点。5. 前端实现Vue 页面怎么和后端无缝对接前端部分是很多非科班同学的弱项但在整个系统里又很重要。因为老师首次打开你的项目时看的不是代码而是页面效果。页面做得干净整洁第一印象就会好很多。5.1 Vue 项目初始化和依赖安装我建议使用 Vue CLI 来创建项目。npm install -g vue/cli vue create movie-frontend创建时选择 Vue 2 或 Vue 3 都可以。当前主流是 Vue 3对应 Element Plus。如果你更熟悉 Vue 2那就用 Element UI问题不大。关键是团队或你自己后续维护要顺畅。创建进入项目后安装路由、状态管理、请求库和 UI 组件库npm install vue-router4 npm install pinia npm install axios npm install element-plus注意Vue 3 对应的是 Element Plus不是 Element UI。如果你在 Vue 3 项目里安装了element-ui页面大概率直接白屏控制台还会报组件注册错误。5.2 axios 请求封装前端最容易乱的就是请求。如果每个页面各自写axios.get(...)请求地址写死、错误处理重复、没有统一 loading项目写大了就会非常混乱。建议在utils/request.js里封装一个 axios 实例import axios from axios import { ElMessage } from element-plus const request axios.create({ baseURL: http://localhost:8080/api, timeout: 10000 }) 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) { ElMessage.error(res.message || 请求错误) return Promise.reject(new Error(res.message)) } return res.data }, error { ElMessage.error(error.message || 网络异常请稍后重试) return Promise.reject(error) } ) export default request这个封装的好处很明显所有请求自动带上 token。后端返回 code 不为 200 时统一弹出错误提示。页面里只需要处理业务数据不用每个页面都写错误判断。5.3 页面路由设计路由配置是整个前端项目的骨架。推荐系统的常规页面如下/login 登录页 /register 注册页 /home 首页电影列表 /movie/:id 电影详情页 /recommend 个性化推荐页 /ratings 我的评分 /admin 后台管理页可选使用 Vue Router 配置时要注意两个问题第一路由跳转前要检查登录状态。你可以写一个全局前置守卫如果页面要求登录而本地没有 token就跳转到登录页。第二电影详情页和推荐页通常放在路由组件中需要传递电影 ID所以路径要设计成/movie/:id这类动态参数式。5.4 首页电影列表首页很简单调用GET /api/movie/list?page1size12把结果用卡片列表展示。每张卡片显示封面、标题、类型、评分。这里有个实际体验问题如果第一次渲染时后端还没返回数据Vue 会自动初始化data.list []然后页面会闪烁一下。建议增加v-loading或按钮 loading 状态等请求完成后再渲染。5.5 电影详情页和评分交互电影详情页建议做两个区域上半部分是电影基本信息封面、标题、导演、主演、简介、类型。下半部分是当前用户的评分区域如果用户没登录提示先登录再评分。如果用户已经评分显示以往评分并允许修改。用户点击 1 到 5 星时前端记录分数再调用/api/rating/submit接口。前端星级评分的值最后会传给后端。这个交互很简单但会让页面看起来有完整交互闭环。比单纯展示信息更能体现系统完整性。5.6 推荐页推荐页是系统的门面。这里不是简单展示推荐列表而是建议增加一个说明区域例如“根据你看过的《流浪地球2》《星际穿越》等电影我们为你推荐以下内容。”这种解释性文案在论文里可以叫“推荐解释模块”。它不是算法的一部分但会让系统显得更完整答辩时也更好讲。推荐页的核心代码很简单就是调用后端推荐接口然后用电影卡片组件展示结果。注意处理特殊情况新用户没有任何评分记录时推荐接口返回热门电影列表。推荐为空时页面不能白屏要给出“暂无推荐先去评分吧”的提示。5.7 Vue 环境配置和跨域前后端分离项目一定会遇到跨域问题。解决方案有几种方式一后端加全局跨域配置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); } }方式二前端开发时用 Vue CLI 代理。在vue.config.js中配置module.exports { devServer: { proxy: { /api: { target: http://localhost:8080, changeOrigin: true } } } }方式一适合快速联调方式二更适合生产环境。建议开发时用代理部署时用 Nginx 反向代理但初版直接用后端的跨域配置是最省事的。6. 联调验证从接口到页面的全流程测试项目写完之后不能只在 IDEA 里启动就完事。你要按用户的路径完整走一遍确认每个环节都正常。6.1 基础功能测试清单我整理了一份测试清单建议按顺序执行测试项操作预期结果用户注册填写用户名密码点击注册提示成功并跳到登录页用户登录输入正确账号密码登录返回 token 并跳转首页错误密码登录输入错误密码提示用户名或密码错误电影列表首页加载展示电影卡片滚动可分页电影搜索输入关键字搜索展示匹配电影电影详情点击任意电影展示完整信息用户评分未登录评分跳转登录页用户评分登录后评分提示成功刷新后评分保留推荐列表登录且有 3 条以上评分返回个性化推荐新用户推荐新注册账号进入推荐页返回热门电影列表退出登录点击退出token 清除回到首页测试时建议用 Postman 先测接口再用浏览器页面确认一次。如果接口通过但页面错大概率是前端参数名和后端字段名不一致。比如后端返回cover前端取的是movie.coverUrl那图片自然显示不出来。6.2 如何验证协同过滤确实“生效”了这是整个项目测试中最关键的一环。很多同学不知道怎样算测试通过。我的建议是设计一个可控的小样本场景比如创建三个测试用户小明看过电影 A、B、C评分都是 5。小红看过电影 A、B评分都是 5看过 D 评分 1。小刚看过电影 A、B、C、D。用协同过滤算完之后小明和小红因为共同喜欢 A 和 B相似度较高。那么小明应该能得到电影 D 的推荐但对 D 的预测分不会特别高因为小红给 D 的评分很低。反过来如果还有一个用户小丽给 A、B、C 都评 5还给 E、F 评 5那么小明最可能先看到 E 和 F。这个场景的优点是可以倒推算法结果是否正确。你不需要看代码只需要在页面上观察推荐结果是否符合直觉。如果推荐出来的全是用户已经看过的电影那就说明过滤条件没有生效。我项目里出现过一次原因是在查询“待推荐电影”时没有排除用户已评分的电影。6.3 性能边界和常见问题排查问题一项目启动时就报错最常见的是三种数据库连接失败。检查 MySQL 是否启动、URL 地址是否写对、账号密码是否匹配、端口是否被占用。Maven 依赖下载失败。先清理 IDE 缓存再看网络环境。如果本地 Maven 仓库里缺少依赖可以尝试切换阿里云镜像。端口被占用。Spring Boot 默认 8080如果被其他程序占用启动会报Port already in use。解决办法是把 IDEA 里之前运行的实例停掉或者修改server.port。问题二前端启动后页面白屏优先看浏览器控制台一般三种情况Vue Router 版本和 Vue 核心版本不匹配。Element Plus 没有正确引入或者引入方式不对。入口文件main.js里没有挂载路由或 store。问题三接口报 404检查后端 Controller 的RequestMapping路径和前端请求路径是否一致。尤其是版本号、大小写、斜杠位置。问题四接口报 500第一步看后端控制台完整异常堆栈不要只看日志第一行。通常原因包括数据库表字段不存在MyBatis 报 SQL 异常。参数为空代码没有做空值判断。实体类字段类型和数据库字段不匹配。编码问题前端传中文时后端乱码。问题五协同过滤推荐结果为空按这个顺序排查数据库里有没有评分记录。目标用户是否已有评分记录。待推荐电影是否过滤掉了已评分电影。相似度计算时是否存在共同评分电影。如果没有任何共同评分记录结果必然为空。是否设置了“共同评分电影数小于 N 时直接跳过”的过滤条件这个条件太严也会导致结果少。问题六页面卡顿主要原因大概率在后端接口性能而不是前端。例如每次打开推荐页都实时计算所有用户的相似度数据量大的时候就会很慢。优化的思路推荐结果做缓存比如用 Redis 缓存每个用户的推荐列表24 小时失效。把物品相似度计算从实时改成定时任务提前算好存到数据库或缓存。对评分表查询做条件过滤不要一次性加载全表。这些优化不一定都要实现但至少在论文里要能说出思路。7. 系统扩展和毕业设计进阶方向如果你不满足于一个基础版本还有余力做更多功能我建议优先做下面这几个方向。它们不会破坏现有系统结构而且每一块都能在答辩里讲出一段“为什么这样做”。7.1 推荐算法扩展基础系统如果用的是基于物品的协同过滤后续可以扩展成混合推荐基于内容特征的推荐根据电影类型、导演、演员计算相似度。基于用户协同过滤作为辅助解决用户已有评分但物品相似度不高的问题。热门榜单兜底解决冷启动和推荐结果稀疏的问题。混合策略不用做得多复杂最简单的做法是给不同算法分配权重最终推荐分 0.6 × ItemCF 分数 0.4 × 热度分数。这样既能保留个性化特征又不会让推荐结果太偏门。7.2 前端交互增强初版系统只有基本的列表、详情、评分。可以增加评分雷达图展示当前用户对不同电影类型的偏好程度用 ECharts 画雷达图放在个人中心页面。推荐理由展示在推荐卡片下方写“因为你看过《xxx》”。搜索历史记录用户搜索关键词便于后续做搜索排序优化。管理员后台电影信息维护、用户管理、评分数据统计。加一个后台整个项目的工作量和完整度立刻提升一档。7.3 后端工程化增强引入 Redis 缓存用户推荐列表和电影详情。增加日志切面统一记录请求耗时。增加全局异常处理器把参数校验错误、数据库异常、推荐计算异常统一处理。引入 Spring Security 和 JWT 做权限控制。这样后端部分就有了“安全设计”这一节。7.4 关于论文或报告中可以写的重点如果这是毕业设计论文结构可以围绕以下主线需求分析和可行性分析。系统总体设计功能模块图、技术架构图、数据库 ER 图。协同过滤算法设计算法选择理由、计算公式、相似度阈值、冷启动措施。系统实现按功能模块截图展示页面。系统测试功能测试用例表 算法效果对比。总结与展望指出系统存在的不足例如数据规模较小、没有考虑用户实时行为等。推荐算法部分建议单独成章这是和普通 CRUD 项目拉开差距的地方。即使代码实现很朴素只要把公式写清楚、测试场景设计合理、你能讲明白每一步为什么这样做老师就会认为你有完整的工程思维。7.5 我给你的最终建议如果你正在做这个方向的毕业设计我最后给到的一个建议宁可用最朴素的协同过滤也别把范围铺得太大。把一条推荐链路跑通从注册登录、电影列表、用户评分、算法计算、前端推荐展示每一步都能讲出细节比写十个没验证过的“高级功能”更稳。先跑通再优化这是做全栈项目最不容易翻车的顺序。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进