
1. 项目背景与核心需求在大学校园里学科竞赛是培养学生创新能力和实践能力的重要途径。但传统的人工管理方式存在诸多痛点报名表堆积如山、信息核对耗时费力、成绩统计容易出错。去年我参与某高校数学建模竞赛组织时仅处理300份纸质报名表就耗费了整整一周时间更不用说后续的成绩汇总工作了。这套基于SpringBootVue的学科竞赛管理系统正是为解决这些问题而生。系统采用前后端分离架构后端使用SpringBoot提供RESTful API前端用Vue.js构建交互界面实现了从竞赛发布、报名、评审到成绩统计的全流程数字化管理。2. 技术架构设计2.1 后端技术选型SpringBoot 2.7.x作为后端框架是经过多重考量后的选择自动配置特性大幅减少了XML配置比如数据库连接池默认使用HikariCP内嵌Tomcat服务器简化部署只需打包成jar即可运行与MyBatis的整合非常顺畅通过MapperScan注解就能自动扫描映射接口数据库选用MySQL 8.0主要考虑到高校IT部门通常已有MySQL运维经验事务ACID特性保证报名数据的一致性JSON字段支持方便存储竞赛详情等半结构化数据2.2 前端技术方案Vue 3.x Element Plus的组合提供了良好的开发体验Composition API使代码组织更灵活Element Plus的表格组件完美适配大量报名数据的展示Axios拦截器统一处理401认证过期等场景特别值得一提的是采用的多环境配置方案// env.development VUE_APP_API_BASEhttp://localhost:8080 // env.production VUE_APP_API_BASE/api3. 核心功能实现3.1 竞赛报名模块报名流程的状态机设计是关键public enum RegistrationStatus { PENDING(0, 待审核), APPROVED(1, 已通过), REJECTED(2, 已拒绝); // 省略getter和构造方法 }数据库表设计特别注意了并发控制CREATE TABLE competition_registration ( id BIGINT PRIMARY KEY AUTO_INCREMENT, competition_id BIGINT NOT NULL COMMENT 关联竞赛ID, student_id VARCHAR(20) NOT NULL COMMENT 学号, team_name VARCHAR(50) COMMENT 团队名称, status TINYINT DEFAULT 0 COMMENT 0-待审核 1-已通过 2-已拒绝, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, UNIQUE KEY idx_competition_student (competition_id, student_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;3.2 评审打分模块采用策略模式实现评分计算public interface ScoringStrategy { BigDecimal calculateTotal(ScoreDTO score); } Component public class DefaultScoringStrategy implements ScoringStrategy { Override public BigDecimal calculateTotal(ScoreDTO score) { return score.getTechnical() .add(score.getInnovation()) .add(score.getPresentation()); } }4. 关键问题与解决方案4.1 高并发报名场景在热门竞赛开放报名时出现了严重的超卖问题。我们通过以下方案解决数据库层面添加唯一索引防止重复报名使用Redis分布式锁控制报名流程public boolean register(Long competitionId, String studentId) { String lockKey reg: competitionId : studentId; try { Boolean locked redisTemplate.opsForValue() .setIfAbsent(lockKey, 1, 30, TimeUnit.SECONDS); if (Boolean.TRUE.equals(locked)) { // 执行报名逻辑 } } finally { redisTemplate.delete(lockKey); } }4.2 文件上传优化报名时需要提交作品附件我们做了以下优化使用MinIO替代本地存储前端实现分片上传后端添加MD5校验避免重复上传5. 部署实践5.1 后端部署采用Docker Compose部署方案version: 3 services: app: image: openjdk:17-jdk ports: - 8080:8080 volumes: - ./app.jar:/app.jar command: java -jar /app.jar depends_on: - redis - mysql mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} volumes: - mysql_data:/var/lib/mysql redis: image: redis:6 ports: - 6379:63795.2 前端部署配置Nginx实现静态资源服务和API反向代理server { listen 80; server_name competition.example.com; location / { root /var/www/html; try_files $uri $uri/ /index.html; } location /api { proxy_pass http://backend:8080; proxy_set_header Host $host; } }6. 扩展功能6.1 微信通知集成通过微信公众号模板消息发送审核结果通知public void sendWechatNotice(String openId, String status) { String templateId 审核结果通知模板ID; MapString, Object data new HashMap(); data.put(status, status); wechatClient.sendTemplateMsg(openId, templateId, data); }6.2 数据分析看板使用ECharts实现的竞赛数据可视化// 参赛人数趋势图 const option { xAxis: { type: category, data: [周一,周二,周三,周四,周五] }, yAxis: {type: value}, series: [{ data: [120, 200, 150, 80, 70], type: bar }] };7. 踩坑记录Vue路由history模式需要后端配合配置否则刷新会404。解决方案Configuration public class WebConfig implements WebMvcConfigurer { Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController(/{path:[^\\.]*}) .setViewName(forward:/index.html); } }MyBatis批量插入性能优化改用BatchExecutor并合理设置rewriteBatchedStatements参数跨域问题解决方案精确配置CORS而非简单允许所有来源Bean public CorsFilter corsFilter() { UrlBasedCorsConfigurationSource source new UrlBasedCorsConfigurationSource(); CorsConfiguration config new CorsConfiguration(); config.addAllowedOrigin(https://competition.example.com); config.addAllowedHeader(*); config.addAllowedMethod(*); source.registerCorsConfiguration(/api/**, config); return new CorsFilter(source); }这套系统在某高校实际运行一个学期后管理效率提升显著原本需要3天处理的报名工作现在2小时即可完成成绩统计错误率降为零。后续计划加入智能组队、往届数据分析等功能进一步发挥系统价值。