ARTICLE DETAIL

资讯详情

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

JavaEE学生成绩管理系统实战:从跑通到二次开发

JavaEE学生成绩管理系统实战:从跑通到二次开发 简介这是一套面向高校课程设计与Java Web入门进阶的完整学生成绩管理系统源码包基于JSP、Servlet、JDBC与MySQL实现并引入MD5加密算法覆盖学生、教师、管理员三类角色。学生端支持考勤管理、请假、选课、成绩查询与个人信息修改教师端在此基础上增加请假审核、选课信息管理、学生与班级信息管理、课程管理、成绩管理及成绩导入导出并提供可视化成绩统计管理员端额外具备教师管理功能。资源共93个文件以24个java源文件、24个class、21个jsp页面为主另含6个jar依赖、css样式、properties与xml配置、sql建库脚本及一份doc说明文档压缩包约1.7MB代码完整且注释详细。项目对操作系统、JDK、Tomcat与MySQL版本要求宽松推荐JDK1.8、Tomcat8.0与MySQL8.0以下Eclipse或IDEA均可导入运行。目前已有1487人学习下载适合需要课程设计参考、二次开发或学习JSPServlet分层开发的读者可据此快速理解权限划分、数据库设计与成绩统计的实现思路。1. 从一份 .rar 说起JavaEE 学生成绩管理系统到底能拿来干什么很多计算机专业的同学第一次接触「JavaEE学生成绩管理系统源码数据库文档.rar」这类资源往往是在课程设计或毕业设计的前两周。下载下来解压一看里面有 src 源码、一个 .sql 数据库脚本、几份 Word 文档然后就开始犯愁这东西能不能跑起来、跑起来之后怎么改成自己的、答辩的时候老师会问什么。我带过几届学生的课设也帮同事做过教务侧的二次开发可以很直接地说这类系统的价值不在于它本身多完整而在于它是一套「能跑通的最小闭环」——登录、角色权限、成绩录入、查询统计、导出这几件事串起来正好覆盖 JavaEE 的核心知识点。它适合三类人一是要交课设、需要一份能演示、能讲清楚分层架构的在校生二是想从零练一遍 Servlet/JSP 或 Spring Boot MyBatis 的转行者三是需要给小型培训机构、中小学做内部成绩登记的一线开发者。不适合直接拿去当生产系统用因为权限模型、并发写入、数据校验这些地方通常做得比较糙。下面我按「先跑通、再拆解、后改造」的顺序把这类系统从解压到二次开发的完整路径讲清楚中间会给出可复制的命令、建表语句和参数说明。2. 把压缩包跑起来环境、建库、启动三步走拿到源码包之后最忌讳的就是直接双击 IDE 打开然后一路报错。我一般会先做三件事确认 JDK 版本、确认数据库版本、确认构建方式。这三个对不上后面全是玄学问题。2.1 先看目录结构再决定用哪套技术栈解压后先别急着导入用命令行把目录树打出来看一眼# 只看两层目录避免输出太长 find . -maxdepth 2 -type d | sort # 找关键文件pom.xml 说明是 Maven 项目WEB-INF 说明是传统 Servlet 项目 find . -maxdepth 3 -name pom.xml -o -name web.xml -o -name *.sql如果看到pom.xml基本是 Spring Boot 或 SSMSpring SpringMVC MyBatis结构用 Maven 管理依赖如果只有WEB-INF/web.xml加一堆.jsp那就是传统 Servlet/JSP 项目需要 Tomcat 部署。这两种的启动方式完全不同先判断清楚能省掉一半的排查时间。常见做法是Spring Boot 项目直接找Application主类运行传统项目则配置 Tomcat把webapp目录作为部署路径。我一般会优先选 Spring Boot 那类因为依赖版本在pom.xml里写死了不容易出现 jar 包冲突。2.2 建库和导入 SQL 的具体命令数据库这块热词里提到的 MySQL 是最常见的。先建库再导脚本字符集一定要显式指定否则中文姓名和课程名会变问号-- 建库时指定 utf8mb4兼容 emoji 和生僻字 CREATE DATABASE student_score DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; -- 建一个专用账号别用 root 跑应用 CREATE USER score_applocalhost IDENTIFIED BY Score2024; GRANT ALL PRIVILEGES ON student_score.* TO score_applocalhost; FLUSH PRIVILEGES;然后导入脚本# -u 用户名 -p 回车后输密码注意路径别带中文 mysql -u score_app -p student_score db/student_score.sql # 导入后验证表是否齐全 mysql -u score_app -p -e USE student_score; SHOW TABLES;参数说明utf8mb4比utf8多支持四字节字符成绩系统里学生姓名偶尔有生僻字用utf8mb4更稳专用账号是为了避免应用配置里写 root 密码答辩时老师问「权限怎么控制的」你能答上来。导入后如果表数量对不上多半是脚本里有DROP TABLE IF EXISTS被中途打断重新导一次即可。2.3 改配置文件里的四个连接参数数据库通了之后改应用配置文件。Spring Boot 找application.yml或application.propertiesSSM 找jdbc.properties# 四个参数必须和上面建库时一致 jdbc.drivercom.mysql.cj.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/student_score?useUnicodetruecharacterEncodingutf8mb4serverTimezoneAsia/Shanghai jdbc.usernamescore_app jdbc.passwordScore2024serverTimezoneAsia/Shanghai这个参数经常被漏掉漏了之后插入时间会差 8 小时成绩录入时间全乱。characterEncodingutf8mb4要和建库字符集对应。改完启动控制台看到 Tomcat 端口或 Spring Boot 的启动 banner 就算成功。如果报Access denied回去检查账号授权如果报Unknown database说明库名拼错了。3. 拆开看骨架三层架构和成绩表怎么设计跑通只是第一步真正要改造成自己的东西得先看懂它的分层和数据模型。这类系统的骨架其实高度相似看懂了这一套换任何一份源码都能快速上手。3.1 Controller-Service-Dao 三层各自管什么标准分层是这样的Controller 接 HTTP 请求、做参数校验Service 写业务逻辑比如「录入成绩前先判断该学生该课程是否已有记录」Dao或 Mapper只负责和数据库打交道。判断一份源码质量好不好就看 Service 层有没有业务判断如果 Service 只是原样调用 Dao那说明业务逻辑全堆在 Controller 里了这种代码改起来很痛苦。以成绩录入为例合理的 Service 方法应该长这样// 录入成绩先查重再插入最后返回受影响行数 public int addScore(Score score) { // 同一学生同一课程只允许一条有效记录 Score exist scoreMapper.selectByStudentAndCourse( score.getStudentId(), score.getCourseId()); if (exist ! null) { throw new BizException(该学生该课程成绩已存在请使用修改功能); } // 分数范围校验防止前端绕过 if (score.getScore() 0 || score.getScore() 100) { throw new BizException(分数必须在 0 到 100 之间); } return scoreMapper.insert(score); }逻辑说明查重放在插入前避免同一学生同一课程出现两条记录导致统计翻倍分数校验放在后端因为前端校验可以被绕过。参数上studentId和courseId是联合唯一键的依据score用BigDecimal比double更合适避免浮点误差。3.2 成绩表设计的四个关键字段和索引成绩系统的核心表通常三张学生表、课程表、成绩表。成绩表是关联表设计好坏直接决定查询性能字段名类型说明是否索引idBIGINT主键自增主键索引student_idBIGINT学生 ID外键联合唯一索引course_idBIGINT课程 ID外键联合唯一索引scoreDECIMAL(5,2)成绩保留两位普通索引exam_timeDATETIME考试时间无create_timeDATETIME录入时间无联合唯一索引建在(student_id, course_id)上从数据库层面杜绝重复录入比只在代码里查重更可靠。score用DECIMAL(5,2)而不是FLOAT因为成绩要精确到 0.5 分浮点数会出现59.99999这种尴尬值。如果系统要按分数段统计给score加普通索引能加快WHERE score BETWEEN 60 AND 70这类查询。3.3 角色权限管理员、教师、学生看到的不该一样这类系统一般有三种角色。管理员管用户和课程教师录成绩学生只能查自己的。权限控制常见两种做法一是用拦截器判断 session 里的角色二是用 Spring Security 做方法级注解。课设级别用拦截器就够了// 拦截器里判断角色放行对应路径 public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) { String role (String) req.getSession().getAttribute(role); String uri req.getRequestURI(); // 学生只能访问查询相关接口 if (student.equals(role) uri.contains(/score/edit)) { resp.setStatus(403); return false; } return true; }这里的关键是权限判断必须放在服务端前端隐藏按钮只是体验优化不能当安全措施。我见过有课设把角色写死在 JSP 的if里学生用浏览器改一下 URL 就能进管理页答辩时被老师当场演示很尴尬。4. 避坑与排查跑不起来、乱码、查重失效的五个血泪经验这一章是我这些年帮人调这类系统攒下来的几乎每个坑都踩过不止一次。按「现象 → 原因 → 解决」写照着排查能省不少时间。4.1 启动报 404页面能开但接口全挂现象Tomcat 起来了访问首页正常但一点登录就 404。原因通常是web.xml里的servlet-mapping路径和前端请求路径不一致或者 Spring Boot 的context-path配了前缀但前端没加。解决打开浏览器 F12 看 Network 里请求的真实 URL再对照RequestMapping或web.xml里的配置把前缀对齐。如果是 Spring Boot检查server.servlet.context-path这一项很多人复制配置时带了个/api却忘了改前端。4.2 中文姓名入库变问号现象录入「张三」数据库里显示??。原因有三层数据库字符集不是utf8mb4、连接 URL 没带characterEncoding、Tomcat 的URIEncoding没设。解决按顺序查——先SHOW VARIABLES LIKE character%确认库和表的字符集再检查 JDBC URL最后在 Tomcat 的server.xml里给 Connector 加URIEncodingUTF-8。三层都对了才不会乱码只改一层往往还是问号。4.3 同一学生同一课程出现两条成绩现象统计平均分时数值偏高查明细发现重复记录。原因只在 Service 里做了查重但并发请求下两个线程同时查到「不存在」然后都插入了。解决在数据库层加联合唯一索引UNIQUE KEY uk_student_course (student_id, course_id)插入时捕获唯一键冲突异常并提示用户。代码查重是体验数据库约束才是后悔药。4.4 修改表结构后系统报字段不存在现象手动给表加了个字段重启后 MyBatis 报Unknown column。原因实体类和resultMap没同步更新或者 XML 里的字段名和数据库不一致。解决改表结构后同步改实体类属性、Mapper XML 的resultMap和insert/update语句。我一般会先改数据库再全局搜字段名确保三处都改到。用 MyBatis-Plus 的话检查TableField注解。4.5 导出 Excel 时内存溢出现象成绩条数上万后点导出直接OutOfMemoryError。原因用了POI的XSSFWorkbook把全部数据一次性加载进内存。解决换成SXSSFWorkbook流式写入或者分页查询后分批写。参数上SXSSFWorkbook(100)表示内存里只保留 100 行其余刷到磁盘临时文件。数据量再大就考虑导出 CSV比 Excel 轻量得多。5. 从课设到能交付二次开发的三个进阶技巧跑通、看懂、避坑之后如果你想让这套系统真正拿得出手还得做几件事。这一章讲三个我实际用过的技巧都是能直接提升答辩分数或交付质量的。5.1 用存储过程做班级排名别在 Java 里循环很多课设统计排名是在 Java 里查出全班成绩排序后循环赋值名次。数据量一大就慢而且代码丑。更好的做法是让数据库算-- 按课程统计班级排名用窗口函数一次算完 SELECT s.student_id, st.name, s.score, RANK() OVER (PARTITION BY s.course_id ORDER BY s.score DESC) AS rank_no FROM score s JOIN student st ON s.student_id st.id WHERE s.course_id 1001;RANK()遇到同分会给相同名次并跳号DENSE_RANK()不跳号按学校要求选。MySQL 8.0 以上才支持窗口函数5.7 得用变量模拟。这个技巧在答辩时很加分因为它体现了你懂数据库而不只是会写 CRUD。5.2 加一层缓存把课程列表这种低频数据挡住课程列表、班级列表这类数据几乎不变每次请求都查库是浪费。用 Spring Cache 加个注解就行// 课程列表加缓存增删改时清除 Cacheable(value courseList, key all) public ListCourse listAllCourses() { return courseMapper.selectAll(); } CacheEvict(value courseList, allEntries true) public void updateCourse(Course course) { courseMapper.update(course); }Cacheable第一次查库后把结果放缓存后续直接返回CacheEvict在课程变动时清掉旧数据避免脏读。默认用内存缓存单机够用要多机部署就换 Redis改一下配置即可。注意别给成绩明细加缓存那类数据变动频繁缓存反而容易出问题。5.3 用接口测试代替手点回归时省一半时间改完代码最怕的是「改 A 坏 B」。我一般会给核心接口写几个测试用例用 MockMvc 或直接 HTTP 请求// 测试成绩录入接口正常录入应返回 200 Test public void testAddScore() throws Exception { String json {\studentId\:1,\courseId\:1001,\score\:88.5}; mockMvc.perform(post(/score/add) .contentType(MediaType.APPLICATION_JSON) .content(json)) .andExpect(status().isOk()) .andExpect(jsonPath($.code).value(0)); }每次改完 Service 或 Mapper跑一遍测试就知道有没有破坏原有功能。参数上jsonPath用来断言返回体里的字段比只看状态码更严格。这套习惯我从课设一直用到工作最大的体会是手点测试只能证明「这次没坏」自动化测试才能证明「一直没坏」。最后说个我自己的教训。早年做课设我总想着把功能堆满结果每个功能都只做到半成品答辩时被问「并发下成绩会不会重复」直接卡壳。后来才明白一套系统能不能交付不看功能多少看核心链路有没有做扎实——登录、录入、查询、导出这四步每一步的边界条件都想清楚比加十个花哨模块有用。希望帮到你。本文还有配套的精品资源点击获取
返回列表