1. SSM学生信息管理系统开发全流程解析
作为一名有多年Java Web开发经验的程序员,最近我完成了一个基于SSM框架的学生信息管理系统。这个项目从需求分析到最终上线历时3个月,现在将整个开发过程中的技术选型、核心实现和踩坑经验分享给大家。
1.1 为什么选择SSM框架
SSM(Spring+Spring MVC+MyBatis)是当前Java Web开发的主流框架组合。在技术选型阶段,我对比了多种技术方案:
- Spring Boot:虽然开发更快速,但不利于理解底层原理
- Django:Python生态成熟,但团队Java基础更好
- ASP.NET:微软系技术栈,与现有技术体系不匹配
最终选择SSM主要基于以下考虑:
- 团队成员对Spring IOC、AOP等概念熟悉
- MyBatis比Hibernate更灵活,方便复杂SQL优化
- 学校现有系统多为Java技术栈,便于后期集成
提示:对于教学类项目,建议从SSM开始而不是直接使用Spring Boot,能更好掌握底层原理。
2.1 系统架构设计
系统采用经典的三层架构:
2.1.1 表现层
- 前端:Bootstrap + jQuery + Thymeleaf模板
- 后端:Spring MVC处理HTTP请求
- 接口规范:RESTful风格设计
2.1.2 业务逻辑层
- 核心服务模块划分:
- 用户服务(UserService)
- 课程服务(CourseService)
- 成绩服务(ScoreService)
- 事务管理:Spring声明式事务
2.1.3 数据访问层
- ORM框架:MyBatis 3.5.6
- 连接池:Druid 1.2.6
- 二级缓存:Ehcache 3.8.1
3.1 数据库设计关键点
3.1.1 主要表结构
sql复制-- 学生表
CREATE TABLE `student` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`student_no` varchar(20) NOT NULL COMMENT '学号',
`name` varchar(50) NOT NULL,
`gender` tinyint(1) DEFAULT '0',
`class_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_student_no` (`student_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 课程表
CREATE TABLE `course` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`course_code` varchar(20) NOT NULL,
`name` varchar(100) NOT NULL,
`credit` tinyint(4) DEFAULT '1',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3.1.2 索引优化实践
- 所有外键字段添加普通索引
- 学号、课程编号等业务唯一字段建立唯一索引
- 成绩查询高频字段建立联合索引:
sql复制ALTER TABLE `score` ADD INDEX `idx_student_course` (`student_id`, `course_id`);
4.1 核心功能实现
4.1.1 选课功能实现
java复制@Transactional
public boolean selectCourse(Integer studentId, Integer courseId) {
// 检查选课人数是否已满
Course course = courseMapper.selectById(courseId);
if(course.getSelected() >= course.getCapacity()) {
throw new BusinessException("该课程已选满");
}
// 检查是否已选过该课程
if(scoreMapper.exists(studentId, courseId)) {
throw new BusinessException("不能重复选课");
}
// 插入选课记录
Score score = new Score();
score.setStudentId(studentId);
score.setCourseId(courseId);
scoreMapper.insert(score);
// 更新课程已选人数
courseMapper.incrementSelected(courseId);
return true;
}
4.1.2 成绩导入性能优化
处理大批量成绩导入时,采用MyBatis批量操作:
java复制public void batchImport(List<Score> scores) {
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
try {
ScoreMapper mapper = sqlSession.getMapper(ScoreMapper.class);
for (Score score : scores) {
mapper.insert(score);
}
sqlSession.commit();
} finally {
sqlSession.close();
}
}
5.1 安全防护措施
5.1.1 认证与授权
java复制@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/teacher/**").hasAnyRole("TEACHER", "ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll();
}
}
5.1.2 防SQL注入
- 全部使用MyBatis参数化查询
- 禁止拼接SQL语句
- 使用MyBatis的
<if>标签动态生成SQL
6.1 部署实践
6.1.1 服务器配置
- JDK 1.8
- Tomcat 9
- MySQL 5.7
- Redis 5.0(用于会话管理)
6.1.2 性能调优
- Tomcat连接池配置:
properties复制server.tomcat.max-threads=200 server.tomcat.min-spare-threads=20 - JVM参数:
bash复制
-Xms512m -Xmx1024m -XX:+UseG1GC
7.1 踩坑经验总结
-
MyBatis缓存问题:在批量操作时发现查询结果未更新,原因是未清除本地缓存,解决方案:
xml复制<insert id="insert" flushCache="true"> -
事务失效场景:
- 同类方法调用(this.method())
- 异常被捕获未抛出
- 非public方法
-
日期处理建议:
- 数据库使用datetime类型
- 前后端统一使用时间戳传输
- 前端展示时再做时区转换
这个项目让我对SSM框架有了更深入的理解,特别是在复杂事务管理和性能优化方面积累了不少经验。对于想学习Java Web开发的同学,建议从这样一个完整的业务系统入手,逐步掌握企业级开发的各项技能。