ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

基于Spring Boot+MyBatis+Vue的中学生成绩管理系统实现

基于Spring Boot+MyBatis+Vue的中学生成绩管理系统实现 简介基于 Spring Boot、MyBatis、MySQL 与 Vue 技术栈开发的学生成绩管理系统完整源码定位为高分毕业设计项目适合高校计算机相关专业的学生用于毕业设计、课程设计或期末大作业。系统采用前后端分离架构围绕成绩管理核心业务设计管理员、班主任、教师三种角色管理员统一维护用户、班主任、教师、学生及基础信息并管理成绩数据班主任可进行学生管理和成绩查看教师则支持个人信息维护与成绩查询业务划分清晰符合学校教务场景。资源包为 RAR 压缩格式共包含 215 个文件大小约 3.05MB。文件主要由 72 个 Java 源码、72 个 XML 映射与配置、27 个 Vue 页面组成覆盖后端逻辑、持久层映射和前端界面另有 JS、CSS、数据库脚本、工程说明及启动辅助文件方便初始化数据库与启动项目。目前已有 84 人学习下载该资源项目代码规范、功能完整既可直接作为毕业设计成品使用也可作为学习 Spring Boot 与 Vue 前后端分离开发、理解权限管理实现思路的实战参考。1. 为什么说这是最适合拿来改的毕设项目每年毕业季成绩管理系统都是 Java Web 方向选题里出现频率最高的题目之一但能真正跑通、能演示、能通过导师验收的其实不多。多数网上流传的版本要么数据库脚本缺失要么前端接口对不上要么用了阿里大于等已停用的短信接口。而这个基于 Spring Boot MyBatis MySQL Vue 的中学生成绩管理系统属于那种“理论模型完整、代码结构简洁、运行环境主流”的典型示例后端用三层架构把用户、班主任、教师三类角色的权限边界划清楚前端用 Vue 管理成绩展示和数据维护整条链路从数据库建表到页面渲染都能自洽。它解决的痛点很明确学校场景下成绩数据的录入、查看、统计权限是分级别的任课老师只能看自己任教科目的成绩班主任能看全班成绩管理员则负责维护所有账号和基础数据。适合的人群也分两类——如果你的毕业设计选题还没敲定这个仓库可以直接作为蓝本二次开发如果你已经在写类似系统它的角色权限划分和 Maven 目录组织方式也值得对照参考。2. Spring Boot MyBatis 的工程搭建与数据层设计2.1 为什么是这三个后端组件而不是别的成绩管理系统属于典型的 CRUD 加权限控制应用业务逻辑并不复杂难点在于数据关系的梳理。Spring Boot 负责把 MVC 的骨架搭起来自动配置机制能在不写 web.xml 的前提下完成 Servlet 容器、事务管理器、数据源的装配。MyBatis 轻量支持手写 SQL对于成绩查询这种需要多表联查的场景比 JPA 更容易控制查询性能。MySQL 则是所有表结构和无乱码环境验证过的稳定选择。具体到工程结构Maven 依赖在 pom.xml 里只需关注几个核心坐标spring-boot-starter-web提供 REST 接口能力mybatis-spring-boot-starter做 MyBatis 与 Spring 的整合mysql-connector-java负责数据库驱动再配合 Lombok 减少实体类的 Getter/Setter 样板代码。开发环境和运行时环境对应关系如下组件开发环境运行时要求JDK1.8 或 11与打包时一致Maven3.6构建机安装MySQL8.0 或 5.7服务器安装Node.js14前端构建构建时使用2.2 数据库表结构如何支撑三种角色核心表设计逻辑是“用户表 基础信息表 成绩表”三条线。用户表sys_user保存账号密码和角色类型角色用整数区分0 是管理员1 是教师2 是班主任。学生表和教师表都通过 user_id 外键关联到用户表这样登录后获取的是同一个身份数据的完整维度不用来回 join 多张表查用户昵称。成绩表score是查询频率最高的表结构上把 student_id 和 course_id 做联合业务主键另外保留 exam_id 字段用于区分期中、期末、月考等不同考试。MyBatis 的 Mapper 接口里对应这段查询逻辑Mapper public interface ScoreMapper { ListScoreVO selectScorePage(ScoreQuery query); int insertScore(Score score); int updateScore(Score score); int deleteScore(Integer id); }XML 映射文件里实现分页与条件查询时需要注意 if 标签的拼接顺序。因为成绩查询往往伴随后端返回的班级、学号、考试类型等条件条件为空时不能拼入 SQL否则会出现 WHERE 后直接跟 AND 的语法错误select idselectScorePage resultTypecom.demo.vo.ScoreVO select s.id, st.stu_no, sc.student_id, c.course_name, sc.score, sc.exam_type from score sc left join student st on sc.student_id st.id left join course c on sc.course_id c.id where if teststuNo ! null and stuNo ! and st.stu_no #{stuNo} /if if testcourseId ! null and sc.course_id #{courseId} /if if testexamType ! null and examType ! and sc.exam_type #{examType} /if /where order by sc.id desc /select这里用where标签替代手写where 11MyBatis 会自动处理第一个条件前多余的 and 或 or。#{stuNo}是预编译参数占位符可以防止 SQL 注入和${}的直接拼接有本质区别。2.3 yml 配置里最容易被忽略的两个参数application.yml 是 Spring Boot 读取数据源和 MyBatis 配置的入口。数据源需要配置驱动的时区参数尤其是 MySQL 8.x 版本spring: datasource: url: jdbc:mysql://localhost:3306/grade_system?useUnicodetruecharacterEncodingutf8serverTimezoneAsia/ShanghaiuseSSLfalse username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver mybatis: mapper-locations: classpath:mapper/*.xml type-aliases-package: com.demo.entity configuration: map-underscore-to-camel-case: truemap-underscore-to-camel-case设为 true 后数据库字段的stu_no才能自动映射到实体类属性stuNo否则你需要在结果映射里手动写 property 和 column 的对应关系。mapper-locations的值要和你实际放置 XML 的目录严格一致这是很多新手启动时报Invalid bound statement (not found)的根源。3. 后端核心业务之登录认证与角色权限控制3.1 登录接口的完整处理链路系统登录不依赖 Spring Security而是走传统的拦截器方式理解起来更直观也更适合毕设答辩时向导师解释。用户提交账号密码后后端在 UserService 里先根据 username 查询用户用 BCrypt 或 MD5 比对密码密码正确则把用户对象放进 HttpSession。这里有一个值得借鉴的细节登录成功后不直接返回成功标记而是把用户角色和跳转路径一并返回前端根据 role 值决定进入哪个首页。Controller 层的写法应该保持薄业务逻辑集中在 ServiceRestController RequestMapping(/api/user) public class UserController { Resource private UserService userService; PostMapping(/login) public Result login(RequestBody User user, HttpSession session) { User loginUser userService.login(user.getUsername(), user.getPassword()); if (loginUser null) { return Result.error(账号或密码错误); } session.setAttribute(loginUser, loginUser); return Result.success(loginUser); } }登录判断的逻辑在 Service 实现中处理通常还叠加用户状态校验比如被禁用账号不能登录。返回给前端的是 Result 包装对象结构包含 code、message、data 三个字段code 为 200 代表正常为 500 时前端直接弹出 message 内容。3.2 拦截器实现未登录跳转和角色鉴权系统有三个角色访问权限可以按接口路径来约束。管理员接口统一以/api/admin/**开头学生和教师相关的查询接口单独分配。一个自定义 HandlerInterceptor 就能同时承担登录与权限两层职责Component public class AuthInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException { HttpSession session request.getSession(); User user (User) session.getAttribute(loginUser); if (user null) { response.setStatus(401); response.setContentType(application/json;charsetUTF-8); response.getWriter().write({\code\:401,\message\:\未登录\}); return false; } String uri request.getRequestURI(); if (uri.startsWith(/api/admin/) user.getRole() ! 0) { response.setStatus(403); return false; } return true; } }最后在实现WebMvcConfigurer的配置类里注册拦截器并配置排除路径放行登录接口、静态资源和跨域预检请求Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(authInterceptor) .addPathPatterns(/api/**) .excludePathPatterns(/api/user/login, /error); }注意拦截器拦截到 401 时不能 return true否则请求会继续走 Controller 层出现“明明未登录却返回了空数据”的假象。这是排查权限漏洞时的第一个检查点。3.3 成绩新增时的事务边界成绩录入是整个系统写操作最频繁的功能涉及两张表成绩表插入一行记录同时更新统计表中的总分与平均分。如果这些操作不在同一个事务里出现异常时数据就会不一致。这里用Transactional声明事务边界Transactional(rollbackFor Exception.class) public void addScore(Score score) { scoreMapper.insertScore(score); StudentStatistic stat statisticMapper.selectByStudentId(score.getStudentId()); if (stat ! null) { stat.setTotalScore(stat.getTotalScore() score.getScore()); stat.setAvgScore(stat.getTotalScore() / stat.getCourseCount()); statisticMapper.updateStat(stat); } }这里有一条容易被忽略的规则Transactional默认只在运行时异常时回滚如果方法内部捕获了异常并吞掉事务不会回滚。在 Service 层直接让异常向上抛由全局异常处理器统一返回错误信息是更可控的做法。4. Vue 前端的页面组织与接口联调4.1 Vue CLI 项目里如何规划视图目录前端是 Vue 2 或 Vue 3 都可运行的标准工程页面按角色划分视图目录。src/views 下分别是 admin、teacher、clazz 三个文件夹admin 里放用户管理、基础信息管理、成绩管理页面teacher 里放个人信息和成绩查看clazz 里放学生管理和成绩查看。路由模式采用 history 还是 hash 会影响部署配置后端部署时也只需把前端打包的 dist 目录放进 Spring Boot 的 static 目录即可。4.2 Axios 请求封装与响应拦截跨域问题在开发环境靠 devServer 的 proxy 配置解决代理地址指向 8080 端口。生产环境下前后端同源部署不存在跨域烦恼。Axios 封装时需要在拦截器里统一附加 Session 凭证前提是withCredentials设为 trueimport axios from axios const request axios.create({ baseURL: /api, timeout: 10000, withCredentials: true }) request.interceptors.response.use( response { const res response.data if (res.code 401) { window.location.href /login return Promise.reject(new Error(res.message)) } if (res.code ! 200) { this.$message.error(res.message) return Promise.reject(new Error(res.message)) } return res }, error { return Promise.reject(error) } )把withCredentials配上很关键因为后端拦截器从 Session 中取登录用户如果前端不携带 Cookie每次请求都视为未登录。同时后端需要配置CorsConfiguration允许的来源要明确指定前端地址不能直接使用*通配符否则前端请求会触发 CORS 错误。成绩页面的表格渲染同样走生命周期函数mounted() { this.loadScoreList() }, methods: { async loadScoreList() { const res await request.get(/score/page, { params: { pageNum: this.pageNum, pageSize: this.pageSize, stuNo: this.stuNo } }) this.tableData res.data.records this.total res.data.total } }接口路径要和后端 Mapper 里的方法能力对应上。页面里传送的pageNum和pageSize字段后端 PageHelper 插件需要与配置的数据库方言配套使用MySQL 会生成 LIMIT 语句完成物理分页。4.3 角色路由与菜单渲染的实现方式不同角色登录后能看到的菜单项不同常见的实现方式有两种一是在路由配置里写meta: { role: 0 }然后用路由守卫做跳转拦截二是后端登录接口返回权限列表前端动态生成菜单组件。这个系统适合后者因为管理员需要管理用户教师菜单只有三项后端返回的菜单数据直接驱动侧边栏的 v-for 循环当用户尝试直接访问未授权路由时再结合后端的角色拦截做双保险。5. 从部署前检查到绕过常见坑的五条经验5.1 检查数据库脚本与字符集项目下载后首先要执行 SQL 脚本。注意数据库脚本里的建表语句要检查表名是否和 Mapper XML 里的 SQL 完全一致。MySQL 8.0 环境下若控制台查询中文显示乱码需要在数据源 URL 里确认characterEncodingutf8同时数据库连接时都使用 utf8mb4 字符集。5.2 Maven 打包时的资源过滤坑Spring Boot 项目打包时如果 mapper 目录下的 XML 文件没有被打进 jar 包运行 jar 就会报找不到 SQL。需要在 pom.xml 的 build 节点显式声明资源位置build resources resource directorysrc/main/java/directory includes include**/*.xml/include /includes /resource resource directorysrc/main/resources/directory /resource /resources /build如果开发时使用了 Maven 运行插件spring-boot:run方式启动资源缺失问题往往不会立刻暴露等打包成 jar 部署时才出现。提前检查 pom 的这段配置能省去很多排查时间。5.3 前端 npm install 失败时的降级方案前端依赖安装阶段最容易出现问题的是 node-sass 与 Node.js 版本不兼容。如果项目中引入了相关样式依赖看到Node Sass could not find a binding报错时建议删除 node_modules 目录后重新执行安装并固定 Node 版本。Vue CLI 项目本身要求 Node 版本在 8.9 以上推荐使用 14 或 16 版本避免高版本 Node 带来的 OpenSSL 兼容警告。若安装持续失败可以切换 npm 镜像源后重试不要反复强试默认源。5.4 验证成绩查询接口的分页字段顺序启动后端后先别急着打开前端直接使用接口测试工具验证登录与查询接口是否正常。测试成绩查询接口时注意 PageHelper 的页码参数是从 1 开始如果前端传的是 0第一页数据会查不出来。PageHelper 还会自动拦截下一条 SQL如果查询方法里自己拼接了 LIMIT 语句就会出现诡异的分页错乱只能选择信任 PageHelper 的分页机制或放弃它。5.5 演示前的最后一遍数据准备答辩演示时提前往系统里录入至少两名学生、三门课程和一次考试成绩。很多演示翻车是因为成绩列表空白让导师觉得功能没有实现。另外把管理员的密码复杂度调低演示时方便现场输入。系统的启动顺序建议先启动 MySQL 服务再运行 Spring Boot最后再启动前端这个顺序符合依赖关系也能让答辩流程流畅进行。本文还有配套的精品资源点击获取
返回列表