news 2026/10/22 8:18:23

SpringBoot短视频推荐系统毕业设计完整复盘

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SpringBoot短视频推荐系统毕业设计完整复盘

记一次SpringBoot短视频推荐系统毕业设计的完整复盘

每年到毕业季前后,总有同学拿着“Java后端 + Vue前端”的技术栈来问我,做什么题目既好落地、又能讲出点东西来。短视频推荐系统是我这几年看来性价比很高的一个方向。它表面上是“做一个视频App后台”,实际上把用户权限、内容管理、推荐算法、前后端分离开发这些高频考点全串起来了。就算推荐部分砍到最简,光是把SpringBoot+Vue这套流程跑通,再配合一个“看得见效果”的推荐结果页,答辩和简历就都有了实打实的素材。

这篇文章不聊虚的,纯粹以过来人的视角,把从选题到落地、从数据表设计到推荐链路搭建、从前端页面联调到答辩追问点的完整过程,一步步拆开讲清楚。如果你正准备做类似的毕设,或者公司内部要快速搭一个内容分发方向的演示系统,这篇的思路可以直接拿来用。

1. 选题思路与技术选型:为什么短视频推荐系统值得做

1.1 这个题目到底在考察什么

短视频推荐系统乍一听是个“大厂项目”,但拆开看,它的核心环节不多:内容管理、用户行为采集、推荐分发、管理后台。这四个环节恰好覆盖了毕业设计最常见的能力要求:数据库设计能力、业务逻辑抽象能力、简单算法实现能力、前后端联调能力。

我之前见过不少同学选了泛泛的“XX管理系统”,代码写完之后,答辩时老师一句“这个系统的核心难点是什么”就能把人问住。但换成推荐系统,核心难点非常明确:推荐结果是怎么算出来的?为什么这个用户看到的是这些视频而不是另一些?这个问题本身就自带技术深度。

另外,这个题目还有一个隐藏优势:效果可视化。管理系统做完以后页面都是表单和表格,看不出“智能”在哪里。推荐系统不一样,用户登录后首页刷出来的内容能明显感知到“是不是越来越合口味”,演示效果好很多。

1.2 技术栈选型对比与取舍

毕设技术栈的原则只有一条:不要为了炫技选自己完全不懂的框架,要选“能讲清楚原理”的。我比较推荐下面这套组合:

层次选型理由
后端框架SpringBoot 2.7 + MyBatis-Plus生态成熟、代码量少、资料多
数据库MySQL 8.0存储用户、视频、行为等结构化数据
缓存Redis存热门视频列表、登录Token、推荐结果缓存
前端Vue 3 + Vite + Element Plus开发效率高,组件库现成
鉴权Sa-Token 或 JWT轻量,毕设不用上Spring Security全家桶
文件存储本地存储 + Nginx静态映射不依赖第三方OSS,部署简单

有同学喜欢把Spring Cloud、RabbitMQ、Elasticsearch全堆上去,结果系统复杂到连启动都费劲。我的建议是:微服务和消息队列放到“扩展思路”PPT里讲就行,真正实现的时候用单体+Redis,稳才是第一位的。

这套选型的好处在于:每个组件你都能说清楚“它是干什么的”以及“为什么选它不选别的”。比如Redis,你可以讲“用Redis缓存热门视频列表,减少数据库压力”——这就够了。

1.3 系统功能模块怎么划分

标准的短视频推荐系统可以拆成三个端:

  • 用户端(Vue页面):首页视频流、视频详情、点赞/收藏/关注、发布视频、个人中心。
  • 管理端(Vue页页面):视频审核、用户管理、分类管理、内容统计。
  • 后端服务(SpringBoot):统一提供RESTful接口,处理推荐、上传、互动、管理等全部业务逻辑。

推荐链路单独划成一个模块,放在service层里,不要跟业务代码混在一起。我当时指导的一个同学就是把推荐计算写在了controller里,后期改个参数要改三层方法,血泪教训。

这就是前后端分离架构,静态资源用Nginx部署,后端跑在8080端口,通过接口交互。

2. 数据库设计与核心表关系

2.1 核心数据表盘点

数据库是整个系统的地基,表设计的好坏直接决定后期开发的痛苦程度。我按“用户体系—内容体系—行为体系—管理辅助”四个维度来建表。

用户体系:

  • user:用户ID、昵称、头像、密码加密串、注册时间、状态。
  • follow:关注关系,user_id + follower_id 联合唯一,用于“关注的用户发布了新视频”这种feed。

内容体系:

  • video:视频ID、作者ID、标题、简介、视频URL、封面URL、分类ID、状态(草稿/待审核/已发布/下架)、发布时间、播放数、点赞数、收藏数。
  • category_info:分类ID、分类名称。
  • tag:标签表。
  • video_tag:视频和标签的多对多关联表。

行为体系:

  • user_like:用户点赞记录,user_id + video_id 联合唯一。取消点赞就删记录。
  • user_favorite:收藏记录表,结构与点赞类似。
  • view_history:浏览记录表,记录用户每次刷视频的时长、时间戳,是推荐算法的重要输入。

管理辅助:

  • admin_user:管理员账号表,与管理端登录对应。

这套表结构不算多,但足以支撑推荐算法的“数据闭环”。

2.2 行为数据表与推荐数据流

推荐系统都说“数据决定上限”,落实到表设计上,就是一定要把用户行为完整记下来。很多新手做推荐系统,表里只有用户和视频两张表,那推荐就成空中楼阁了。

行为表里最重要的字段是view_history。设计时我一般建议至少保留这几个字段:user_id、video_id、watch_duration、video_duration、create_time。为什么要有watch_duration?因为“看了多久”比“看没看”更能反映用户兴趣。完整看完30秒短视频和看了2秒就划走,应该代表完全不同的态度。

推荐的数据流可以这么理解:用户刷视频,产生行为数据,行为数据被推荐模块读取,结合user表的偏好标签和video表的分类属性,生成新的推荐候选集,再过滤掉已经看过的内容,最终形成用户的个性化feed流。这套链路是整个系统能否在答辩时说清楚的核心。

2.3 表结构设计要避开的坑

有几个雷区我见过的频率最高:

第一,密码不能明文存储。至少用BCrypt或者MD5加盐,哪怕毕设也一样。答辩老师如果看到数据库里明文密码,印象分会大打折扣。

第二,播放数和点赞数不要每次都去count自表。应该在video表里做冗余字段,点赞时直接update count,被点赞量高的数据,再走一个异步任务定期核对。

第三,行为表必须加联合唯一索引。否则用户重复点赞会生成脏数据,推荐统计直接偏掉。

另外,凡是作为查询条件的字段,比如user_like表的user_id、video_id,都要加索引。实测下来,数据量到几万条以后,没有索引的查询会明显变慢,答辩演示时前端转圈圈就很尴尬。

删除行为表之前,先确认对应的业务状态是否允许物理删除。比如点赞表可以物理删,但浏览记录一般保留。

3. 推荐链路:从行为采集到个性化排序

3.1 推荐系统的四层结构

推荐系统不管做多简单,流程上都离不开四个环节:召回、过滤、排序、兜底。

  • 召回:从全量视频里粗筛出几百个候选。
  • 过滤:把用户已经看过的、状态异常的、作者已注销的剔除。
  • 排序:按“得分”从高到低排列。
  • 兜底:如果用户没有行为数据,推荐热门视频,保证用户不会面对一片空白。

很多毕设的推荐之所以看起来“不智能”,是因为跳过了召回和排序,直接把全表按照播放量排序。那本质上就是热门排行,跟“个性化推荐”没半毛钱关系。

我用一个接地气的类比来解释四层结构:你去食堂吃饭,窗口师傅先帮你把几十道菜里你“可能不爱吃的”排除掉;再根据你平时爱吃的口味排个序;最终端给你一盘菜。师傅的口味判断就是用户的指纹画像,排除和排序就是推荐引擎的工作。

3.2 冷启动策略:新用户和新视频怎么办

冷启动是推荐系统绕不开的问题,也是答辩老师最喜欢追问的点。处理方案不追求绝对最优,但流程必须自洽。

对于新用户,还没有行为数据时,直接走“热门兜底”策略:把全局近7天播放量、点赞量、收藏量按一定权重加权求和,倒序输出。这里给一个参考公式:

score = 播放量 * 0.4 + 点赞量 * 0.35 + 收藏量 * 0.25

不用搞复杂的时间衰减,只要加一个“发布时间必须小于7天”的SQL条件,就能保证热门内容不全是老视频。

对于新视频,问题是推荐系统根本不会推它,因为它的互动数据全部是0。解决办法是打“新鲜期保护标签”:新视频在发布后24小时内默认给予一个基础权重加成,保证至少有几百次曝光,让真实行为数据产生。这也就是“随机探索”机制的简化版。

零基础的同学如果觉得这两个逻辑讲起来不够“深”,可以补一个概念:EE机制,Exploitation(利用)和Exploration(探索)。利用是推用户喜欢的内容,探索是偶尔掺几条新内容看用户反应。那句话一说,导师立刻会觉得你懂行。

3.3 基于标签偏好与协同过滤的召回实现

召回部分我建议从简单有效的方案开始:标签偏好召回 + ItemCF协同过滤召回,两个渠道的结果做一次合并,再进排序。

标签偏好召回的逻辑是这样的:维护一张user_tag_preference表,记录用户对每个标签的偏好分。用户每次看视频超过一定时长(比如超过视频总时长的一半),就把这条视频的所有标签偏好分加1;如果秒划走,减0.5。偏好分越高,说明用户对这个标签越感兴趣。

召回时,从视频表里关联video_tag,按用户偏好分从高到低取候选视频,分数作为初步得分。下面是核心代码示意:

public List<Video> recallByTagPreference(Long userId, int limit) { // 1. 查询用户最近的行为日志(只看有效的正向行为) List<ViewLog> logs = viewLogMapper.selectRecentPositive(userId, 30); // 2. 统计标签权重 Map<Long, Double> tagWeight = new HashMap<>(); for (ViewLog log : logs) { List<Long> tagIds = videoTagMapper.selectTagIdsByVideoId(log.getVideoId()); for (Long tagId : tagIds) { tagWeight.merge(tagId, 1.0, Double::sum); } } // 3. 根据标签权重召回视频候选 if (tagWeight.isEmpty()) { return videoMapper.selectHotVideos(limit); } return videoMapper.selectByTagWeights(tagWeight, limit); }

ItemCF协同过滤在毕设阶段不需要全量算,只算简化版:如果用户A喜欢了视频X,同时用户B也喜欢了视频X,那么用户B喜欢的其他视频,对用户A来说也可以作为候选。翻译成SQL和代码,就是查“偏好相似用户”再查“这些用户喜欢的视频”。

这一步的实现不建议写得太重,用定时任务每10分钟把相似度结果算一遍,存Redis,推荐时直接取。这样既能讲清楚协同过滤思想,又避免了实时计算巨大消耗。

3.4 实时热度计算与最终排序

候选集召回之后,视频列表还是乱的,需要一个统一的排序分。推荐系统的排序阶段本质上是把多个维度的特征加到一起打分。

一个适合毕设的排序公式如下:

final_score = 偏好分 * 0.5 + 热度分 * 0.3 + 新鲜度分 * 0.2

  • 偏好分来自用户标签画像对视频的匹配程度。
  • 热度分来自视频的播放、点赞、收藏的综合值。
  • 新鲜度分:发布时间越近,分越高。可以用一个时间衰减系数计算,比如这个简单公式:新鲜度分 = 1 / ln(当前时间 - 发布时间 + 2)。

把三个分加权求和,最终排序,取前50条作为一次推荐流结果。同时利用Redis缓存这套结果,key设计成“recommend:user:{userId}:page:{page}”,过期时间设为10分钟,这样用户下滑翻页时,不用每次重新计算推荐分。

推荐结果缓存过期问题要小心。如果用户刷到一半就退出去,再次进来时推荐流如果完全变了,体验会有点怪。

4. 前后端实现:SpringBoot接口与Vue页面联调

4.1 推荐流接口设计与分页策略

推荐流接口要设计得让前端好对接。我的建议是:

GET /api/recommend/feed?page=1&size=10

返回结构:

{ "code": 200, "data": { "list": [ { "videoId": 101, "videoUrl": "/static/video/xxx.mp4", "coverUrl": "/static/img/xxx.jpg", "title": "今天拍了一条猫", "authorName": "某某同学", "likeCount": 320, "hasLiked": false, "tags": ["萌宠", "日常"] } ], "hasMore": true, "nextPage": 2 } }

前端用Vue3的滚动加载实现,滚动到底部时请求下一页。这个交互方式是短视频App的标配,实现起来也很简单:给页面容器绑定滚动事件,当scrollTop + clientHeight > scrollHeight - 200时,触发下一页加载。

分页这里注意一个细节:不要用传统偏移量分页的下拉刷新,而是用“游标”的概念。因为推荐流是动态变化的,如果用页码,用户翻到第3页时第1页的数据可能已经更新了,会出现重复视频。简单做法就是上面的page+size,但配合一个dedupe策略:前端把本轮会话已经展示过的videoId收集起来,请求下一页时带上这些ID,后端过滤掉。

4.2 管理端的视频审核与分类管理

内容管理后台是“短视频推荐与内容管理系统”的另一个重头戏,也是很多同学容易漏掉的部分。推荐流做得再好,管理端如果没有审核和上下架能力,系统的“管理”两个字就名存实亡。

管理端的技术栈我建议用Vue3 + Element Plus,因为表格、弹窗、表单这些管理场景Element Plus做得非常成熟。视频审核页面做成一个表格列表,每一行显示:视频封面、标题、作者、上传时间、状态,操作列放“通过”和“下架”按钮,这两按钮背后调用的接口是:

PUT /api/admin/video/{videoId}/status

请求体里带上status(枚举值:0草稿、1待审核、2已发布、3已下架)。后端拿到请求后,先更新video表状态字段,然后清理Redis里对应的推荐缓存,这就是“状态变更后要触发缓存刷新”的意识。

分类管理页面就是简单的CRUD:新增分类、修改分类名称、删除分类。删除分类时要记得处理视频表外键引用,不能直接删,要先做“该分类下是否有视频”的校验。

4.3 视频上传与预处理链路

视频上传是整个系统里面坑比较多的环节,需要重点说明。前端上传可以直接用Element Plus的upload组件,但要注意几点:

第一,上传接口要单独设计,不要跟其他业务接口混在一起。我建议拆两个接口:一个负责上传文件并返回文件ID和URL,一个负责把视频内容和文件关联起来。

POST /api/upload/video // 传视频文件 POST /api/video/publish // 发布视频(填标题、分类、封面、视频文件ID)

第二,视频文件需要做大小限制和类型校验。SpringBoot端可以配置:

spring: servlet: multipart: max-file-size: 100MB max-request-size: 100MB

类型校验不要只依赖前端的accept属性,后端也要校验Content-Type是否是video/mp4、video/quicktime这些常见类型。

第三,视频封面可以做“前端上传后截取第一帧”,或者干脆做成“用户手动上传封面图”,因为服务端用Java做视频截图处理需要引入FFmpeg,复杂度会上升不少。毕设阶段,我的建议是直接让用户传封面图,开发量小,演示效果好。

4.4 前后端联调时最容易翻车的几个环节

前后端联调是整个项目里我见过同学耗时最多的阶段,问题往往集中在以下几个点:

跨域问题:前端页面9000端口,后端接口8080端口,隔着一道CORS。后端的解决方案是统一开启跨域配置,要么写一个CorsFilter,要么在Controller上加@CrossOrigin。建议全局配置一次:

@Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOriginPatterns("*") .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowCredentials(true) .maxAge(3600); } }

图片和视频的URL直接打不开:本地存储的文件如果只存在磁盘路径里,前端访问不了。解决办法是配一个Nginx静态映射,把磁盘的upload目录映射成一个HTTP路径。Nginx的关键配置:

location /static/ { alias /data/app/upload/; expires 7d; }

文件名的处理:前端上传的中文文件名,后端要重命名,避免乱码和路径穿越风险。用UUID + 原始扩展名是最稳的。

5. 常见问题与排查技巧实录

5.1 推荐结果不准:数据稀疏怎么治

我在实际指导过程中,遇到过的新手最常见的问题,就是推荐结果完全“不相关”。用户明明看了好几个萌宠视频,推荐流里却全是美女跳舞。排查下来,原因基本绕不开这三个:

第一,用户行为数据太少。解决方法是减少偏好统计的阈值,比如把“超过50%时长算正反馈”放宽到“超过30%且观看时间大于10秒就算”。第二,标签关联设计不合理。视频没有正确打标签,偏好标签匹配就无从谈起。第三,排序公式中热门分占比过高,个性化信号被稀释了。可以适当调整,把偏好分从0.5提升到0.6。

5.2 重复推荐与疲劳度

用户刷了十几次之后,发现推荐流里不断出现已经看过的视频。这个问题本质上是因为过滤阶段漏了“浏览历史”这一环。

解决方案有两个:一是在召回时SQL排除view_history表里已有的videoId;二是在排序后、返回前用Java内存过滤,用Set收集已看过的ID做排除。两者都做更稳。另外,可以把“最近3天内看过的视频”单独存Redis,key值为“user:seen:{userId}”,过期时间72小时,这样过滤查询很快。

5.3 并发下的缓存与性能

答辩现场如果老师要求看系统性能,并发问题是绕不开的话题。推荐计算如果每次都实时跑SQL联表,在数据量变大之后会越来越慢。我的建议是:把“排序结果”整体缓存到Redis,按userId维度存,10分钟过期。只有缓存过期时才重新计算。

热门视频列表也可以做缓存,比如“hot:videos”这个key,每天凌晨清理一次。用Redis的List或ZSet结构存储,查询时直接LRange取前50条,能扛住不小的流量。

5.4 答辩时的高频追问点与回应思路

每年答辩时,推荐系统被问得最多的问题就那几个,提前准备就不会慌。

“你这个推荐算法相比协同过滤有什么异同?”回应的思路是:协同过滤是经典的二阶段方案,我实现了ItemCF的简化版;同时,在工程落地时加了标签偏好、热度兜底和时间衰减,组成了一个混合推荐策略。这句话虽然在算法层面不够“硬核”,但能在工程层面展示自己的思考。

“如果数据量到千万级,你的推荐系统会怎么优化?”这种问题不是真让你改架构,而是看有没有扩展意识。回答可以提三个方向:用消息队列异步处理行为日志、引入专门的服务器存储用户向量并做近似检索、把热门推荐和实时推荐拆成两条链路分开部署。每一个都是加分项。

“你的推荐会不会导致信息茧房?”这个问题我觉得反而最好回答,因为你只要做了“随机探索”机制,就可以很自信地说:系统在排序时会保留一定比例的新内容位,保证用户能看到新类型的内容。

写在最后的心里话

这个项目带着我前前后后带过不少同学做完,每轮回头看都能有些新体会。如果让我再做一个短视频推荐系统,我一定在项目初期就把“日志采集”的代码写齐,而不是等推荐效果不行了再回头补行为数据。数据是推荐系统的燃料,这个道理做几次就懂了。

还想提醒一句:别想着把推荐算法一步到位做到大厂水平,那本来也不是一个毕设的目标。把链路跑通、把核心逻辑讲透、把工程细节做完整,这套系统和背后的思考过程,足以证明你的能力。

如果你正在纠结怎么做推荐流去重,或者卡在Vue端视频播放组件的封装上,欢迎按这个思路先把骨架搭起来。系统能转起来之后,哪怕算法调参再笨拙,你也已经跑赢大多数只做了管理系统的毕业设计了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/22 8:17:35

海康EHOME SDK实战:道闸控制与LED信息下发开发指南

简介&#xff1a;本资源为海康威视HCEhomeSDK V2.1.7.1开发包&#xff0c;面向从事智慧停车、社区门禁及道闸系统集成的Windows 64位开发者&#xff0c;提供接入抓拍机、LED显示屏与停车道闸所需的完整工具链。压缩包共184个文件&#xff0c;约11.84MB&#xff0c;以66个h头文件…

作者头像 李华
网站建设 2026/10/22 8:17:29

Nginx日志分析实战:从log_format到慢请求根因定位

1. 为什么盯着Nginx日志看&#xff0c;比调优配置更值得花时间&#xff1f; 很多人一提到Nginx性能问题&#xff0c;第一反应是改 worker_processes 、调 keepalive_timeout 、加 gzip on ——这些当然重要&#xff0c;但真正拖垮线上服务的&#xff0c;往往不是参数本身…

作者头像 李华
网站建设 2026/10/22 8:17:25

企业短信平台源码解析:从asmx接口到批量发送任务

简介&#xff1a;企业信使企信通短信平台是一套面向各行业企业集团的短信通信解决方案&#xff0c;适合需要将短信能力嵌入自有业务系统的开发与运维人员&#xff0c;以及关注客户关系管理、市场营销、内部通知等场景的技术团队。平台以稳定可靠、模块化、开放架构和高灵活性为…

作者头像 李华
网站建设 2026/10/22 8:16:33

混凝土泵压力监测物联网方案:从传感器选型到堵管预警实战

1. 方案整体拆解&#xff1a;为什么混凝土泵需要物联网级压力监测 干混凝土泵送这行的人都知道&#xff0c;堵管、爆管、液压系统故障这些事&#xff0c;靠司机耳朵听、眼睛看、手摸振动&#xff0c;不是不行&#xff0c;而是反应太慢。一根输送管从泵口到浇筑面几十米甚至上百…

作者头像 李华
网站建设 2026/10/22 8:16:31

SpringBoot+Vue+MyBatis+MySQL人事管理系统前后端分离实战

1. 项目概述与核心需求解析前后端分离是这几年企业级项目里绕不开的架构模式&#xff0c;尤其是人事管理系统这种典型的CRUD密集型业务系统。市面上能跑的源码不少&#xff0c;但真正把SpringBoot、Vue、MyBatis、MySQL这几样东西缝合得干净、能让人看得懂、还能顺利跑起来的&a…

作者头像 李华
网站建设 2026/10/22 8:16:30

前端生产环境UUID生成实战:从randomUUID到降级方案与避坑指南

前端项目里要不要自己生成 uuid&#xff1f;这个问题以前我都是随口答一句“需要的时候引个库不就行了”。直到有次我在一个离线数据同步的项目里被重复 ID 坑了一整晚&#xff0c;才发现“前端生产 uuid”这几个字里&#xff0c;真正值钱的是“生产”两个字。浏览器端生成 UUI…

作者头像 李华