1. 项目概述
这个基于Spring Boot的隧道云视频监控管理信息平台是我最近完成的一个毕业设计项目,它整合了视频监控、数据管理和用户权限控制等功能模块。作为一个完整的B/S架构系统,它特别适合作为计算机相关专业的毕业设计选题,也完全可以作为实际工程项目的原型进行二次开发。
我在开发过程中采用了当前主流的Java技术栈:Spring Boot作为后端框架,Vue.js负责前端交互,MySQL存储数据,MyBatis Plus简化数据库操作。这种技术组合既保证了系统的稳定性和性能,又降低了开发复杂度,特别适合学生项目开发。
2. 系统架构设计
2.1 MVC分层架构
系统采用标准的MVC设计模式,将代码结构清晰地划分为以下几个层次:
视图层(View):使用Vue.js框架构建响应式前端界面,通过Axios与后端API交互。我特别设计了动态路由和权限控制,确保不同角色的用户看到不同的界面元素。
控制层(Controller):Spring Boot的RestController处理HTTP请求,负责参数校验、权限验证和响应封装。这里我使用了统一的异常处理机制,返回规范的JSON格式数据。
服务层(Service):包含核心业务逻辑,如视频流处理、用户权限校验等。我采用了接口与实现分离的方式,便于单元测试和后期维护。
数据访问层(DAO):通过MyBatis Plus实现,简化了CRUD操作。我特别设计了动态SQL生成器,可以灵活应对各种查询条件。
2.2 B/S架构优势
选择B/S架构主要基于以下几点考虑:
-
零客户端安装:用户只需通过浏览器即可访问系统,特别适合监控场景下多终端访问的需求。
-
集中式管理:所有业务逻辑和数据都集中在服务器端,便于维护和升级。
-
跨平台兼容:系统可以在Windows、Linux、Mac等各种操作系统上运行,甚至支持移动端访问。
-
安全性:通过HTTPS协议传输数据,配合后端权限控制,确保系统安全。
3. 技术栈详解
3.1 Spring Boot后端框架
Spring Boot极大简化了项目配置和部署过程。我在项目中主要利用了以下特性:
-
自动配置:通过starter依赖自动配置各种组件,如Web MVC、MyBatis、Redis等。
-
嵌入式Tomcat:无需额外安装Web服务器,直接打包成可执行JAR。
-
Actuator监控:内置健康检查、性能监控等端点,方便运维。
-
Profile配置:区分开发、测试、生产环境,使用不同的配置参数。
一个典型的Controller示例:
java复制@RestController
@RequestMapping("/api/video")
public class VideoController {
@Autowired
private VideoService videoService;
@GetMapping("/list")
@PreAuthorize("hasRole('ADMIN')")
public Result listVideos(@RequestParam Map<String, Object> params) {
PageUtils page = videoService.queryPage(params);
return Result.ok().put("page", page);
}
@PostMapping("/upload")
public Result uploadVideo(@RequestParam("file") MultipartFile file) {
String url = videoService.uploadVideo(file);
return Result.ok().put("url", url);
}
}
3.2 Vue.js前端框架
前端采用Vue 3组合式API开发,主要特点包括:
-
组件化开发:将界面拆分为可复用的组件,如VideoPlayer、UserTable等。
-
Vue Router:实现前端路由,支持动态路由和导航守卫。
-
Pinia状态管理:集中管理应用状态,如用户信息、权限数据等。
-
Element Plus:使用这套UI组件库快速构建美观的界面。
一个视频列表组件示例:
vue复制<template>
<el-table :data="videoList" style="width: 100%">
<el-table-column prop="name" label="视频名称" />
<el-table-column prop="createTime" label="上传时间" />
<el-table-column label="操作">
<template #default="scope">
<el-button @click="playVideo(scope.row)">播放</el-button>
</template>
</el-table-column>
</el-table>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { getVideoList } from '@/api/video'
const videoList = ref([])
const loadData = async () => {
const res = await getVideoList()
videoList.value = res.data
}
onMounted(() => {
loadData()
})
const playVideo = (row) => {
// 播放视频逻辑
}
</script>
3.3 MySQL数据库设计
数据库设计遵循第三范式,主要表结构包括:
用户表(sys_user):
sql复制CREATE TABLE `sys_user` (
`user_id` bigint NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL COMMENT '用户名',
`password` varchar(100) NOT NULL COMMENT '密码',
`salt` varchar(20) COMMENT '加密盐值',
`email` varchar(100) COMMENT '邮箱',
`mobile` varchar(20) COMMENT '手机号',
`status` tinyint COMMENT '状态 0:禁用 1:正常',
`create_time` datetime COMMENT '创建时间',
PRIMARY KEY (`user_id`),
UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='系统用户';
视频信息表(video_info):
sql复制CREATE TABLE `video_info` (
`video_id` bigint NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL COMMENT '视频名称',
`url` varchar(255) NOT NULL COMMENT '视频地址',
`size` bigint COMMENT '文件大小(字节)',
`duration` int COMMENT '时长(秒)',
`tunnel_id` bigint COMMENT '所属隧道ID',
`create_user_id` bigint COMMENT '上传用户ID',
`create_time` datetime COMMENT '上传时间',
PRIMARY KEY (`video_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='视频信息';
隧道信息表(tunnel_info):
sql复制CREATE TABLE `tunnel_info` (
`tunnel_id` bigint NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL COMMENT '隧道名称',
`location` varchar(255) COMMENT '位置信息',
`length` decimal(10,2) COMMENT '隧道长度(米)',
`status` tinyint DEFAULT 1 COMMENT '状态 0:禁用 1:正常',
`create_time` datetime COMMENT '创建时间',
`update_time` datetime COMMENT '更新时间',
PRIMARY KEY (`tunnel_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='隧道信息';
4. 核心功能实现
4.1 视频监控模块
视频监控是系统的核心功能,主要实现以下特性:
-
视频上传与存储:
- 支持MP4、AVI等常见格式
- 文件分块上传,支持断点续传
- 使用MinIO对象存储服务保存视频文件
-
视频流播放:
- 基于HLS协议实现自适应码率流媒体
- 前端使用video.js播放器
- 支持全屏、倍速播放等常见功能
-
视频分析:
- 集成OpenCV进行简单视频分析
- 支持移动物体检测
- 异常事件标记与报警
关键代码示例(视频上传):
java复制public String uploadVideo(MultipartFile file) throws IOException {
// 验证文件类型
String originalFilename = file.getOriginalFilename();
String fileType = FilenameUtils.getExtension(originalFilename);
if (!Arrays.asList("mp4", "avi", "mov").contains(fileType.toLowerCase())) {
throw new RuntimeException("不支持的文件类型");
}
// 生成存储路径
String datePath = new SimpleDateFormat("yyyy/MM/dd").format(new Date());
String filename = UUID.randomUUID() + "." + fileType;
String objectName = "videos/" + datePath + "/" + filename;
// 上传到MinIO
minioClient.putObject(
PutObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.stream(file.getInputStream(), file.getSize(), -1)
.contentType(file.getContentType())
.build());
return minioEndpoint + "/" + bucketName + "/" + objectName;
}
4.2 用户权限管理
系统采用RBAC(基于角色的访问控制)模型,主要功能包括:
-
用户管理:
- 用户CRUD操作
- 密码加密存储(BCrypt)
- 账户状态控制
-
角色管理:
- 定义不同角色(管理员、操作员、查看员等)
- 角色权限分配
-
权限控制:
- 接口级别权限验证
- 菜单权限动态加载
- 按钮级别权限控制
权限验证拦截器示例:
java复制public class PermissionInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
// 获取请求路径
String requestURI = request.getRequestURI();
// 获取用户权限列表
Set<String> permissions = getUserPermissions(request);
// 检查权限
if (!permissions.contains(requestURI)) {
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write(JSON.toJSONString(Result.error(403, "无访问权限")));
return false;
}
return true;
}
private Set<String> getUserPermissions(HttpServletRequest request) {
// 从token或session中获取用户权限
// ...
}
}
5. 系统部署与测试
5.1 部署方案
系统支持多种部署方式:
-
开发环境:
- 直接运行Spring Boot应用
- 使用H2内存数据库
- Vue开发服务器热加载
-
生产环境:
- 打包为Docker容器
- Nginx反向代理和负载均衡
- MySQL主从复制
- Redis缓存
Docker Compose示例:
yaml复制version: '3'
services:
app:
image: tunnel-monitor:1.0
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
- DB_URL=jdbc:mysql://mysql:3306/tunnel
- DB_USER=root
- DB_PASS=123456
depends_on:
- mysql
- redis
mysql:
image: mysql:8.0
environment:
- MYSQL_ROOT_PASSWORD=123456
- MYSQL_DATABASE=tunnel
volumes:
- mysql_data:/var/lib/mysql
redis:
image: redis:6.0
ports:
- "6379:6379"
minio:
image: minio/minio
ports:
- "9000:9000"
environment:
- MINIO_ROOT_USER=admin
- MINIO_ROOT_PASSWORD=password
command: server /data
volumes:
mysql_data:
5.2 性能测试
使用JMeter对系统进行压力测试,主要指标如下:
-
用户登录接口:
- 100并发用户,平均响应时间<500ms
- 错误率<0.1%
-
视频列表查询:
- 50并发用户,平均响应时间<300ms
- 支持分页查询,每页20条记录
-
视频上传:
- 10并发上传100MB文件,平均耗时<30s
- 支持断点续传
测试结果示例:
| 测试场景 | 并发用户数 | 平均响应时间 | 错误率 | 吞吐量 |
|---|---|---|---|---|
| 用户登录 | 100 | 420ms | 0% | 85/s |
| 视频查询 | 50 | 280ms | 0% | 120/s |
| 视频上传 | 10 | 28s | 0% | 0.3/s |
6. 开发经验与技巧
在开发这个系统的过程中,我积累了一些有价值的经验:
-
Spring Boot配置优化:
- 使用
@ConfigurationProperties管理配置项 - 合理设置连接池参数(HikariCP)
- 启用GZIP压缩减少网络传输
- 使用
-
Vue性能优化:
- 组件懒加载
- 合理使用v-if和v-show
- 防抖节流处理高频事件
-
数据库优化:
- 为常用查询字段添加索引
- 避免SELECT *,只查询需要的字段
- 使用EXPLAIN分析慢查询
-
异常处理技巧:
- 统一异常处理返回规范格式
- 区分业务异常和系统异常
- 记录详细的错误日志
一个实用的日志切面示例:
java复制@Aspect
@Component
@Slf4j
public class LogAspect {
@Pointcut("execution(* com.example.tunnel.controller..*.*(..))")
public void controllerPointcut() {}
@Around("controllerPointcut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
// 获取请求信息
ServletRequestAttributes attributes =
(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 记录请求日志
log.info("请求开始: {} {}, 参数: {}",
request.getMethod(),
request.getRequestURI(),
joinPoint.getArgs());
try {
Object result = joinPoint.proceed();
long endTime = System.currentTimeMillis();
// 记录响应日志
log.info("请求结束: {} {}, 耗时: {}ms",
request.getMethod(),
request.getRequestURI(),
endTime - startTime);
return result;
} catch (Exception e) {
log.error("请求异常: {} {}, 异常: {}",
request.getMethod(),
request.getRequestURI(),
e.getMessage(), e);
throw e;
}
}
}
7. 常见问题与解决方案
在开发和部署过程中,我遇到了一些典型问题,以下是解决方案:
-
视频播放卡顿:
- 原因:原始视频码率过高
- 解决:使用FFmpeg转码为多码率HLS流
- 命令:
ffmpeg -i input.mp4 -c:v libx264 -crf 23 -preset fast -c:a aac -b:a 128k -f hls -hls_time 10 -hls_list_size 0 output.m3u8
-
大文件上传失败:
- 原因:Spring Boot默认文件大小限制
- 解决:配置
spring.servlet.multipart.max-file-size和max-request-size
-
跨域问题:
- 原因:前后端分离架构导致的跨域限制
- 解决:配置CORS过滤器或使用Nginx反向代理
-
MyBatis Plus分页失效:
- 原因:未配置分页插件
- 解决:添加分页插件配置类:
java复制@Configuration public class MyBatisPlusConfig { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); return interceptor; } } -
Vue生产环境空白页:
- 原因:资源路径配置错误
- 解决:在vue.config.js中配置publicPath:
javascript复制module.exports = { publicPath: process.env.NODE_ENV === 'production' ? '/tunnel-monitor/' : '/' }
这个项目从设计到实现大约花费了3个月时间,期间遇到了各种技术挑战,但最终都找到了解决方案。通过这个项目,我不仅巩固了Spring Boot和Vue的技术栈,还学到了很多关于视频处理、系统设计和性能优化的实用知识。对于想要学习全栈开发的同学,我建议可以从这样的实际项目入手,逐步掌握各项技术。