简介:这是一套基于JavaWeb的作业提交与批改系统完整项目源码,面向计算机相关专业正在做毕设的学生,以及需要项目实战练习的Java学习者,可直接作为毕业设计使用。系统采用B/S结构,后台基于JSP、Servlet与JDBC开发,以MySQL作为数据库,开发环境为JDK、Eclipse与Tomcat,并划分管理员、教师、学生三种角色。功能覆盖班级、教师、学生、公告、留言、资料及系统管理七大模块,支持信息的录入、查询、删除与打印等操作,界面美观、操作简单、管理便捷。资源包共3个文件,包含项目源码压缩包、数据库脚本sql文件及项目说明txt文档,整体约4.51MB,结构清晰,导入即可运行。项目经过严格调试,确保可以正常运行,已有3584人学习下载,适合需要快速搭建作业管理类毕设或进行JavaWeb实战练习的读者参考使用。
1. 基于JavaWeb的作业提交与批改系统:从源码到数据库脚本,一套能跑通的毕设方案
很多计算机专业本科毕设选题里,作业提交与批改系统是被选得最多、也最容易被做“水”的一类。原因很直接:业务逻辑不复杂,角色清晰(学生、教师、管理员),功能点好列,但真正动手时,大部分人卡在三个地方——JavaWeb项目在IDEA里跑不起来、数据库脚本导入后连不上、提交和批改的状态流转写成一团乱麻。这套“基于JavaWeb的作业提交与批改系统【项目源码+数据库脚本】”要解决的,就是让你拿到一份能直接导入、能跑通、能改的完整案例,而不是一堆散落的JSP页面和半截SQL。它适合正在做毕设、需要一套JavaWeb完整案例MySQL实现的人,也适合想拿一个真实业务练手SSM或Servlet+JSP的开发者。下面按“先跑通、再拆解、后避坑”的顺序讲清楚。
2. 先搞清楚这套系统在技术栈上到底怎么选:Servlet+JSP还是SSM
2.1 两种主流JavaWeb实现路线的取舍
作业提交与批改系统在JavaWeb范畴里,常见做法有两类。一类是原生Servlet+JSP+JDBC,另一类是SSM(Spring+SpringMVC+MyBatis)或SpringBoot。毕设场景下,我一般会先问一句:你的学校查重和答辩老师更看重“代码结构规范”还是“功能演示完整”?如果是前者,SSM的分层(Controller、Service、Mapper、Entity)更容易写出论文里的架构图;如果是后者,Servlet+JSP反而代码量少、调试直观,出问题一眼能看到是哪个请求没进doPost。
从热搜词“javaweb项目完整案例mysql”和“黑马javaweb笔记数据”能看出来,很多人手里其实只有Servlet+JSP的底子。这套源码如果按原生Servlet+JSP组织,目录结构通常是:src/main/java下按controller、dao、entity、util分包,src/main/webapp下放jsp、css、js和WEB-INF/web.xml。如果是SSM,会多出applicationContext.xml、spring-mvc.xml、mybatis-config.xml和mapper目录。两种都能跑,区别在于你改一个查询要动几个文件。
选型建议很实在:如果你对Spring的IOC和AOP还说不清楚,别硬上SSM,答辩时被问“这个Bean是怎么注入的”会很难受。原生Servlet+JSP配合一个简单的DBUtil工具类,足够撑起作业提交、批改、查询、统计这几个核心模块。下面所有操作都以“能跑通”为第一目标。
2.2 数据库表结构设计与脚本导入
作业提交与批改系统的数据库脚本通常包含这几张核心表:用户表(学生/教师/管理员)、课程表、作业表、提交表、批改表。字段设计上最容易翻车的是“提交表”和“批改表”要不要合并。我的血泪经验是:分开。提交表记录学生提交的文件路径、提交时间、状态(未批改/已批改);批改表记录教师给的分数、评语、批改时间。合并成一张表后,教师端查询“待批改列表”会混入已批改数据,过滤条件越写越乱。
导入脚本的标准动作是:先建库CREATE DATABASE homework_db DEFAULT CHARACTER SET utf8mb4;,再USE homework_db;,然后按“用户表→课程表→作业表→提交表→批改表”的顺序执行,因为有外键依赖。如果你用的是MySQL 8,注意脚本里的ENGINE=InnoDB和DEFAULT CHARSET=utf8mb4要显式写,否则中文评语会变成问号。导入完成后执行SHOW TABLES;确认五张表都在,再SELECT COUNT(*) FROM user;看初始账号有没有进去。
提示:数据库脚本里如果用了
DROP TABLE IF EXISTS,导入前确认你不需要保留旧数据。毕设环境无所谓,但养成先备份的习惯。
2.3 在IDEA里配置并运行JavaWeb项目
热搜词“idea运行javaweb项目配置”是高频痛点。标准流程是:File → Open选中项目根目录,等Maven或Gradle依赖下载完。如果没有构建工具,就手动File → Project Structure → Modules把src/main/java标记为Sources,src/main/webapp标记为Web资源目录。接着配置Tomcat:Run → Edit Configurations → + → Tomcat Server → Local,在Deployment标签页点+ → Artifact,选war exploded。这一步漏了,启动后访问404。
# 确认Tomcat版本与Servlet API匹配,Tomcat 9对应javax.servlet,Tomcat 10对应jakarta.servlet # 如果项目里import的是javax.servlet.*,却用了Tomcat 10,启动直接ClassNotFoundException参数说明:Application context建议设为/homework,这样访问路径是http://localhost:8080/homework/。HTTP port默认8080,被占用就改8081。启动后先访问登录页,用脚本里的初始账号登录,能进主页说明数据库连接和Tomcat都通了。如果报Communications link failure,检查DBUtil里的URL、用户名、密码,以及MySQL服务是否启动。
3. 核心功能模块的实现:提交、批改、查询三条线怎么串
3.1 学生提交作业的上传与状态写入
作业提交的核心是文件上传加数据库记录。原生Servlet里用@MultipartConfig注解配合request.getPart("file")拿文件,存到服务器磁盘的upload目录,再把相对路径写进提交表。这里有个容易忽略的点:文件名要加时间戳或UUID,否则两个学生传同名文件会互相覆盖。
@WebServlet("/submitHomework") @MultipartConfig(maxFileSize = 1024 * 1024 * 10) public class SubmitHomeworkServlet extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { int homeworkId = Integer.parseInt(request.getParameter("homeworkId")); int studentId = (int) request.getSession().getAttribute("userId"); Part filePart = request.getPart("file"); String originalName = filePart.getSubmittedFileName(); // 用UUID避免同名覆盖,保留原扩展名 String savedName = UUID.randomUUID().toString() + "_" + originalName; String savePath = getServletContext().getRealPath("/upload") + File.separator + savedName; filePart.write(savePath); // 写入提交表,状态默认为0(未批改) SubmissionDao.insert(homeworkId, studentId, savedName, new Timestamp(System.currentTimeMillis())); response.sendRedirect("student/submissionList.jsp"); } }逻辑说明:maxFileSize限制10MB,防止大文件拖垮服务器。getSubmittedFileName()在Servlet 3.1才可用,老版本要用Part的getHeader("content-disposition")解析。savePath用getRealPath拿到webapp下的真实路径,部署到Tomcat后文件在webapps/homework/upload。参数上,homeworkId和studentId从请求和session取,不要从表单隐藏域取studentId,否则学生可以伪造提交。
3.2 教师批改的分数录入与状态回写
批改模块要处理两件事:插入批改记录、更新提交表状态。这两步必须在一个事务里,否则可能出现“批改记录有了但状态还是未批改”的脏数据。原生JDBC下手动控制事务:conn.setAutoCommit(false),两条SQL都成功后commit(),异常则rollback()。
public boolean gradeSubmission(int submissionId, int teacherId, int score, String comment) { Connection conn = null; try { conn = DBUtil.getConnection(); conn.setAutoCommit(false); // 插入批改记录 String insertSql = "INSERT INTO grade(submission_id, teacher_id, score, comment, grade_time) VALUES(?,?,?,?,NOW())"; PreparedStatement ps1 = conn.prepareStatement(insertSql); ps1.setInt(1, submissionId); ps1.setInt(2, teacherId); ps1.setInt(3, score); ps1.setString(4, comment); ps1.executeUpdate(); // 更新提交状态为已批改 String updateSql = "UPDATE submission SET status = 1 WHERE id = ?"; PreparedStatement ps2 = conn.prepareStatement(updateSql); ps2.setInt(1, submissionId); ps2.executeUpdate(); conn.commit(); return true; } catch (Exception e) { if (conn != null) try { conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } e.printStackTrace(); return false; } finally { DBUtil.close(conn); } }参数说明:score建议在Service层做范围校验(0-100),数据库字段用TINYINT UNSIGNED或INT都行,但前端要限制输入。comment字段用TEXT类型,避免评语长了被截断。grade_time用NOW()由数据库生成,比Java端new Date()更可靠,不受服务器时区影响。
3.3 作业列表与批改结果的分页查询
学生端要看“我的提交记录”,教师端要看“待批改列表”,管理员要看“全部作业”。这三个查询本质是同一张表加不同WHERE条件,区别在分页。原生Servlet里分页靠LIMIT offset, size,offset = (pageNum - 1) * pageSize。热搜词“jmeter数据库压测脚本”提醒我,分页查询是压测重点,因为LIMIT在大偏移量下会变慢,毕设数据量小无所谓,但要知道这个边界。
-- 教师端待批改列表,按提交时间倒序 SELECT s.id, u.real_name AS studentName, h.title AS homeworkTitle, s.submit_time FROM submission s JOIN user u ON s.student_id = u.id JOIN homework h ON s.homework_id = h.id WHERE s.status = 0 AND h.teacher_id = ? ORDER BY s.submit_time DESC LIMIT ?, ?;逻辑说明:status = 0过滤未批改,h.teacher_id = ?确保教师只看到自己布置的作业。LIMIT的两个参数分别是offset和size,在Java里用ps.setInt(1, offset)和ps.setInt(2, pageSize)传入。如果查询结果为空,前端要显示“暂无待批改作业”,而不是空白页。分页导航的总页数用SELECT COUNT(*)单独查一次,不要用resultSet.last()再getRow(),那个在数据量大时会把所有行拉到内存。
4. 避坑与排查:这套系统跑不起来时先看这5条
4.1 现象:Tomcat启动报ClassNotFoundException,找不到javax.servlet
原因:Tomcat 10及以上版本把Servlet API从javax.servlet改成了jakarta.servlet,而项目源码里import的还是旧包。解决:要么换Tomcat 9,要么全局替换import为jakarta.servlet.*,同时web.xml的schema也要换。毕设环境建议直接用Tomcat 9,省去改包麻烦。
4.2 现象:数据库连接失败,报Access denied for user
原因:DBUtil里的用户名密码和MySQL实际不一致,或者MySQL 8的caching_sha2_password认证插件导致旧驱动连不上。解决:确认mysql-connector-java版本在8.0以上,URL加?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true。如果还不行,用ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '你的密码';改认证方式。
4.3 现象:文件上传后找不到,upload目录是空的
原因:getRealPath("/upload")在Tomcat中指向的是webapps/项目名/upload,但IDEA的war exploded模式下,这个目录可能还没创建。解决:在Servlet里先new File(savePath).getParentFile().mkdirs(),或者手动在webapp下建一个空的upload文件夹并放一个.gitkeep。另外,每次重新部署war包,之前上传的文件会被清掉,这是正常现象,毕设演示前重新传一次即可。
4.4 现象:中文评语存进数据库变成问号
原因:数据库、表、连接三处的字符集不一致。解决:建库时CHARACTER SET utf8mb4,建表时同样指定,JDBC URL加characterEncoding=utf8。如果已经建好表,用ALTER TABLE grade CONVERT TO CHARACTER SET utf8mb4;改。注意utf8在MySQL里是阉割版,存emoji会失败,统一用utf8mb4。
4.5 现象:学生能提交,但教师端看不到待批改记录
原因:提交时homework_id写错了,或者教师查询时teacher_id对不上。解决:先SELECT * FROM submission;看homework_id有没有值,再SELECT * FROM homework WHERE id = ?;看这条作业的teacher_id是谁。常见错误是前端传的homeworkId是字符串,后端Integer.parseInt没做异常捕获,解析失败后写入了0。
5. 进阶技巧:用状态机思路重构提交与批改的流转,以及一套自测清单
这套系统跑通之后,如果你想在答辩时多拿几分,我建议把“提交-批改”的状态流转显式化。现在很多毕设代码里,状态就是0和1两个数字,散落在各个Servlet里,改一个地方要全局搜。更稳的做法是定义一个枚举或常量类,把状态和允许的操作绑在一起。
public enum SubmissionStatus { SUBMITTED(0, "已提交待批改"), GRADED(1, "已批改"), RETURNED(2, "已退回重做"); private final int code; private final String desc; SubmissionStatus(int code, String desc) { this.code = code; this.desc = desc; } public int getCode() { return code; } public String getDesc() { return desc; } // 判断当前状态是否允许批改 public boolean canGrade() { return this == SUBMITTED; } // 判断是否允许学生重新提交 public boolean canResubmit() { return this == RETURNED; } }逻辑说明:canGrade()和canResubmit()把业务规则收进枚举,Servlet里只调if (status.canGrade()),不用再写if (status == 0)。参数上,code存数据库,desc给前端显示。这样教师点“批改”时,如果状态是GRADED,直接提示“该作业已批改”,而不是重复插入批改记录。这个改动不大,但论文里可以写成“基于状态机的作业流转控制”,听起来比“用0和1表示状态”专业得多。
再给一套我每次交付前必跑的自测清单,按顺序执行,能覆盖90%的翻车点:
| 检查项 | 操作 | 预期结果 |
|---|---|---|
| 数据库连接 | 启动Tomcat后访问登录页 | 页面正常渲染,无500错误 |
| 初始账号 | 用脚本里的学生/教师账号分别登录 | 进入各自主页,菜单不同 |
| 作业提交 | 学生登录后提交一个txt文件 | 提交表新增记录,upload目录有文件 |
| 待批改列表 | 教师登录后查看待批改 | 能看到刚才的提交记录 |
| 批改操作 | 输入分数和评语,点提交 | 批改表新增记录,提交状态变1 |
| 学生查看结果 | 学生刷新提交记录 | 显示分数和评语,状态为已批改 |
| 中文显示 | 评语输入中文 | 数据库和页面均无乱码 |
| 重复批改 | 对同一条记录再次批改 | 提示已批改,不产生第二条记录 |
这套清单跑完,基本可以放心演示。最后说个我自己的习惯:每次改完代码,先把数据库脚本重新导入一遍,再启动Tomcat,从登录开始完整走一遍流程。不要只测你刚改的那个功能,因为作业提交与批改系统的模块之间耦合比看起来紧——改了下拉框的课程ID,可能就影响了作业列表的过滤条件。毕设答辩前留出两天做这种全流程回归,比熬夜改新功能有用得多。希望帮到你。
本文还有配套的精品资源,点击获取