1. 项目概述
学科竞赛管理平台是高校信息化建设的重要组成部分,它解决了传统竞赛管理中的三大痛点:信息孤岛、流程繁琐和数据统计困难。作为一名长期参与高校信息化建设的开发者,我深知一套好用的竞赛管理系统对教务工作和学生参与的重要性。
这个基于SpringBoot+Vue的全栈项目,采用了当前企业级开发中最主流的技术栈组合。后端使用SpringBoot 2.7.x构建RESTful API,前端采用Vue 3组合式API开发,数据库选用MySQL 8.0,同时引入Redis缓存提升性能。系统实现了从竞赛发布、报名审核到成绩管理的全流程数字化,特别适合作为计算机专业学生的毕业设计或课程设计案例。
2. 技术架构解析
2.1 后端技术选型
SpringBoot作为后端框架的选择主要基于以下考虑:
- 自动配置特性大幅减少XML配置
- 内嵌Tomcat服务器简化部署
- 丰富的Starter依赖快速集成常用组件
- 完善的文档和社区支持
关键依赖配置示例(pom.xml):
xml复制<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.18.2</version>
</dependency>
2.2 前端技术方案
Vue.js 3.x的优势在本项目中体现为:
- 组合式API更适合复杂业务逻辑组织
- 基于Proxy的响应式系统性能更优
- Vite构建工具带来极快的开发体验
- 丰富的生态系统(Vue Router, Pinia等)
前端项目初始化建议:
bash复制npm create vite@latest competition-platform --template vue
cd competition-platform
npm install vue-router@4 pinia@2 axios
2.3 数据库设计实践
2.3.1 核心表关系
数据库设计遵循第三范式,主要表间关系如下:
- 竞赛表(competition_info)与报名表(user_signup)是一对多关系
- 报名表与成绩表(judge_score)是一对多关系
- 用户表(user)与报名表是多对一关系
ER图关键部分:
code复制用户(user) ← 报名(user_signup) → 竞赛(competition_info)
↓
成绩(judge_score)
2.3.2 索引优化策略
为提高查询性能,我们在以下字段创建索引:
sql复制ALTER TABLE competition_info ADD INDEX idx_status (signup_status);
ALTER TABLE user_signup ADD INDEX idx_competition (competition_id);
ALTER TABLE judge_score ADD INDEX idx_signup (signup_id);
3. 核心功能实现
3.1 JWT认证实现
认证流程设计:
- 用户登录成功后生成JWT token
- 前端将token存储在localStorage
- 每次请求携带在Authorization头
- 服务端通过过滤器校验token
核心Java代码示例:
java复制public String generateToken(User user) {
return JWT.create()
.withSubject(user.getUsername())
.withExpiresAt(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.sign(Algorithm.HMAC512(SECRET.getBytes()));
}
注意事项:token过期时间建议设置为2-4小时,refresh token可设置较长时间(如7天)
3.2 竞赛报名流程
完整的报名状态机设计:
code复制待提交 → 已提交(待审核) → 审核通过/拒绝
↑____________↓
前端报名表单关键校验逻辑:
javascript复制const validateForm = () => {
if (!teamName.value && competition.value.requireTeam) {
ElMessage.error('该竞赛需要组队参加')
return false
}
// 其他校验规则...
return true
}
3.3 评审打分功能
成绩计算采用去掉最高最低分后取平均的算法:
java复制public BigDecimal calculateFinalScore(List<JudgeScore> scores) {
if (scores.size() <= 2) {
return average(scores);
}
scores.sort(Comparator.comparing(JudgeScore::getScore));
List<JudgeScore> validScores = scores.subList(1, scores.size() - 1);
return average(validScores);
}
4. 系统部署方案
4.1 开发环境配置
推荐使用Docker Compose快速搭建环境:
yaml复制version: '3'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
ports:
- "3306:3306"
redis:
image: redis:6
ports:
- "6379:6379"
4.2 生产环境部署
后端打包与运行:
bash复制mvn clean package -DskipTests
java -jar target/competition-platform-0.0.1-SNAPSHOT.jar
前端构建:
bash复制npm run build
# 生成的dist目录可部署到Nginx
5. 常见问题排查
5.1 跨域问题解决
SpringBoot配置CORS的三种方式:
- 全局配置(推荐)
java复制@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*");
}
};
}
- 控制器注解
- 过滤器方式
5.2 性能优化实践
Redis缓存使用场景:
- 竞赛列表缓存(5分钟过期)
- 用户权限信息缓存
- 热门竞赛数据统计
缓存更新策略:
java复制@CacheEvict(value = "competitions", key = "#competitionId")
public void updateCompetition(Long competitionId, CompetitionDTO dto) {
// 更新数据库
}
6. 项目扩展建议
6.1 功能增强方向
- 微信小程序端接入
- 竞赛成果展示墙
- 智能组队推荐功能
- 多维度数据分析看板
6.2 技术深化建议
- 引入Spring Cloud实现微服务化
- 使用Elasticsearch实现全文检索
- 接入OSS实现作品附件存储
- 集成WebSocket实现实时通知
在实际开发中,我发现分页查询的性能优化尤为重要。对于竞赛列表这种高频访问接口,建议采用以下优化方案:
sql复制-- 避免使用offset
SELECT * FROM competition_info
WHERE id > ?
ORDER BY id ASC
LIMIT ?
这个项目从技术选型到架构设计都遵循了当前主流的最佳实践,特别适合作为全栈开发的学习案例。我在实现过程中最大的收获是理解了如何在前端和后端之间建立高效的协作模式,以及如何设计可扩展的数据模型来适应业务变化。