1. 项目背景与核心价值
校园视频平台系统是当前高校信息化建设中的重要组成部分。随着在线教育、远程授课、校园文化传播等需求的快速增长,传统基于FTP或简单网页的视频分享方式已经无法满足师生对视频内容管理、互动交流和个性化推荐的需求。
这个毕业设计项目采用SpringBoot+Vue的前后端分离架构,构建了一个功能完备的校园视频平台。我在实际开发过程中发现,这类系统需要特别关注三个核心问题:视频的高效存储与传输、用户权限的精细化管理、以及平台的可扩展性设计。
2. 技术架构解析
2.1 后端技术选型
SpringBoot 2.7作为后端框架,主要基于以下考虑:
- 内嵌Tomcat服务器,简化部署流程
- 自动配置特性大幅减少XML配置
- 丰富的Starter依赖(特别是Spring Security和Spring Data JPA)
- 完善的RESTful API支持
数据库选用MySQL 8.0,主要特性利用:
-- 视频表核心字段设计 CREATE TABLE `video` ( `id` bigint NOT NULL AUTO_INCREMENT, `title` varchar(255) NOT NULL, `description` text, `cover_url` varchar(512), `video_url` varchar(512) NOT NULL, `duration` int DEFAULT 0, `status` tinyint DEFAULT 1, `user_id` bigint NOT NULL, `category_id` int DEFAULT NULL, `view_count` int DEFAULT 0, `create_time` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), KEY `idx_category` (`category_id`), KEY `idx_user` (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;2.2 前端技术方案
Vue 3 + Element Plus的组合提供了:
- 响应式布局适配多终端
- 组件化开发提升复用性
- Axios实现API统一管理
- Vue Router处理前端路由
- Vuex进行状态管理
典型页面组件结构:
src/ ├── api/ # API接口定义 ├── assets/ # 静态资源 ├── components/ # 公共组件 │ ├── VideoCard.vue │ ├── Pagination.vue │ └── ... ├── router/ # 路由配置 ├── store/ # Vuex状态 ├── utils/ # 工具函数 └── views/ # 页面视图 ├── Home.vue ├── Video/ │ ├── Detail.vue │ └── Upload.vue └── ...3. 核心功能实现
3.1 视频上传与处理
采用分片上传策略解决大文件传输问题:
// SpringBoot后端分片上传处理 @PostMapping("/upload/chunk") public ResponseEntity<?> uploadChunk( @RequestParam("file") MultipartFile file, @RequestParam("chunkNumber") int chunkNumber, @RequestParam("totalChunks") int totalChunks, @RequestParam("identifier") String identifier) { // 1. 创建临时目录存储分片 String tempDir = "upload/temp/" + identifier; File chunkFile = new File(tempDir, chunkNumber + ".part"); // 2. 保存分片文件 file.transferTo(chunkFile); // 3. 检查是否所有分片已上传 if (chunkNumber == totalChunks) { mergeChunks(identifier, tempDir); } return ResponseEntity.ok().build(); }重要提示:实际部署时需要配置Nginx限制上传大小,避免内存溢出:
client_max_body_size 1024m;
3.2 视频转码与播放
使用FFmpeg进行视频处理:
# 转码为HLS格式 ffmpeg -i input.mp4 \ -profile:v baseline -level 3.0 \ -start_number 0 -hls_time 10 -hls_list_size 0 \ -f hls output.m3u8前端播放器采用Video.js:
// Vue组件中初始化播放器 mounted() { this.player = videojs(this.$refs.videoPlayer, { controls: true, fluid: true, sources: [{ src: this.videoUrl, type: 'application/x-mpegURL' }] }); }4. 系统安全设计
4.1 权限控制模型
基于RBAC实现五级权限体系:
- 游客:仅可浏览公开视频
- 学生:上传/管理个人视频
- 教师:管理课程相关视频
- 院系管理员:管理本院系内容
- 系统管理员:全局管理
Spring Security配置示例:
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/admin/**").hasRole("ADMIN") .antMatchers("/teacher/**").hasAnyRole("TEACHER", "ADMIN") .antMatchers("/upload").authenticated() .anyRequest().permitAll() .and() .formLogin() .loginPage("/login") .defaultSuccessUrl("/") .and() .logout() .logoutSuccessUrl("/"); } }4.2 敏感操作审计
通过AOP记录关键操作日志:
@Aspect @Component public class AuditLogAspect { @Autowired private AuditLogRepository logRepository; @AfterReturning( pointcut = "@annotation(com.example.demo.annotation.AuditLog)", returning = "result") public void afterReturning(JoinPoint joinPoint, Object result) { MethodSignature signature = (MethodSignature) joinPoint.getSignature(); AuditLog annotation = signature.getMethod().getAnnotation(AuditLog.class); AuditLogEntity log = new AuditLogEntity(); log.setOperation(annotation.value()); log.setParams(JsonUtils.toJson(joinPoint.getArgs())); log.setResult(JsonUtils.toJson(result)); log.setCreateTime(new Date()); logRepository.save(log); } }5. 性能优化实践
5.1 缓存策略设计
采用多级缓存架构:
- 前端:LocalStorage缓存用户偏好
- 网关层:Redis缓存热门视频列表
- 服务层:Caffeine缓存频繁访问的视频元数据
- 数据库:MySQL查询缓存
缓存更新策略对比:
| 策略 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 定时刷新 | 实现简单 | 实时性差 | 变化不频繁的数据 |
| 主动失效 | 实时性强 | 维护成本高 | 关键业务数据 |
| 延迟双删 | 平衡实时与性能 | 实现复杂 | 高并发场景 |
5.2 数据库优化
视频查询的典型优化方案:
-- 优化前(全表扫描) SELECT * FROM video WHERE title LIKE '%spring%'; -- 优化后(使用全文索引) ALTER TABLE video ADD FULLTEXT INDEX ft_title (title); SELECT * FROM video WHERE MATCH(title) AGAINST('spring');分页查询优化:
// 错误做法:先查询全部再截取 List<Video> list = videoRepository.findAll(); return list.stream().skip(offset).limit(pageSize).collect(Collectors.toList()); // 正确做法:数据库层分页 Pageable pageable = PageRequest.of(pageNum, pageSize, Sort.by("createTime").descending()); return videoRepository.findAll(pageable);6. 部署与监控
6.1 容器化部署
Docker Compose编排方案:
version: '3' services: mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: video_platform ports: - "3306:3306" volumes: - ./mysql/data:/var/lib/mysql redis: image: redis:6 ports: - "6379:6379" backend: build: ./backend ports: - "8080:8080" depends_on: - mysql - redis frontend: build: ./frontend ports: - "80:80"6.2 监控方案
Prometheus + Grafana监控体系:
- Spring Boot Actuator暴露指标
- Prometheus定时抓取数据
- Grafana配置监控看板
关键监控指标:
- 系统层面:CPU/Memory/Disk使用率
- 应用层面:JVM内存、GC次数
- 业务层面:并发用户数、视频播放量
- 异常监控:错误日志、慢查询
7. 开发经验总结
在实际开发过程中,有几个关键点需要特别注意:
视频存储方案选择:
- 小规模部署:直接使用服务器本地存储
- 中大规模:MinIO分布式存储
- 生产环境:阿里云OSS等云存储服务
跨域问题解决方案:
// SpringBoot全局跨域配置 @Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("*") .allowedMethods("GET", "POST", "PUT", "DELETE") .allowCredentials(true) .maxAge(3600); } }- 前端性能优化技巧:
- 使用Intersection Observer实现懒加载
- 对视频列表进行虚拟滚动处理
- 关键路由组件使用异步加载
// 路由懒加载 const VideoDetail = () => import('./views/Video/Detail.vue');这个项目完整实现了从视频上传、转码、存储到播放的全流程管理,并针对校园场景做了权限和内容管理的特殊设计。在开发过程中,特别要注意视频处理对服务器资源的消耗,建议在实际部署时单独部署转码服务,避免影响主应用的稳定性。