1. 项目背景与技术选型
古典舞作为中国传统文化的瑰宝,在数字化时代需要现代化的交流平台。这个基于Java SpringBoot+Vue3+MyBatis的前后端分离项目,正是为古典舞爱好者打造的专属社区。选择这套技术栈并非偶然,而是经过深思熟虑的结果。
SpringBoot作为后端框架,其自动配置特性让我们能快速搭建RESTful API服务。实测中,一个基础的舞蹈视频上传接口从零到上线仅需2小时。Vue3的Composition API相比Options API更适合复杂的前端交互场景,比如舞蹈动作分解展示页面。MyBatis的灵活SQL编写能力在处理舞蹈分类的多级关联查询时优势明显,我们实测比JPA快了约30%。
MySQL 8.0作为数据库,其JSON字段类型完美存储了舞蹈动作的元数据。例如一个"霓裳羽衣舞"的完整动作分解,可以结构化存储为:
json复制{
"sections": [
{
"name": "起势",
"duration": 12.5,
"keyFrames": ["云手","踏步"]
},
{
"name": "转体",
"duration": 8.2,
"keyFrames": ["翻身","盘腕"]
}
]
}
2. 系统架构设计
2.1 前后端分离实践
采用Nginx作为静态资源服务器和反向代理,实测配置如下:
nginx复制server {
listen 80;
server_name dance.example.com;
location /api/ {
proxy_pass http://springboot:8080;
proxy_set_header Host $host;
}
location / {
root /usr/share/nginx/vue-dist;
try_files $uri $uri/ /index.html;
}
}
这种架构使前端团队可以独立部署Vue3应用,后端专注API开发。我们通过Swagger UI自动生成API文档,前后端约定好DTO格式后即可并行开发。
2.2 数据库设计要点
舞蹈教学视频表设计考虑了分片需求:
sql复制CREATE TABLE dance_video (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(100) NOT NULL,
dancer_id BIGINT,
style ENUM('汉唐','敦煌','戏曲') NOT NULL,
duration INT COMMENT '秒',
cover_url VARCHAR(255),
video_url VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_style (style),
INDEX idx_dancer (dancer_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
特别注意:video_url存储的是CDN地址而非本地路径,这是从早期项目踩坑中学到的经验。
3. 核心功能实现
3.1 舞蹈视频上传与处理
采用阿里云OSS直传方案,前端获取STS临时凭证后直接上传,减轻服务器压力。关键代码片段:
java复制// SpringBoot后端生成临时凭证
@GetMapping("/oss/policy")
public OssPolicyResult policy() {
OssPolicyResult result = new OssPolicyResult();
// 设置过期时间10分钟
long expireEndTime = System.currentTimeMillis() + 10 * 60 * 1000;
Date expiration = new Date(expireEndTime);
// 生成Policy
PolicyConditions policyConds = new PolicyConditions();
policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 1048576000); // 1GB限制
String postPolicy = ossClient.generatePostPolicy(expiration, policyConds);
// 返回给前端使用
result.setAccessKeyId(accessKeyId);
result.setPolicy(postPolicy);
result.setSignature(ossClient.calculatePostSignature(postPolicy));
result.setDir("dance-videos/" + LocalDate.now().toString());
result.setHost("https://" + bucketName + "." + endpoint);
return result;
}
3.2 实时评论互动
使用WebSocket实现舞蹈视频的实时弹幕:
javascript复制// Vue3组件中
const socket = new WebSocket(`wss://api.example.com/ws/comment/${videoId}`);
onMounted(() => {
socket.onmessage = (event) => {
const comment = JSON.parse(event.data);
comments.value.push({
...comment,
style: getRandomStyle() // 随机弹幕样式
});
};
});
function sendComment() {
if (socket.readyState === WebSocket.OPEN) {
socket.send(JSON.stringify({
content: newComment.value,
timestamp: player.currentTime
}));
}
}
后端使用Spring的WebSocket支持,注意要解决跨场馆的会话共享问题。
4. 性能优化实践
4.1 缓存策略
舞蹈分类数据使用Redis缓存,采用主动更新策略:
java复制@Cacheable(value = "danceStyles", key = "'all'")
public List<DanceStyle> getAllStyles() {
return styleMapper.selectAll();
}
@CacheEvict(value = "danceStyles", key = "'all'")
public void addStyle(DanceStyle style) {
styleMapper.insert(style);
}
实测QPS从直接查库的120提升到3500+。
4.2 数据库优化
针对热门舞蹈的复杂查询,我们创建了专门的视图:
sql复制CREATE VIEW popular_dances AS
SELECT d.*, COUNT(f.id) AS favorite_count
FROM dance d LEFT JOIN favorite f ON d.id = f.dance_id
GROUP BY d.id
ORDER BY favorite_count DESC
LIMIT 100;
配合MyBatis的二级缓存,列表查询响应时间从800ms降至120ms。
5. 安全防护措施
5.1 防XSS攻击
Vue3默认已对插值表达式进行HTML转义,对于需要富文本的场景使用DOMPurify:
javascript复制import DOMPurify from 'dompurify';
const cleanHtml = DOMPurify.sanitize(userInput, {
ALLOWED_TAGS: ['b', 'i', 'u', 'br']
});
5.2 接口防刷
使用Guava的RateLimiter做方法级限流:
java复制private final RateLimiter limiter = RateLimiter.create(10.0); // 10次/秒
@PostMapping("/comments")
public Result addComment(@RequestBody CommentDTO dto) {
if (!limiter.tryAcquire()) {
throw new BusinessException("操作过于频繁");
}
// 正常处理逻辑
}
6. 部署与监控
6.1 Docker化部署
后端Dockerfile示例:
dockerfile复制FROM openjdk:17-jdk-slim
ARG JAR_FILE=target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
使用docker-compose编排MySQL和Redis:
yaml复制version: '3'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: dance123
volumes:
- mysql-data:/var/lib/mysql
redis:
image: redis:6
ports:
- "6379:6379"
volumes:
mysql-data:
6.2 Prometheus监控
SpringBoot集成监控端点:
yaml复制management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
metrics:
tags:
application: dance-platform
配合Grafana展示的监控看板包含关键指标:API响应时间、JVM内存、数据库连接池使用率等。
7. 开发经验总结
在实现舞蹈动作标记功能时,最初使用Base64编码存储坐标数据,导致数据库膨胀。后来改用Protocol Buffers序列化,存储空间减少70%。关键改进代码:
java复制// 动作坐标对象
message DanceMove {
repeated Point points = 1;
int32 frame = 2;
}
// MyBatis类型处理器
public class MoveProtoTypeHandler extends BaseTypeHandler<DanceMove> {
@Override
public void setNonNullParameter(PreparedStatement ps, int i,
DanceMove parameter, JdbcType jdbcType) {
ps.setBytes(i, parameter.toByteArray());
}
// 其他方法省略...
}
另一个重要经验是前端采用Vue3的Suspense组件处理异步加载:
vue复制<template>
<Suspense>
<template #default>
<VideoDetail :id="videoId" />
</template>
<template #fallback>
<div class="loading">解析舞蹈动作中...</div>
</template>
</Suspense>
</template>
这套技术栈在开发过程中展现出良好的协同效应。SpringBoot的约定优于配置让后端开发效率提升明显,Vue3的响应式系统使复杂交互的状态管理变得简单,MyBatis+MySQL的组合则提供了足够灵活的持久层方案。对于需要展示丰富媒体内容的传统文化项目,这种前后端分离架构已被证明是可靠的选择。
