ARTICLE DETAIL

资讯详情

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

SpringBoot学生成绩管理系统项目实战:从Controller到Mapper的完整解析

SpringBoot学生成绩管理系统项目实战:从Controller到Mapper的完整解析 简介这是一份基于Spring Boot的学生成绩管理系统期末大作业源码与数据库打包面向Java初学者及需要完成课程设计的高校学生。系统覆盖管理员、教师、学生三类角色包含登录验证、班级管理、课程管理、成绩录入与查询、考勤记录等常见功能模块后端类包含Controller控制器、实体类及工具类并通过Mapper映射文件操作数据库代码结构清晰适合作为毕业设计或课程设计的参考模板。压缩包共648个文件约2.44MB包括Java源文件、class编译文件、html/css/js前端页面、xml的MyBatis映射文件、png图标及sql数据库脚本等其中png用于界面素材sql包含建表语句与初始数据目录按后端逻辑、静态资源、模板和全局配置拆分便于查阅。项目基于IntelliJ IDEA与Maven构建数据库使用MySQLpom.xml已整合依赖导入后还原环境即可运行测试。目前已有2872人学习下载适合需要快速掌握Spring Boot整合MyBatis和角色权限管理的读者参考。1. 压缩包里是 SpringBoot 学生成绩管理系统先看清它解决了什么问题看到压缩包里的 ScoreController.class、AttendanceController.class 这些文件先别急着双击。这套期末大作业是基于 SpringBoot 的学生成绩管理系统前端页面在 templates数据库脚本单独放在压缩包里覆盖了登录、班级、学生、成绩、考勤和选课。选它当大作业稳妥之处在于技术栈集中重点全在 Controller、Service、Mapper 三层怎么配合适合拿去应付数据库课程设计也能帮人理解 springboot 框架的常规开发方式。我拆项目先看结构再跑通最后改需求。SpringBoot 与传统 JavaWeb 的差别是不用手动配置一堆 XML启动入口和自动装配帮忙省了很多事但前提是先搞清 maven 依赖、application.yml 和数据库三者的关系。这个项目适合做期末大作业的学生也适合想上手 springboot 项目的初级开发。只要你会装 MySQL 和 IDEA按后面步骤操作半天之内能跑起来。2. 从压缩包反推项目结构Controller、Util、Mapper 在 SpringBoot 里如何分工拿到源码先看命名规则。压缩包里的 java 目录放着 ScoreController.class、SystemController.class、StudentController.class、TeacherController.class、AttendanceController.class、ClazzController.class、SelectedCourseController.class还有 CpachaUtil.class。这些类名的第一个词基本就是业务模块Controller 后缀是接口层Util 后缀是辅助工具。resources 目录里则放着 mapper、static、templates 和 application.yml。这套结构在 SpringBoot 项目里非常标准梳理顺序一般是先看配置文件再看实体然后看 Controller 路由最后看 Mapper XML。2.1 按业务模块划分 Controller路由设计和类名一一对应Controller 类名对应的是页面路由。ScoreController 管成绩StudentController 管学生TeacherController 管教师AttendanceController 管考勤ClazzController 管班级SelectedCourseController 管选课SystemController 负责登录和验证码。这是典型的按业务模块划分 Controller 的方式每个类里的方法通过 RequestMapping 或 GetMapping 暴露端点。比如你访问/score/listScoreController 里某个方法会接住请求调用 Service再由 Service 调用 Mapper 访问数据库。实体类 Teacher、Student 是数据载体和数据库表字段对应Controller 返回的数据最终会拼成 JSON 或渲染到模板页面里。这些模块的路径对应关系可以归纳成下面这张表方便你对崩溃报告里出现的 Controller 名快速定位Controller路径前缀主要职责SystemController/system登录、验证码、退出StudentController/student学生信息增删改查TeacherController/teacher教师信息管理ClazzController/clazz班级管理和列表ScoreController/score成绩录入、修改、查询AttendanceController/attendance考勤记录与统计SelectedCourseController/selected_course选课与退选上面这张表也体现了 StudentController 与 TeacherController 的相似性。如果你要模仿这个项目做自己的 springboot 大作业只需要把模块名换掉Controller 内部的代码骨架基本不用大变。这就是 SpringBoot 框架容易上手的原因也是答辩时最常被问到的知识点。2.2 resources 目录里的 mapper、static、templates 各管什么改页面去哪找resources 目录是 SpringBoot 约定的资源根目录。mapper 文件夹放的是 MyBatis 的 XML里面写与表相关的 SQL 操作和 java 目录下对应的 Mapper 接口同名同包。static 放静态资源比如 css、js、图片不需要后端渲染的样式都丢这里。templates 放的是服务端渲染的 HTML 页面里面经常出现${}占位符把后端 Model 里的数据填进表格。这三个目录职责不同但经常被放错有人把 js 顺手放到了 templates结果页面 404原因就是静态资源没有走 static 路径。为什么要这样分因为学生成绩管理系统的页面大多是表格加表单服务端渲染比前后端分离更容易控制登录状态也方便期末演示。修改前端页面时优先看 templates 下同名 html 和 static 下对应 js不要动 application.yml 里的视图解析配置。SpringBoot 默认会去 classpath:/templates/ 找模板文件如果前后端改成了 Vue这部分的职责完全不同混用会出很多诡异问题。2.3 pom.xml 与 application.ymlmaven 依赖决定用什么全局配置决定怎么跑打开 pom.xml能看到 spring-boot-starter-web、mybatis-spring-boot-starter、mysql-connector-java 这些依赖。它们决定了项目能用哪些注解和 API。引入 web starter 后才有 RestController引入 mybatis starter 后才有 MapperScan。如果你换电脑后编译报错优先看 maven 仓库里有没有对应 jar 包再从 pom.xml 检查版本是否冲突。application.yml 是 springboot 项目最关键的配置文件数据库连接、端口、MyBatis 驼峰映射都在这。一个典型的配置如下server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/studentmanager?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai username: root password: 123456 thymeleaf: cache: false mybatis: mapper-locations: classpath:mapper/*.xml configuration: map-underscore-to-camel-case: true这里的server.port是后端服务端口改成 8081 后前端请求地址也得跟着变。datasource.url里的studentmanager是数据库名必须和你导入的库名一致characterEncodingutf8保证中文不乱码serverTimezoneAsia/Shanghai是 MySQL 8 必须加的时区参数不加会报时区异常。mapper-locations: classpath:mapper/*.xml告诉 MyBatis 去 resources 下的 mapper 目录找 SQL 文件map-underscore-to-camel-case让数据库字段s_name自动映射成实体属性sName少写很多 resultMap。这套配置在绝大多数 springboot 项目中可以通用区别只有数据库名、用户密码和中间件地址。启动项目前先把 pg 里这几个值和本机环境对上能够省掉至少一半的启动报错。3. 核心模块逐个拆CpachaUtil、ScoreController、AttendanceController 的实现要点系统真正能演示的都在这些核心模块里。登录时验证码怎么生成、成绩怎么录入、考勤怎么统计、选课怎么防重复每一项都能展开讲很久。这里先把最容易出问题的几个点拆开代码片段可以直接沿用。3.1 CpachaUtil 验证码工具图片生成与 session 校验流程CpachaUtil 是压缩包里专门处理验证码的工具类一般会在一个方法里生成图片和验证码字符串把字符串存到 session再把图片以流的形式写到 response。它的核心参数包括验证码长度、图宽高、干扰线数量。下面的代码是常见的图形渲染逻辑public class CpachaUtil { private int width; private int height; private int codeCount; private int lineCount; public BufferedImage generatorBufferedImage(String code) { BufferedImage image new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D g image.createGraphics(); g.setColor(Color.WHITE); g.fillRect(0, 0, width, height); for (int i 0; i lineCount; i) { g.setColor(new Color(random.nextInt(200), random.nextInt(200), random.nextInt(200))); g.drawLine(random.nextInt(width), random.nextInt(height), random.nextInt(width), random.nextInt(height)); } for (int i 0; i code.length(); i) { g.setColor(new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256))); g.setFont(new Font(Arial, Font.BOLD, height - 10)); g.drawString(String.valueOf(code.charAt(i)), i * (width / codeCount) 5, height - 8); } g.dispose(); return image; } }这段代码里codeCount决定验证码位数lineCount决定干扰线密度。它只负责画图真正的校验在登录接口把用户输入的验证码和 session 中存的字符串比较忽略大小写一致才继续查数据库。做二次开发时给验证码加上 60 秒超时更稳妥避免验证码长期有效被脚本反复利用。将验证码存 session 有个好处登录逻辑和登录页在同一会话内校验过程不暴露给前端。若项目日后改为前后端分离这个逻辑要换成 redis用 UUID 关联验证码和请求答辩时被问到验证码为什么放 session可以从会话隔离和实现简单两个角度回答。这是一个加分点。3.2 ScoreController 成绩模块分页查询的参数设计和录入口径成绩模块是系统的核心ScoreController 的接口通常有分页查询、按学号或姓名搜索、录入成绩、修改成绩、删除成绩。学习这个模块时重点看RequestParam的参数怎么设计以及成绩插入前有没有做数值校验。一个常见的接口如下RestController RequestMapping(/score) public class ScoreController { Autowired private ScoreService scoreService; GetMapping(/list) public Result list(RequestParam(defaultValue 1) Integer page, RequestParam(defaultValue 10) Integer size, RequestParam(required false) String studentName) { PageResultScore result scoreService.findPage(page, size, studentName); return Result.success(result); } PostMapping(/add) public Result add(RequestBody Score score) { scoreService.save(score); return Result.success(null); } }page和size是分页参数默认值分别为 1 和 10studentName是可选模糊搜索required false表示不传时查出全部。录入成绩时Service 层要先校验学生和课程是否存在再判断分数范围最后执行 insert。如果成绩表在student_id course_id上有唯一索引重复录入会抛出DuplicateKeyException代码里要把这个异常转成该学生此课程成绩已存在的业务提示而不是把异常堆栈直接抛给页面。成绩数值建议用decimal(5,2)存储。为什么不用 float因为平时分和期末分相加可能出现小数浮点数有精度误差decimal 是精确数值类型。此外前端传成绩时如果按字符串接后端要统一做一次BigDecimal转换别在中途用 double 参与计算否则分数会带上很难看的尾数。3.3 AttendanceController 考勤模块status 用数字还是字符串统计怎么设计考勤模块的核心是记录每个学生的出勤状态。常见状态包括出勤、迟到、请假、缺席。这个项目里 AttendanceController 的实现通常用数字 0/1/2/3 表示状态页面显示时再翻译成中文。这样的好处是统计代码简单直接对数字做聚合比如统计迟到次数可以用sum(case when status 1 then 1 else 0 end)。如果状态存中文聚合语句会变得很啰嗦还容易因为全角半角差异出问题。状态码要提前定好建议做成常量或枚举PRESENT3、LATE1、LEAVE2、ABSENT0。这样代码里写status 1还不如写status AttendanceStatus.LATE可读性高。生成考勤报表时再用 switch 或 map 把数字转成中文前端拿到的要么是数字要么是已经转好的文本不要两边各转一次。3.4 SelectedCourseController 选课模块重复选课不能只靠 Controller 拦选课模块的核心不是列出课程而是防止同一学生重复选择同一门课。很多人在 Controller 里先select判断再决定是否insert正常操作没问题但连续点击两次时两个请求可能都通过了检查最后插入两条重复记录。正确的做法是在数据库层兜底给s_selected_course表加student_id course_id唯一索引插入失败时捕获DuplicateKeyException再给出业务提示。即便用了唯一索引Controller 里也建议保留select count校验目的不是为了防并发而是为了给用户更快的响应。两者结合使用既保证提示友好又保证极端情况下数据不会错。这个思路放在订单、报名、预约类功能里同样适用面试时换个场景回答会显得有设计经验。4. studentmanager 数据库设计从 s_admin 到选课表表结构和 Mapper 映射怎么对齐数据库是整个系统最值得阅读的部分。压缩包里提供了 MySQL 脚本数据库名为 studentmanager。摘要中明确点出的管理员信息表是 s_admin但一个完整的学生成绩管理系统至少还应该有班级表、学生表、教师表、课程表、成绩表、考勤表和选课表。这些表都带s_前缀既好识别也避免和 MySQL 保留字冲突。4.1 核心表字段设计与关系说明下面这张表把这个项目常见的表结构归纳出来了导入数据库后可以逐张对照表名业务含义主要字段s_admin管理员id, username, passwords_clazz班级id, c_name, create_times_student学生id, s_no, s_name, clazz_id, passwords_teacher教师id, t_no, t_name, passwords_course课程id, c_no, c_name, teacher_ids_score成绩id, student_id, course_id, scores_attendance考勤id, student_id, course_id, status, work_dates_selected_course选课id, student_id, course_id, create_time从字段能看出关系的走向s_student 通过 clazz_id 挂在班级下s_course 通过 teacher_id 挂在教师下s_score 和 s_attendance 都通过 student_id 和 course_id 关联到具体学生和课程。s_selected_course 的表也会使用联合唯一索引来保证不重复选课。这里学生表的 s_no 通常是学号具有唯一性除了作为登录账号外还承担打印成绩单时的标识作用所以建表时应该加 unique key。密码字段password长度设置为 64 或更长比较保险。如果用户用了 MD5 加密32 位足够但要存储 BCrypt 密文64 位是基本要求。把密码长度设置在 32 位以下后面想换更安全的加密算法就不得不改表结构很麻烦。4.2 建表语句里的外键和索引选择导入前注意什么数据库脚本导入时如果报错常见原因有两个一个是脚本顺序问题先插入成绩数据但学生表还没建另一个是字符集不是 utf8导致中文乱码或者建表失败。下面是一个典型的 s_score 建表语句片段CREATE TABLE s_score ( id bigint NOT NULL AUTO_INCREMENT, student_id bigint NOT NULL, course_id bigint NOT NULL, score decimal(5,2) DEFAULT NULL, create_time datetime DEFAULT NULL, PRIMARY KEY (id), UNIQUE KEY uk_student_course (student_id,course_id), KEY idx_student (student_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;这段建表语句中uk_student_course是联合唯一索引防止成绩重复idx_student是普通索引加速按学生查询成绩。用utf8mb4而不是utf8是因为 utf8mb4 能存 emoji 和更多生僻字虽然本类系统用不到但这是 MySQL 8 的推荐做法。导入前用source命令或 Navicat 执行脚本后先检查表数量和行数再继续改配置。4.3 Mapper XML 的 namespace、resultMap 和参数绑定MyBatis 的 mapper XML 必须和接口对应否则启动后会报Invalid bound statement (not found)。这个项目里resources/mapper 下的每个 XML 的 namespace 要和 Java 里 Mapper 接口全限定名一致比如com.example.mapper.StudentMapper。一个典型的查询接口和 XML 如下Mapper public interface StudentMapper { Student findById(Param(id) Integer id); }mapper namespacecom.example.mapper.StudentMapper select idfindById parameterTypeinteger resultTypecom.example.entity.Student select id, s_no, s_name, clazz_id from s_student where id #{id} /select /mapper#{id}是预编译占位符MyBatis 会把它转成?再用 PreparedStatement 设置参数能有效防止 SQL 注入。${}则是字符串拼接只有当参数是排序字段或表名时才用而且必须人工校验白名单。resultType 直接指定实体类时MyBatis 按字段名映射s_name到sName靠的是驼峰映射配置如果查询用了别名别名的命名也要匹配 Java 属性比如select s_name as sName。实体类属性与列名的映射是最容易出问题的地方。create_time对应createTimeclazz_id对应clazzId。如果你改了表结构又忘记改实体类MyBatis 不会报错只是返回的对象属性为 null。这类 bug 排查比较费时间可以先在浏览器看接口响应再用日志打印 Mapper 返回结果基本能定位到是映射问题还是 SQL 结果集问题。4.4 s_admin 登录表和密码加密的常见做法s_admin 是系统入口字段通常只有 id、username、password。登录前先根据 username 查出 admin再比较密码。如果脚本里的密码是明文建议手动改成一个复杂密码再开始演示。常见加密方式如下String encoded DigestUtils.md5DigestAsHex(password.getBytes(StandardCharsets.UTF_8));DigestUtils来自 spring-core不需要额外引包。注意 MD5 只适合课程设计这类演示环境生产环境应该换 BCrypt。如果项目里用了 BCrypt登录校验多用BCryptPasswordEncoder.matches(rawPassword, encodedPassword)不要自己解密因为 BCrypt 不是可逆加密只能校验。这块知识点在 springboot 面试题里出现频率很高能说出MD5 加盐和 BCrypt 的区别已经比大多数只背框架的人强了。5. 在 IDEA 里把项目跑通启动顺序、配置修改和验证清单5.1 导入项目与三步启动法第一步打开 IDEA选择 Open 项目根目录等 Maven 自动下载依赖。如果右下角没有 Maven 项目提示手动右侧 Maven 面板刷新。第二步在 MySQL 里新建数据库 studentmanager执行解压出来的 studentmanager.sql导入后确认表出现。第三步修改 application.yml 中的账号密码然后运行主启动类。顺序不要颠倒先改配置再导库容易出现连不上库的假象。5.2 常见报错与处理报错关键词原因处理Access denied for user用户名密码错误修改 application.ymlUnknown database库名不对或没导入确认库名是 studentmanagerInvalid bound statementmapper XML 未匹配检查 namespace 和接口名Port 8080 was already in use端口被占用改 server.port 或释放端口Table doesnt existsql 未导入或导错库重新导入脚本如果出现Failed to configure a DataSource说明 SpringBoot 启动时没有拿到可用的数据源优先检查 application.yml 的 url 和驱动类名。Windows 下 MySQL 8 常见的问题还包括驱动包版本过低pom.xml 里应该使用mysql-connector-java8.x与 MySQL 8 服务端匹配。5.3 跑通后的验证清单服务启动后访问http://localhost:8080能看到登录页并显示验证码说明静态资源和模板目录正常。用 s_admin 里的账号登录进入后台后依次点开学生列表、班级列表、成绩录入、考勤添加、选课页面。每一步都打开浏览器开发者工具看网络请求状态码 200 只代表请求到达还要看响应体里的数据是否和数据库一致。最后建议做一次端到端演练新增一个学生给该学生录入成绩再添加考勤记录最后查询成绩列表确认同一条数据。这样可以验证从 Controller 到 Mapper 再到数据库的整条链路。项目跑通后再回看 Controller 和 Service 的代码你会发现 springboot 开发的核心其实不是会写接口而是能把请求参数、业务逻辑和数据库三者缝得不出错。本文还有配套的精品资源点击获取
返回列表