ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

SSM+Vue学生成绩管理系统源码实战:从跑通到答辩的完整指南

SSM+Vue学生成绩管理系统源码实战:从跑通到答辩的完整指南 简介这是一套面向高校计算机专业毕业设计场景的SSMVue学生成绩管理系统实战项目采用Java语言、SSM与Vue前后端分离框架、B/S架构及MySQL数据库适合正在准备毕设或需要完整企业级项目练手的开发者参考。压缩包共990个文件约67.89MB以166个Java源码、63个Vue组件、156个JavaScript脚本、116个HTML页面及46个CSS样式为主另含SQL建表脚本、XML配置、图片与字体等静态资源覆盖后端接口、前端页面与数据库脚本的完整链路。系统按管理员、教师、学生三类角色划分权限管理员端涵盖学生与教师管理、优秀教师与优秀班主任、教学课件、在线答疑、公告信息、班级与学生成绩、试题试卷及考试管理等模块教师端与学生端则聚焦课件、答疑、成绩与在线考试等核心业务。资源包内附项目说明文档与运行录像可帮助读者快速理解目录结构、理清模块调用关系并完成本地部署调试。目前已有224人学习下载适合作为毕设选题落地的完整参考方案。1. 从一份 SSMVue 学生成绩管理系统源码说起它到底能帮你省下多少时间如果你正在为 Java 毕业设计发愁尤其是选题落在「学生成绩管理系统」这个方向那你大概率已经翻过不少资料有人丢给你一个 SSM 框架的压缩包有人让你去看 Vue 官网还有人劝你直接换个题目。但真正的问题是——你拿到一份 SSMVue 项目实战的学生成绩管理系统源码之后能不能把它跑起来、看懂、改出属于自己的东西并且在答辩时讲清楚每一层在干什么。这份标题里的关键词很明确SSM、Vue、学生成绩管理系统、Java 毕业设计外加源码、说明和录像。它解决的不是「从零写一个系统」的问题而是「给你一套能跑通的骨架让你在有限时间里完成一个结构完整、技术栈主流、能讲出所以然的毕设」。适合的人群也很清楚Java 基础刚过一遍、Vue 只写过几个 demo、对 SSM 三层架构有概念但没完整搭过项目的人。如果你已经工作两年这套东西对你来说偏基础但作为带新人的教学案例依然好用。我见过太多人卡在第一步源码解压完IDEA 打开一片红数据库连不上前端 npm install 报错然后就放弃了。其实这套技术栈的落地路径非常固定坑也就那么几个。接下来我会按「环境怎么配 → 后端怎么跑 → 前端怎么接 → 数据怎么设计 → 怎么改成自己的 → 怎么避坑」这条线把一份 SSMVue 学生成绩管理系统从压缩包到能答辩的完整过程拆开讲。你不需要有很深的框架源码功底但需要愿意动手敲命令、看日志、改配置。2. SSM 后端跑通从建库到第一个接口返回 JSON2.1 先搞清楚 SSM 在这套系统里各自管什么SSM 是 Spring SpringMVC MyBatis 的缩写这三个东西在学生成绩管理系统里的分工非常清晰。Spring 负责管理对象和依赖注入比如 Service 层要调用 Mapper不需要自己 new交给容器SpringMVC 负责接收前端请求、参数绑定、返回 JSONMyBatis 负责写 SQL、映射结果集到 Java 对象。很多教程一上来就讲 IOC 和 AOP其实对跑通项目帮助不大你只需要知道Controller 接请求Service 写业务Mapper 查数据库三层各司其职。学生成绩管理系统的业务逻辑不复杂核心就是几张表学生表、课程表、成绩表、用户表。成绩表里存学生 ID、课程 ID、分数查询的时候做关联。SSM 的好处是 SQL 完全可控你可以在 Mapper XML 里写多表联查返回一个包含学生姓名、课程名称、分数的 VO 对象。这比 JPA 自动生成 SQL 更直观也更容易在答辩时讲清楚「这条数据是怎么查出来的」。选型理由也在这里为什么不用 SpringBoot因为很多学校教学计划里 SSM 是必修内容答辩老师认这个技术栈而且 SSM 的配置文件虽然多但每一层都暴露在外面出问题容易定位。SpringBoot 自动配置虽然快但一旦出错新手往往不知道从哪里查。所以如果你时间紧、基础一般SSM 反而是更稳的选择。2.2 建库建表四张核心表的最小可用结构在跑代码之前先把数据库准备好。我一般用 MySQL 5.7 或 8.0字符集选 utf8mb4排序规则用 utf8mb4_general_ci。下面是最小可用的建表语句你可以直接复制执行。注意成绩表里的 student_id 和 course_id 要建索引否则数据量上去之后联查会明显变慢。-- 学生表 CREATE TABLE student ( id int(11) NOT NULL AUTO_INCREMENT, student_no varchar(20) NOT NULL COMMENT 学号, name varchar(50) NOT NULL COMMENT 姓名, class_name varchar(50) DEFAULT NULL COMMENT 班级, gender tinyint(1) DEFAULT 1 COMMENT 1男 0女, PRIMARY KEY (id), UNIQUE KEY uk_student_no (student_no) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; -- 课程表 CREATE TABLE course ( id int(11) NOT NULL AUTO_INCREMENT, course_name varchar(100) NOT NULL, credit decimal(3,1) DEFAULT NULL COMMENT 学分, teacher_name varchar(50) DEFAULT NULL, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; -- 成绩表 CREATE TABLE score ( id int(11) NOT NULL AUTO_INCREMENT, student_id int(11) NOT NULL, course_id int(11) NOT NULL, score decimal(5,1) DEFAULT NULL, exam_time date DEFAULT NULL, PRIMARY KEY (id), KEY idx_student (student_id), KEY idx_course (course_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4; -- 用户表登录用 CREATE TABLE sys_user ( id int(11) NOT NULL AUTO_INCREMENT, username varchar(50) NOT NULL, password varchar(100) NOT NULL, role varchar(20) DEFAULT student COMMENT admin/teacher/student, PRIMARY KEY (id), UNIQUE KEY uk_username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;建完表之后插入一条管理员账号密码先用明文后面再讲怎么加密。这里注意很多源码包里自带的 SQL 文件可能包含大量测试数据导入之前先看一眼有没有外键约束如果有导入顺序必须是 student → course → score → sys_user否则会报外键错误。INSERT INTO sys_user (username, password, role) VALUES (admin, 123456, admin);2.3 后端配置三个必须改对的地方拿到源码后不要急着点运行。先找到 src/main/resources 下面的配置文件通常是 jdbc.properties、applicationContext.xml、spring-mvc.xml 这几个。你需要改的地方只有三处数据库连接、端口号、静态资源映射。数据库连接里把 URL、用户名、密码换成你本地的。URL 里记得加useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai否则中文乱码和时间差问题会让你查半天。# jdbc.properties jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/score_manager?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/Shanghai jdbc.usernameroot jdbc.password你的密码端口号在 Tomcat 配置里改默认 8080 如果被占用就换成 8081。静态资源映射在 spring-mvc.xml 里确保mvc:resources标签把前端打包后的 static 目录映射出去。如果你不打算前后端分离部署可以把 Vue 打包后的 dist 文件放到 webapp 下面这样启动一个 Tomcat 就能同时访问前后端。改完配置后用 Maven 拉依赖。如果下载慢在 settings.xml 里加阿里云镜像。然后配置 Tomcat部署 war 包启动。看到 Spring 容器启动没有报错访问http://localhost:8080/能看到登录页或者接口返回后端就算跑通了。如果报 404先检查 Controller 的RequestMapping路径和 Tomcat 的 context path 是否一致如果报 500看控制台异常栈大概率是数据库连接或者 Mapper XML 里的 SQL 写错了。3. Vue 前端接入从 npm install 到跨域请求打通3.1 Vue 环境配置node 版本和依赖安装的坑前端部分先确认你的 Node.js 版本。Vue 2 项目建议用 Node 14 或 16Vue 3 项目可以用 16 以上。如果你用 Node 18 跑 Vue 2 的老项目可能会遇到 OpenSSL 报错解决办法是在 package.json 的 scripts 里加上SET NODE_OPTIONS--openssl-legacy-provider。安装依赖用 npm 或 yarn 都行但不要混用否则 lock 文件冲突会让你重新装一遍。# 查看 node 版本 node -v # 安装依赖建议用淘宝源加速 npm install --registryhttps://registry.npmmirror.com # 启动开发服务器 npm run serve启动成功后浏览器访问http://localhost:8081能看到登录页面。如果页面空白按 F12 看控制台报错。常见的是路由模式问题history 模式需要后端配合hash 模式不需要。学生成绩管理系统一般用 hash 模式就够了改 router/index.js 里的mode: hash。3.2 用 axios 封装请求解决跨域和 token 携带前端跑起来之后下一步是让它能调通后端接口。Vue 项目里通常用 axios我一般会封装一个 request.js统一处理 baseURL、超时、请求拦截和响应拦截。baseURL 指向后端地址开发阶段是http://localhost:8080生产环境换成实际域名。跨域问题在后端加一个 CORS 过滤器就能解决或者用 Vue 的 devServer proxy 代理。// src/utils/request.js import axios from axios const service axios.create({ baseURL: process.env.VUE_APP_BASE_API || http://localhost:8080, timeout: 10000 }) // 请求拦截带上 token service.interceptors.request.use(config { const token localStorage.getItem(token) if (token) { config.headers[Authorization] token } return config }, error Promise.reject(error)) // 响应拦截统一处理错误码 service.interceptors.response.use(response { const res response.data if (res.code ! 200) { alert(res.message || 请求失败) return Promise.reject(new Error(res.message)) } return res }, error { console.error(接口异常, error) return Promise.reject(error) }) export default service这段代码的关键在于拦截器请求拦截负责把登录后拿到的 token 塞进 header响应拦截负责把后端返回的{code, message, data}结构拆开业务代码只需要关心 data。参数说明timeout 设 10000 毫秒太长会让用户等太久太短可能查大表时超时。baseURL 用环境变量方便切换开发和生产。3.3 成绩列表页一个完整的增删改查页面怎么组织学生成绩管理系统里最核心的页面就是成绩管理。我一般把它拆成三个部分搜索栏、表格、分页器。搜索栏支持按学号、课程名、班级筛选表格展示学生姓名、课程、分数、考试时间分页器控制每页条数。数据用 Vue 的 data 管理方法里调 request.js 发请求。// 成绩列表查询 export default { data() { return { list: [], total: 0, query: { pageNum: 1, pageSize: 10, studentNo: , courseName: } } }, created() { this.fetchList() }, methods: { async fetchList() { const res await request.get(/score/page, { params: this.query }) this.list res.data.records this.total res.data.total }, handleSearch() { this.query.pageNum 1 this.fetchList() } } }逻辑说明created 钩子里先拉第一页数据handleSearch 在点击搜索按钮时把页码重置为 1避免搜完停在空页。参数说明pageNum 和 pageSize 是分页参数后端用 PageHelper 插件接收studentNo 和 courseName 是模糊查询条件后端 Mapper 里用if teststudentNo ! null and studentNo ! 动态拼接 SQL。这样一套下来一个标准的 CRUD 页面就成型了其他模块照这个结构复制即可。4. 数据库设计与业务逻辑成绩录入、查询、统计怎么落地4.1 成绩录入批量插入和事务控制成绩录入通常有两种场景单个录入和批量导入。单个录入就是表单提交后端接收一个 Score 对象插入前先校验学生和课程是否存在。批量导入一般用 ExcelJava 这边用 POI 解析然后批量插入。批量插入时一定要加事务否则插到一半失败会留下脏数据。Service public class ScoreServiceImpl implements ScoreService { Autowired private ScoreMapper scoreMapper; Override Transactional(rollbackFor Exception.class) public void batchInsert(ListScore scoreList) { // 每 500 条一批避免 SQL 过长 int batchSize 500; for (int i 0; i scoreList.size(); i batchSize) { int end Math.min(i batchSize, scoreList.size()); scoreMapper.batchInsert(scoreList.subList(i, end)); } } }Transactional注解保证要么全成功要么全回滚。batchSize 设 500 是经验值太大容易超过 MySQL 的 max_allowed_packet太小则频繁提交影响性能。Mapper XML 里用foreach拼接 values注意 collection 参数名要和 Java 里一致。4.2 成绩查询多表联查和分页插件查询成绩时前端需要展示学生姓名和课程名称但 score 表里只有 ID。这时候有两种做法一是用 JOIN 一次性查出来二是先查 score 再根据 ID 查学生和课程。前者效率高后者代码简单但 N1 问题严重。我一般用 JOIN返回一个 ScoreVO。select idselectScorePage resultTypecom.example.vo.ScoreVO SELECT s.id, st.name AS studentName, st.student_no AS studentNo, c.course_name AS courseName, s.score, s.exam_time FROM score s LEFT JOIN student st ON s.student_id st.id LEFT JOIN course c ON s.course_id c.id where if teststudentNo ! null and studentNo ! AND st.student_no LIKE CONCAT(%, #{studentNo}, %) /if if testcourseName ! null and courseName ! AND c.course_name LIKE CONCAT(%, #{courseName}, %) /if /where ORDER BY s.id DESC /select分页用 PageHelper在 Service 里调PageHelper.startPage(pageNum, pageSize)紧跟着查 Mapper返回的 PageInfo 里就有 total 和 list。注意 startPage 之后必须紧跟查询语句中间不要插入其他数据库操作否则分页会作用到错误的 SQL 上。4.3 成绩统计平均分、及格率、分数段分布统计功能是答辩时的加分项。常见需求有每门课的平均分、及格率、各分数段人数。这些都可以用 SQL 聚合函数完成不需要在 Java 里循环计算。-- 每门课的平均分和及格率 SELECT c.course_name, AVG(s.score) AS avg_score, SUM(CASE WHEN s.score 60 THEN 1 ELSE 0 END) / COUNT(*) AS pass_rate FROM score s JOIN course c ON s.course_id c.id GROUP BY c.id, c.course_name; -- 分数段分布 SELECT CASE WHEN score 90 THEN 优秀 WHEN score 80 THEN 良好 WHEN score 70 THEN 中等 WHEN score 60 THEN 及格 ELSE 不及格 END AS level, COUNT(*) AS num FROM score WHERE course_id #{courseId} GROUP BY level;这两条 SQL 直接返回统计结果前端用 ECharts 画柱状图或饼图。注意 pass_rate 是小数前端展示时乘以 100 加百分号。如果数据量大统计查询要加缓存否则每次刷新页面都全表扫描体验很差。5. 避坑与排查源码跑不起来时先看这五条5.1 启动报 ClassNotFoundException 或 NoSuchMethodError现象Tomcat 启动时控制台抛出 ClassNotFoundException或者运行到某个接口时报 NoSuchMethodError。原因通常是依赖版本冲突比如 Spring 版本和 MyBatis 版本不匹配或者 servlet-api 重复引入。解决用mvn dependency:tree查看依赖树找到冲突的包用exclusions排除。常见的是 javax.servlet-api 在 Tomcat 和 pom 里各有一份把 pom 里的 scope 改成 provided。5.2 数据库连接失败Access denied 或 Unknown database现象启动时连不上数据库报 Access denied for user 或 Unknown database。原因一般是 jdbc.properties 里的用户名密码不对或者数据库根本没建。解决先用命令行mysql -u root -p登录确认能看到 score_manager 库然后检查配置文件里有没有多余空格密码有没有被引号包错。如果是 MySQL 8.0驱动类要改成com.mysql.cj.jdbc.DriverURL 里加时区参数。5.3 前端 npm install 卡住或报 node-sass 错误现象npm install 卡在 node-sass 下载或者报 Python 环境错误。原因是 node-sass 需要编译对 Node 版本和本机环境要求高。解决换成 sassdart-sass在 package.json 里把 node-sass 替换成 sass然后删掉 node_modules 和 package-lock.json 重新装。如果公司网络限制用npm install --registryhttps://registry.npmmirror.com走国内源。5.4 接口返回 404 或跨域错误现象前端调接口报 404或者浏览器控制台提示 CORS policy。原因404 多半是路径不对比如后端接口是/score/page前端写成了/score/list跨域是后端没加 CORS 头。解决先在后端 Controller 上确认RequestMapping的完整路径然后在浏览器直接访问接口 URL 看是否返回 JSON。跨域在后端加一个 Filter设置Access-Control-Allow-Origin、Allow-Methods、Allow-Headers或者用 Vue 的 proxy 代理。5.5 中文乱码从数据库到页面全链路排查现象页面显示的学生姓名是问号或者接口返回的 JSON 里中文变成乱码。原因可能出在数据库字符集、JDBC URL、Tomcat 编码、前端解码四个环节。解决数据库和表都用 utf8mb4JDBC URL 加characterEncodingutf8Tomcat 的 server.xml 里 Connector 加URIEncodingUTF-8前端 axios 默认就是 UTF-8不用改。如果还乱码检查 MySQL 的character_set_server变量用SHOW VARIABLES LIKE character%看一遍。6. 把源码改成自己的三个让答辩加分的改造技巧6.1 加一个角色权限控制让系统看起来更完整原始源码可能只有登录没有区分角色。你可以在 sys_user 表里加 role 字段登录成功后把角色存进 session 或 token前端根据角色渲染不同菜单。后端用拦截器校验admin 能看所有成绩teacher 只能看自己教的课student 只能看自己的成绩。这个改造不需要动核心业务但答辩时能讲出「权限模型」和「数据隔离」比单纯增删改查高一个层次。public class AuthInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { String role (String) request.getSession().getAttribute(role); String uri request.getRequestURI(); if (uri.contains(/admin/) !admin.equals(role)) { response.setStatus(403); return false; } return true; } }拦截器注册在 spring-mvc.xml 里指定拦截路径。注意登录接口和静态资源要放行否则会死循环。6.2 用 ECharts 做一个成绩看板替代干巴巴的表格成绩看板是视觉加分项。你可以在首页放三个图每门课平均分柱状图、分数段饼图、班级及格率折线图。数据从后端统计接口拿前端用 ECharts 渲染。ECharts 用 npm 安装按需引入柱状图、饼图、折线图组件避免打包体积过大。import * as echarts from echarts export default { mounted() { this.initChart() }, methods: { async initChart() { const res await request.get(/stat/courseAvg) const chart echarts.init(this.$refs.chart) chart.setOption({ xAxis: { type: category, data: res.data.map(i i.courseName) }, yAxis: { type: value }, series: [{ type: bar, data: res.data.map(i i.avgScore) }] }) } } }参数说明xAxis.data 是课程名数组series.data 是平均分数组。如果后端返回的字段名不一致在 map 里转换一下。图表容器要设固定高度否则 ECharts 初始化时拿不到尺寸图会缩成一团。6.3 导出 Excel用 POI 把成绩表变成可下载文件导出功能在答辩时很实用老师一看就知道你考虑了实际使用场景。Java 用 Apache POI前端用 window.open 或 axios 的 blob 响应。后端 Controller 返回application/vnd.ms-excel的流前端收到后创建 a 标签下载。GetMapping(/export) public void export(HttpServletResponse response) throws IOException { ListScoreVO list scoreService.listAll(); XSSFWorkbook workbook new XSSFWorkbook(); XSSFSheet sheet workbook.createSheet(成绩表); XSSFRow header sheet.createRow(0); header.createCell(0).setCellValue(学号); header.createCell(1).setCellValue(姓名); header.createCell(2).setCellValue(课程); header.createCell(3).setCellValue(分数); for (int i 0; i list.size(); i) { XSSFRow row sheet.createRow(i 1); row.createCell(0).setCellValue(list.get(i).getStudentNo()); row.createCell(1).setCellValue(list.get(i).getStudentName()); row.createCell(2).setCellValue(list.get(i).getCourseName()); row.createCell(3).setCellValue(list.get(i).getScore().doubleValue()); } response.setContentType(application/vnd.ms-excel); response.setHeader(Content-Disposition, attachment;filenamescores.xlsx); workbook.write(response.getOutputStream()); workbook.close(); }注意POI 的 XSSFWorkbook 适合 .xlsx数据量大时用 SXSSFWorkbook 避免内存溢出。文件名用英文中文文件名在不同浏览器下可能乱码需要 URLEncoder 编码。导出接口不要加拦截器权限否则前端下载会拿到 403 页面而不是文件。6.4 我踩过的一个真实教训最后说一个我自己的习惯每次改完代码先跑一遍完整流程——登录、查成绩、录成绩、导出、退出。不要只测你改的那个接口因为 SSM 的配置是全局的改一个地方可能影响另一个。有一次我改了 spring-mvc.xml 的拦截器路径结果静态资源被拦了页面样式全丢查了两个小时才发现是mvc:resources的顺序问题。所以改配置之前先备份改完之后清浏览器缓存再测。希望帮到你。本文还有配套的精品资源点击获取
返回列表