文章目录
一、这个系统到底要干啥?(需求分析篇)
先说人话!!!咱们要做的这个系统得满足这些刚需:
- 用户分级 👉 老师能录成绩/学生只能查成绩(权限控制超重要!)
- 成绩管理 👉 增删改查是标配(别忘了批量导入导出功能)
- 统计报表 👉 自动生成班级排名/学科分析(柱状图、折线图不能少)
- 系统安全 👉 登录验证+操作日志(防止熊孩子乱改数据)
(偷偷告诉你们,很多毕设系统都漏掉了日志模块,结果答辩被导师怼惨了…)
二、技术栈怎么选?(小白避坑指南)
![技术架构图]
别被这张图吓到!咱们用最实在的技术组合:
- 后端:Spring Boot(yyds!)+ MyBatis Plus(省掉50%的SQL)
- 前端:Thymeleaf模板(JSP早该淘汰了)+ Bootstrap5(颜值担当)
- 数据库:MySQL 8.0(记得用utf8mb4字符集!)
- 工具:Lombok(少写getter/setter真香)
(为啥不用Redis?刚开始做别整太复杂,V1.0够用就行!)
三、数据库设计(核心中的核心)
3.1 表结构设计
CREATE TABLE `tb_score` (
`id` INT NOT NULL AUTO_INCREMENT,
`student_id` VARCHAR(12) NOT NULL COMMENT '学号',
`course_name` VARCHAR(20) NOT NULL COMMENT '课程名称',
`score` DECIMAL(4,1) UNSIGNED COMMENT '成绩',
`term` VARCHAR(10) COMMENT '学期',
PRIMARY KEY (`id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4;
(注意!!score字段用DECIMAL别用FLOAT,小数点精度坑死过很多人!)
3.2 索引优化技巧
ALTER TABLE tb_score ADD INDEX idx_student (student_id);
ALTER TABLE tb_score ADD INDEX idx_course (course_name);
(建立联合索引还是单列索引?看查询条件!80%的情况单列够用了)
四、核心功能实现(上代码!)
4.1 用户登录模块
@PostMapping("/login")
public String login(@RequestParam String username,
@RequestParam String password,
HttpSession session) {
User user = userService.checkLogin(username, password);
if(user != null) {
session.setAttribute("currentUser", user);
return "redirect:/index";
}
return "redirect:/login?error=1"; // 登录失败带参数跳转
}
(Session存用户信息简单粗暴!想进阶的可以用JWT)
4.2 成绩录入功能
@Transactional
public boolean batchImport(List<Score> scores) {
try {
return scoreMapper.insertBatch(scores) > 0;
} catch (DuplicateKeyException e) {
log.error("学号{}重复录入", scores.get(0).getStudentId());
throw new ServiceException("数据重复,请检查学号和课程");
}
}
(批量插入一定要加事务!!血的教训啊兄弟们)
五、统计报表黑科技
5.1 使用ECharts生成图表
function initChart() {
var chart = echarts.init(document.getElementById('chart'));
$.get('/score/stat', function(data) {
chart.setOption({
xAxis: { data: data.courses },
series: [{ data: data.scores }]
});
});
}
(别傻乎乎用POI导出了!现在都流行网页直接显示图表)
5.2 班级排名算法
public List<StudentVO> calculateRank(List<Score> scores) {
return scores.stream()
.collect(Collectors.groupingBy(Score::getStudentId))
.entrySet().stream()
.map(e -> new StudentVO(e.getKey(),
e.getValue().stream()
.mapToDouble(Score::getScore)
.average().orElse(0)))
.sorted((a,b) -> Double.compare(b.getAvgScore(), a.getAvgScore()))
.collect(Collectors.toList());
}
(Java8的Stream真香!比for循环优雅多了)
六、部署踩坑指南
6.1 打包成可执行Jar
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
(用mvn package打包时记得跳过测试!-DskipTests)
6.2 常见启动错误
- 端口冲突:加
--server.port=8081
- 数据库连不上:检查
spring.datasource.url
- 页面乱码:统一改成UTF-8编码
(遇到问题先看日志!日志!日志!重要的事情说三遍)
七、进阶优化方向
想让系统更专业?试试这些骚操作:
- 缓存优化:用Redis缓存热点数据(比如班级前十名)
- 权限升级:集成Shiro做细粒度权限控制
- 接口安全:增加API签名验证
- 压力测试:用JMeter模拟并发查询
(这些写在简历上绝对加分!)
最后说点真心话
别看这个系统好像简单,真要完整做下来,光调试各种边界条件就能让你怀疑人生(比如成绩为0、满分超过100、课程名称特殊字符等等)。建议先把基础功能跑通,再慢慢加高级功能。
源码已打包放在Github(地址私信我发你),记得点个Star再白嫖啊!有什么问题评论区见,看到都会回~