1. 项目概述
这个基于Java+SSM+Django的网上选课系统是一个典型的B/S架构应用,采用了前后端分离的设计模式。前端使用Django框架构建用户界面,后端采用Spring+SpringMVC+Mybatis(SSM)技术栈处理业务逻辑,数据库支持MySQL和SQLServer两种选择。
在实际开发中,我发现这种技术组合有几个显著优势:Django自带的管理后台可以快速搭建基础CRUD界面,而SSM框架则提供了企业级Java应用的稳定性和扩展性。系统主要面向高校或培训机构的课程管理需求,实现了学生选课、教师评分、管理员管理等核心功能。
2. 技术架构解析
2.1 前端技术选型
Django作为Python生态中最成熟的Web框架之一,在这个项目中承担了视图渲染和路由分发的职责。我特别欣赏它的几个特性:
- MTV模式清晰:与传统的MVC不同,Django采用Model-Template-View模式,模板系统非常直观
- 自带Admin:通过简单配置就能生成功能完善的后台管理界面
- ORM强大:虽然本项目主要用Java处理业务,但Django ORM在快速原型阶段非常有用
实际开发时,我建议使用Django 3.2 LTS版本,它在稳定性和新特性之间取得了很好的平衡。对于前端页面,可以结合Bootstrap快速搭建响应式界面。
2.2 后端技术实现
SSM框架组合是Java Web开发的经典选择:
- Spring:5.3.x版本,负责IoC容器管理和AOP支持
- SpringMVC:处理HTTP请求,实现RESTful接口
- MyBatis:3.5.x,比Hibernate更灵活的SQL映射方案
在控制器层,我采用了@RestController注解简化JSON响应:
java复制@RestController
@RequestMapping("/api/course")
public class CourseController {
@Autowired
private CourseService courseService;
@GetMapping("/list")
public Result list(@RequestParam Map<String, Object> params) {
PageUtils page = courseService.queryPage(params);
return Result.ok().put("page", page);
}
}
2.3 数据库设计
系统核心表包括:
- 用户表:区分学生、教师、管理员角色
- 课程表:存储课程基本信息
- 选课关系表:记录学生选课情况
- 成绩表:教师录入的学生成绩
我建议使用MySQL 8.0作为生产环境数据库,它的窗口函数和CTE特性在复杂统计查询中非常有用。建表时注意设置合适的索引,比如在选课关系表的student_id和course_id上建立联合索引。
3. 核心功能实现
3.1 学生选课模块
选课功能需要考虑几个关键点:
- 并发控制:热门课程可能被多人同时选择
- 时间冲突检测:同一时段不能选多门课
- 容量限制:课程人数不能超过上限
实现代码示例:
java复制@Transactional
public Result selectCourse(Long studentId, Long courseId) {
// 检查课程容量
Course course = courseDao.selectById(courseId);
if(course.getSelected() >= course.getCapacity()) {
return Result.error("课程已满");
}
// 检查时间冲突
List<Course> selectedCourses = courseDao.listSelectedCourses(studentId);
if(hasTimeConflict(course, selectedCourses)) {
return Result.error("时间冲突");
}
// 执行选课
courseDao.incrementSelected(courseId);
selectionDao.insert(new Selection(studentId, courseId));
return Result.ok();
}
3.2 成绩管理模块
教师录入成绩时需要处理:
- 权限验证:只能录入自己教授的课程
- 数据校验:成绩必须在合理范围内
- 批量操作:支持Excel导入导出
建议使用Apache POI处理Excel文件,并实现如下接口:
java复制@PostMapping("/import")
public Result importScores(@RequestParam("file") MultipartFile file,
@RequestParam Long courseId) {
// 验证教师权限
if(!teachingService.isTeaching(currentUserId(), courseId)) {
return Result.error("无权限");
}
// 解析Excel
List<ScoreImportDTO> imports = ExcelUtil.parse(file);
// 批量保存
scoreService.batchSave(courseId, imports);
return Result.ok("导入成功");
}
4. 系统安全设计
4.1 认证与授权
采用JWT进行无状态认证,结合Spring Security实现RBAC:
java复制@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/api/admin/**").hasRole("ADMIN")
.antMatchers("/api/teacher/**").hasRole("TEACHER")
.anyRequest().authenticated()
.and()
.addFilter(new JwtAuthenticationFilter(authenticationManager()))
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
4.2 数据安全
- 密码加密:使用MD5加盐存储
- SQL防护:MyBatis使用#{}防止注入
- XSS防护:前端使用vue-sanitize等库过滤
密码加密实现:
java复制public class PasswordUtil {
private static final String SALT = "random_salt_value";
public static String encrypt(String rawPassword) {
return DigestUtils.md5DigestAsHex((SALT + rawPassword).getBytes());
}
}
5. 性能优化实践
5.1 缓存策略
- 课程列表缓存:使用Redis缓存热门课程
- 查询结果缓存:MyBatis二级缓存
- 页面静态化:不常变的页面生成静态HTML
Redis配置示例:
java复制@Cacheable(value = "courses", key = "#root.methodName + '_' + #params.hashCode()")
public PageUtils queryPage(Map<String, Object> params) {
// 查询逻辑
}
5.2 数据库优化
- 读写分离:主库写,从库读
- 分表策略:按学期分课程表
- 索引优化:EXPLAIN分析慢查询
建议在application.yml中配置多数据源:
yaml复制spring:
datasource:
master:
url: jdbc:mysql://master:3306/course
slave:
url: jdbc:mysql://slave:3306/course
6. 部署与监控
6.1 容器化部署
使用Docker Compose编排服务:
yaml复制version: '3'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
redis:
image: redis:6
backend:
build: ./backend
ports:
- "8080:8080"
frontend:
build: ./frontend
ports:
- "8000:8000"
6.2 监控方案
- Spring Boot Actuator:暴露健康检查端点
- Prometheus+Grafana:监控系统指标
- ELK:日志收集分析
Actuator配置示例:
yaml复制management:
endpoints:
web:
exposure:
include: health,info,metrics
endpoint:
health:
show-details: always
7. 常见问题排查
7.1 选课并发问题
现象:多人同时选课导致超选
解决方案:
- 数据库乐观锁:version字段
- Redis分布式锁
- 消息队列削峰
乐观锁实现:
java复制@Update("UPDATE course SET selected = selected + 1, version = version + 1
WHERE id = #{id} AND version = #{version}")
int updateWithLock(Course course);
7.2 跨域问题
现象:前端访问接口报CORS错误
解决方案:
- 配置CorsFilter
- Nginx反向代理
- @CrossOrigin注解
全局CORS配置:
java复制@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOrigin("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
在实际开发中,我发现文档和注释的完整性对项目维护至关重要。建议使用Swagger生成API文档,并结合JavaDoc为关键方法添加详细注释。对于学生毕业设计项目,还应该特别注意代码规范性,遵循阿里巴巴Java开发手册等标准。