大学选课系统是高校教务管理中最核心的子系统之一。在传统模式下,学生需要排队填写纸质选课单,教务人员需要手工录入和核对数据,整个过程耗时耗力且容易出错。我曾参与过某高校的选课系统升级项目,亲眼目睹了高峰期教务处的"壮观"场景:上百名学生挤在走廊排队,教务老师加班到凌晨处理选课冲突。
这种模式主要存在三大痛点:
基于这些痛点,我们设计了这个基于SpringBoot+Vue的选课系统。系统采用前后端分离架构,后端提供稳定的选课服务,前端提供流畅的交互体验。实测表明,新系统将选课效率提升了5倍以上,选课冲突率降低了90%。
选择SpringBoot作为后端框架主要基于以下考虑:
核心依赖配置示例:
xml复制<dependencies>
<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>
</dependencies>
Vue.js作为前端框架的优势:
典型组件结构:
code复制src/
├── components/
│ ├── CourseTable.vue # 课程表格组件
│ ├── SelectDialog.vue # 选课弹窗组件
├── views/
│ ├── StudentView.vue # 学生选课页面
系统采用MySQL 8.0作为数据库,主要考虑其:
核心表关系图:
code复制学生表(stu_info) ← 选课记录(select_record) → 课程表(course_info)
选课流程采用状态机模式实现:
关键代码片段:
java复制@Transactional
public Result selectCourse(Long stuId, Long courseId) {
// 1. 检查课程状态
Course course = courseRepository.findById(courseId)
.orElseThrow(() -> new BusinessException("课程不存在"));
// 2. 检查时间冲突
if (scheduleService.hasConflict(stuId, course.getTime())) {
throw new BusinessException("时间冲突");
}
// 3. 使用乐观锁更新课程名额
int updated = courseRepository.reduceCapacity(courseId, course.getVersion());
if (updated == 0) {
throw new BusinessException("选课失败,名额已满");
}
// 4. 创建选课记录
SelectRecord record = new SelectRecord();
record.setStuId(stuId);
record.setCourseId(courseId);
recordRepository.save(record);
return Result.success();
}
针对选课高峰期的并发问题,我们采用三级防护:
Redis限流配置示例:
java复制@Bean
public RedisRateLimiter redisRateLimiter(RedisTemplate<String, String> redisTemplate) {
return new RedisRateLimiter(
redisTemplate,
100, // 每秒100个令牌
200 // 桶容量200
);
}
系统采用JWT进行身份认证,权限控制基于RBAC模型:
JWT生成代码:
java复制public String generateToken(UserDetails user) {
Algorithm algorithm = Algorithm.HMAC256(secret);
return JWT.create()
.withSubject(user.getUsername())
.withExpiresAt(new Date(System.currentTimeMillis() + expireTime))
.withClaim("role", user.getRole())
.sign(algorithm);
}
关键数据安全措施:
密码加密示例:
java复制@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
推荐使用Docker Compose部署:
yaml复制version: '3'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: course_selection
backend:
build: ./backend
ports:
- "8080:8080"
depends_on:
- mysql
frontend:
build: ./frontend
ports:
- "80:80"
集成Spring Boot Actuator提供健康检查:
properties复制management.endpoints.web.exposure.include=health,metrics,info
management.endpoint.health.show-details=always
日志收集采用ELK方案:
典型冲突场景及解决方案:
| 冲突类型 | 检测方法 | 解决方案 |
|---|---|---|
| 时间冲突 | 比对课程时间表 | 前端实时提示 |
| 名额已满 | 检查course_selected < course_capacity | 加入等待队列 |
| 先修课程 | 检查学生已修课程 | 限制选课资格 |
经过压测发现的性能瓶颈及优化措施:
课程列表查询慢:
选课事务超时:
缓存穿透:
基于实际运营经验,建议后续增加:
智能推荐系统:
移动端适配:
数据分析看板:
实现推荐系统的伪代码:
python复制def recommend_courses(student):
# 获取同专业学生的选课记录
similar_students = find_similar_by_major(student.major)
# 计算课程评分
recommendations = []
for course in popular_courses:
score = calculate_score(student, course, similar_students)
recommendations.append((course, score))
return sorted(recommendations, key=lambda x: -x[1])[:5]
这个选课系统在实际运行中表现稳定,单服务器可支持5000+并发选课请求。开发过程中最大的教训是要提前做好容量规划,我们在第一次选课季就遇到了数据库连接耗尽的问题。后来通过引入连接池和读写分离,才彻底解决了性能瓶颈。