1. 项目概述
这个企业级Web课程设计选题管理系统采用SpringBoot+Vue+MyBatis+MySQL技术栈实现,是一个典型的现代化前后端分离架构应用。系统主要面向高校教学管理场景,解决课程设计选题环节中师生双向选择、过程管理、成果归档等核心痛点。
我在实际开发中发现,这类系统虽然业务逻辑不算复杂,但要真正达到"企业级"标准,需要在权限控制、数据一致性、高并发处理等方面做足功夫。下面我就从架构设计到具体实现,分享这个项目的完整开发经验。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 技术选型解析
2.1 后端技术栈
SpringBoot 2.7.x作为基础框架,主要基于以下考虑:
- 自动配置特性大幅减少XML配置
- 内嵌Tomcat简化部署流程
- 完善的Starter生态(特别是Spring Security Starter)
- 与MyBatis的天然集成优势
数据库选用MySQL 8.0,主要特性包括:
- JSON字段支持(用于存储动态表单数据)
- 窗口函数(用于复杂统计报表)
- 事务隔离级别设置为REPEATABLE_READ
注意:生产环境建议使用InnoDB集群方案,我们测试环境中单机QPS可达1200+
2.2 前端技术栈
Vue 3.x + Element Plus的组合方案:
- Composition API更适合复杂业务逻辑
- Vite构建速度比Webpack快3-5倍
- 按需引入组件减小打包体积
- 路由采用history模式(需Nginx额外配置)
3. 核心功能实现
3.1 选题流程引擎
采用状态机模式实现选题全生命周期管理:
java复制public enum SelectionStatus {
INIT(0, "初始状态"),
TEACHER_PUBLISHED(1, "教师发布课题"),
STUDENT_SELECTED(2, "学生选择课题"),
TEACHER_CONFIRMED(3, "教师确认"),
FINISHED(4, "已完成");
// 省略getter/setter
}
关键业务逻辑:
- 教师发布课题时自动生成唯一选题码
- 学生选择采用乐观锁防止超选
- 状态变更记录完整操作日志
3.2 动态表单系统
为满足不同学院的个性化需求,设计了基于JSON Schema的表单引擎:
json复制{
"fields": [
{
"name": "project_type",
"label": "课题类型",
"type": "select",
"options": ["理论研究", "应用开发", "实验分析"]
}
]
}
后端存储使用MySQL的JSON类型字段,前端通过递归组件渲染表单。
4. 安全防护方案
4.1 认证授权体系
采用JWT + RBAC模型:
- AccessToken有效期30分钟
- RefreshToken有效期7天
- 接口权限细粒度到按钮级别
Spring Security配置示例:
java复制http.authorizeRequests()
.antMatchers("/api/teacher/**").hasRole("TEACHER")
.antMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated();
4.2 防XSS攻击
前端使用DOMPurify过滤富文本:
javascript复制import DOMPurify from 'dompurify';
const clean = DOMPurify.sanitize(dirtyHtml);
后端采用Jackson的@JsonSerialize注解:
java复制@JsonSerialize(using = HtmlEscapeSerializer.class)
private String projectDescription;
5. 性能优化实践
5.1 数据库优化
-
索引策略:
- 联合索引:(student_id, project_id)
- 覆盖索引:常用查询字段单独建索引
-
查询优化:
sql复制EXPLAIN SELECT * FROM selection
WHERE status = 1
ORDER BY create_time DESC
LIMIT 10;
5.2 缓存方案
采用多级缓存架构:
- 本地Caffeine缓存(有效期5分钟)
- Redis集群缓存(有效期30分钟)
- 缓存击穿防护:
java复制public Project getProject(Long id) {
return cacheManager.get("project:"+id,
() -> projectMapper.selectById(id));
}
6. 部署方案
6.1 容器化部署
Docker Compose编排文件关键配置:
yaml复制services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD}
volumes:
- mysql_data:/var/lib/mysql
backend:
build: ./backend
ports:
- "8080:8080"
depends_on:
- mysql
6.2 前端部署
Nginx配置要点:
nginx复制location / {
try_files $uri $uri/ /index.html;
gzip on;
gzip_types text/css application/javascript;
}
location /api {
proxy_pass http://backend:8080;
}
7. 踩坑实录
-
MyBatis批量插入性能问题:
- 错误做法:循环执行单条insert
- 正确方案:使用
标签批量插入
-
Vue路由缓存问题:
javascript复制<router-view v-slot="{ Component }"> <keep-alive> <component :is="Component" :key="$route.fullPath"/> </keep-alive> </router-view> -
SpringBoot文件上传限制:
properties复制spring.servlet.multipart.max-file-size=10MB spring.servlet.multipart.max-request-size=20MB
这个项目从技术选型到最终上线历时3个月,最大的体会是企业级应用不仅要求功能完整,更要在异常处理、监控报警、文档完备等方面下功夫。特别是师生选题高峰期,需要做好充分的压力测试,我们最终在2核4G的云服务器上实现了800+的并发处理能力。
