news 2026/9/23 17:35:42

JavaWeb作业提交与批改系统毕设:SpringBoot+Vue全栈实现与数据库脚本设计

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JavaWeb作业提交与批改系统毕设:SpringBoot+Vue全栈实现与数据库脚本设计

简介:这是一套基于JavaWeb的作业提交与批改系统项目源码,面向计算机相关专业正在做毕设的学生以及需要项目实战练习的Java学习者,可直接作为毕业设计使用。系统采用B/S结构,后台基于JSP、Servlet与JDBC实现,以MySQL作为数据库,开发环境为JDK、Eclipse与Tomcat,并划分管理员、教师、学生三种角色。功能上覆盖班级、教师、学生、公告、留言、资料及系统管理七大模块,支持信息的录入、查询、删除与打印等操作,界面美观、操作简单,具备较高的实际应用价值。资源包共3个文件,包含项目源码压缩包、数据库脚本sql文件以及项目说明txt文档,整体约4.51MB,源码与脚本均已严格调试,可正常运行。目前已有3583人学习下载,适合希望快速搭建作业管理类系统、理解JavaWeb分层开发与数据库设计的读者参考使用。

1. 从一份“能跑起来”的作业提交与批改系统说起

很多同学做毕设时,选题定成“基于JavaWeb的作业提交与批改系统”,第一反应是去搜“javaweb项目完整案例mysql”,然后复制一份代码改改界面就交差。但真正答辩时被问到“学生提交的作业文件怎么存”“教师批改状态怎么流转”“数据库脚本为什么这样设计”,往往答不上来。这个标题背后其实是一套完整的业务闭环:学生上传作业、系统记录提交状态、教师下载批阅、回填分数与评语、学生查看结果。它适合计算机毕设选题中偏管理信息系统方向的同学,也适合想用SpringBoot+Vue毕设练手全栈开发的人。核心难点不在页面多漂亮,而在文件存储策略、状态机设计和数据库表关系是否经得起追问。下面按理论选型、库表设计、后端实现、前端联调、部署排错的顺序,把一套可复现的方案讲清楚。

2. 作业提交与批改系统的技术选型与数据库脚本设计

2.1 为什么用 Spring Boot + MyBatis-Plus 而不是纯 Servlet

标题写的是 JavaWeb,但 2024 年之后的毕设如果还用 JSP + Servlet 裸写,代码量会膨胀到难以维护。常见做法是保留 JavaWeb 的 MVC 分层思想,用 Spring Boot 做容器和自动配置,MyBatis-Plus 做数据访问。这样既符合“JavaWeb”的范畴,又能让答辩老师看到你对主流框架的掌握。选型理由有三点:第一,Spring Boot 内嵌 Tomcat,idea运行javaweb项目配置时不需要单独装 Tomcat;第二,MyBatis-Plus 的BaseMapper能省掉大量单表 CRUD;第三,前后端分离后 Vue 负责交互,Java 端只返回 JSON,职责清晰。

依赖版本建议锁定 Spring Boot 2.7.x 和 MyBatis-Plus 3.5.x,JDK 用 8 或 11,MySQL 用 5.7 或 8.0。不要盲目追 Spring Boot 3.x,因为部分毕设环境里的 JDK 还是 8,贸然升级会导致javax包名变成jakarta,启动直接报错。

2.2 数据库脚本的核心表与字段说明

数据库脚本是毕设查重和答辩的重点。作业提交与批改系统至少需要五张表:用户表、课程表、作业表、提交记录表、批改记录表。下面给出建表脚本的关键部分,可直接在 MySQL 中执行。

-- 用户表:区分学生、教师、管理员 CREATE TABLE `sys_user` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `username` VARCHAR(50) NOT NULL COMMENT '登录名', `password` VARCHAR(100) NOT NULL COMMENT 'BCrypt加密', `real_name` VARCHAR(50) DEFAULT NULL, `role` TINYINT NOT NULL COMMENT '1学生 2教师 3管理员', `class_id` BIGINT DEFAULT NULL COMMENT '学生所属班级', PRIMARY KEY (`id`), UNIQUE KEY `uk_username` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 作业表:教师发布的作业任务 CREATE TABLE `homework` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `course_id` BIGINT NOT NULL, `title` VARCHAR(200) NOT NULL, `content` TEXT, `deadline` DATETIME NOT NULL COMMENT '截止时间', `create_by` BIGINT NOT NULL COMMENT '教师ID', `status` TINYINT DEFAULT 1 COMMENT '1进行中 0已截止', PRIMARY KEY (`id`), KEY `idx_course` (`course_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; -- 提交记录表:一个学生一份作业只有一条有效记录 CREATE TABLE `submission` ( `id` BIGINT NOT NULL AUTO_INCREMENT, `homework_id` BIGINT NOT NULL, `student_id` BIGINT NOT NULL, `file_path` VARCHAR(255) DEFAULT NULL COMMENT '相对存储路径', `file_name` VARCHAR(255) DEFAULT NULL, `submit_time` DATETIME DEFAULT CURRENT_TIMESTAMP, `status` TINYINT DEFAULT 0 COMMENT '0未批改 1已批改', `score` DECIMAL(5,1) DEFAULT NULL, `comment` VARCHAR(500) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uk_hw_stu` (`homework_id`,`student_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

uk_hw_stu唯一索引是关键,它保证同一个学生对同一份作业只能提交一次,后续再交就是更新操作。file_path存相对路径而不是绝对路径,方便迁移服务器。status字段驱动整个批改流程,教师端查询时只查status=0的记录。

2.3 文件存储路径与上传大小限制

作业文件不能存进数据库 BLOB,否则备份和查询都会变慢。常见做法是在application.yml里配置本地磁盘目录,并用日期分目录避免单目录文件过多。

spring: servlet: multipart: max-file-size: 20MB max-request-size: 20MB file: upload-dir: /data/homework/upload/ allowed-ext: pdf,doc,docx,zip,rar

max-file-size限制单文件 20MB,超过会抛MaxUploadSizeExceededException,需要在全局异常处理器里捕获并返回友好提示。allowed-ext做后缀白名单,防止上传可执行文件。存储时用homeworkId/studentId_时间戳.后缀命名,既避免重名又便于追溯。

3. 后端接口实现:提交、批改与状态流转

3.1 学生提交作业的接口与文件落盘逻辑

学生提交作业的接口需要同时处理文件流和表单字段。用MultipartFile接收文件,先校验作业是否已截止,再判断是新增还是更新提交记录。

@PostMapping("/submit") public Result submit(@RequestParam Long homeworkId, @RequestParam("file") MultipartFile file, HttpServletRequest request) { Long studentId = getCurrentUserId(request); Homework hw = homeworkMapper.selectById(homeworkId); // 截止时间校验 if (hw.getDeadline().before(new Date())) { return Result.fail("已过截止时间,无法提交"); } // 后缀白名单 String ext = FileUtil.getSuffix(file.getOriginalFilename()); if (!allowedExt.contains(ext)) { return Result.fail("不支持的文件类型"); } // 按作业ID分目录存储 String dir = uploadDir + homeworkId + "/"; String storeName = studentId + "_" + System.currentTimeMillis() + "." + ext; File dest = new File(dir + storeName); if (!dest.getParentFile().exists()) { dest.getParentFile().mkdirs(); } try { file.transferTo(dest); } catch (IOException e) { return Result.fail("文件保存失败"); } // 存在则更新,不存在则插入 Submission sub = submissionMapper.selectOne( new LambdaQueryWrapper<Submission>() .eq(Submission::getHomeworkId, homeworkId) .eq(Submission::getStudentId, studentId)); if (sub == null) { sub = new Submission(); sub.setHomeworkId(homeworkId); sub.setStudentId(studentId); sub.setFilePath(homeworkId + "/" + storeName); sub.setFileName(file.getOriginalFilename()); sub.setStatus(0); submissionMapper.insert(sub); } else { sub.setFilePath(homeworkId + "/" + storeName); sub.setFileName(file.getOriginalFilename()); sub.setSubmitTime(new Date()); sub.setStatus(0); // 重新提交后回到未批改 submissionMapper.updateById(sub); } return Result.ok("提交成功"); }

逻辑说明:先查作业是否存在、是否截止,再校验后缀,然后落盘。落盘目录按homeworkId分文件夹,文件名用studentId_时间戳保证唯一。数据库层面用selectOne判断是否已有记录,有则更新,无则插入。注意重新提交后要把status重置为 0,否则教师端看不到新版本。参数homeworkIdfile是必传的,file为空时 Spring 会直接返回 400,前端需要做非空校验。

3.2 教师批改接口与分数回填

教师批改时传入提交记录 ID、分数和评语,后端更新submission表并置status=1

@PostMapping("/grade") public Result grade(@RequestBody GradeDTO dto) { Submission sub = submissionMapper.selectById(dto.getSubmissionId()); if (sub == null) { return Result.fail("提交记录不存在"); } if (dto.getScore() == null || dto.getScore() < 0 || dto.getScore() > 100) { return Result.fail("分数需在0到100之间"); } sub.setScore(dto.getScore()); sub.setComment(dto.getComment()); sub.setStatus(1); submissionMapper.updateById(sub); return Result.ok("批改完成"); }

GradeDTO包含submissionIdscorecomment三个字段。分数用BigDecimalDouble接收,数据库字段是DECIMAL(5,1),支持一位小数。批改后学生端查询时根据status显示“已批改”并展示分数和评语。这里不要用物理删除,保留历史记录便于申诉。

3.3 分页查询与多条件筛选

教师端需要按课程、作业、状态筛选提交记录,学生端需要查看自己的提交历史。用 MyBatis-Plus 的分页插件实现。

@GetMapping("/page") public Result page(@RequestParam(defaultValue = "1") Integer page, @RequestParam(defaultValue = "10") Integer size, Long homeworkId, Integer status) { Page<SubmissionVO> p = new Page<>(page, size); LambdaQueryWrapper<Submission> wrapper = new LambdaQueryWrapper<>(); wrapper.eq(homeworkId != null, Submission::getHomeworkId, homeworkId) .eq(status != null, Submission::getStatus, status) .orderByDesc(Submission::getSubmitTime); return Result.ok(submissionMapper.selectPage(p, wrapper)); }

pagesize控制分页,homeworkIdstatus为可选筛选条件。eq的第一个参数是布尔值,条件为真时才拼接 SQL,这是 MyBatis-Plus 的条件构造技巧。排序按提交时间倒序,最新提交的排前面。返回的SubmissionVO需要关联查询学生姓名和作业标题,可以用@Select自定义 SQL 或 XML 映射。

4. 前端联调与部署排错:从 IDEA 到可访问

4.1 Vue 端上传组件与请求封装

前端用 Vue + Element Plus 的el-upload组件,设置:http-request自定义上传,避免默认行为不受控。

// 自定义上传,携带 token 和 homeworkId const handleUpload = async (options) => { const formData = new FormData(); formData.append('file', options.file); formData.append('homeworkId', currentHomeworkId.value); try { const res = await axios.post('/api/submission/submit', formData, { headers: { 'Content-Type': 'multipart/form-data' } }); if (res.data.code === 200) { ElMessage.success('提交成功'); loadList(); } else { ElMessage.error(res.data.msg); } } catch (e) { ElMessage.error('网络异常'); } };

FormData自动设置multipart/form-data边界,不要手动设置Content-Type,否则边界丢失会导致后端解析失败。homeworkId从当前作业详情页传入。上传成功后刷新列表,让状态实时更新。

4.2 IDEA 运行 JavaWeb 项目的常见配置坑

在 IDEA 中运行 Spring Boot 项目时,常见问题有三个。第一,端口被占用,改server.port即可;第二,数据库连接失败,检查application.yml中的url是否加了useSSL=false&serverTimezone=Asia/Shanghai;第三,文件上传目录没有写权限,Linux 下用chmod 755授权。如果启动报Table 'xxx' doesn't exist,说明数据库脚本没执行完整,用idea导出数据库脚本功能反向核对表结构。

提示:MySQL 8.0 的驱动类名是com.mysql.cj.jdbc.Driver,5.7 是com.mysql.jdbc.Driver,写错会报ClassNotFoundException

4.3 批改状态不一致的排查思路

如果教师批改后学生端仍显示“未批改”,按以下顺序排查:先查数据库submission表的status字段是否已更新为 1;再查后端接口是否返回了最新数据;最后查前端是否缓存了旧列表。常见原因是前端用了keep-alive缓存页面,切换路由时没有重新请求。解决办法是在activated钩子里重新加载数据,或者关闭该页面的缓存。

现象可能原因处理方式
上传报 413文件超过 max-file-size调大配置或前端限制
批改后状态不变前端缓存或事务未提交检查@Transactional和刷新逻辑
文件下载 404file_path 拼接错误核对存储根路径与相对路径
登录后接口 401token 未携带检查 axios 拦截器

5. 进阶技巧:用状态机与软删除让系统更经得起答辩

5.1 把 status 字段升级为显式状态机

很多毕设的status只有 0 和 1,答辩时被问“如果学生迟交怎么办”“如果教师打回重做怎么办”就卡住了。进阶做法是定义状态枚举:0 未提交、1 已提交待批改、2 已批改、3 打回重做、4 迟交。状态流转用服务层方法控制,禁止前端直接改status

public enum SubmitStatus { NOT_SUBMITTED(0), SUBMITTED(1), GRADED(2), RETURNED(3), LATE(4); private final int code; SubmitStatus(int code) { this.code = code; } public int getCode() { return code; } }

在提交接口里判断当前时间是否超过deadline,超过则置为LATE,教师端可以单独筛选迟交记录。打回重做时把状态改为 3,学生端显示“需重新提交”,再次提交后回到 1。这样状态流转清晰,答辩时能画出完整的状态图。

5.2 软删除与数据恢复

批改记录和提交记录不建议物理删除。在表里加deleted字段,MyBatis-Plus 用@TableLogic注解自动处理。

@TableLogic private Integer deleted;

配置后,deleteById实际执行UPDATE ... SET deleted=1,查询时自动追加deleted=0。这样误删后还能从数据库恢复,也符合毕设对数据完整性的要求。注意唯一索引uk_hw_stu在软删除下会冲突,需要把deleted加入唯一索引,或者用时间戳标记删除。

5.3 用接口文档工具提升联调效率

前后端分离后,接口字段对不齐是最大时间黑洞。建议引入 Knife4j 或 Swagger,在 Controller 上加注解自动生成文档。

@ApiOperation("学生提交作业") @PostMapping("/submit") public Result submit(@ApiParam("作业ID") @RequestParam Long homeworkId, @ApiParam("作业文件") @RequestParam MultipartFile file) { ... }

启动后访问/doc.html即可看到所有接口和参数说明,前端不用反复问后端字段名。导出接口文档 PDF 附在毕设论文附录里,也是加分项。最后提醒一点:数据库脚本要随源码一起提交,并在 README 里写清楚执行顺序和初始账号,否则答辩现场跑不起来,前面做得再好也会大打折扣。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/23 17:34:24

PyTorch从零实现贝叶斯神经网络:量化模型不确定性

简介&#xff1a;本资源是一份面向机器学习进阶学习者与研究者的贝叶斯神经网络实践教程代码包&#xff0c;聚焦于不确定性建模与概率深度学习核心能力培养&#xff0c;适用于小样本学习、模型校准、医学图像置信预测等高可靠性场景。压缩包共12个文件&#xff0c;含6个Python源…

作者头像 李华
网站建设 2026/9/23 17:34:21

信息链全解析:从理论模型到数据管道落地实践

上周有个朋友问我&#xff1a;一个用户需求从提出到最终变成产品功能&#xff0c;中间的环节到底有多少机会“走样”&#xff1f;我说&#xff0c;你先去把信息链&#xff08;Information Chain&#xff09;这个概念吃透&#xff0c;答案自然就出来了。信息链&#xff08;Infor…

作者头像 李华
网站建设 2026/9/23 17:27:49

模型压缩实战:蒸馏与剪枝源码解析及边缘部署优化

简介&#xff1a;这份资源是面向毕业设计与模型压缩入门者的Python代码仓库&#xff0c;聚焦基于知识蒸馏与剪枝的识别算法实现&#xff0c;适合具备一定深度学习基础、需要完成相关课题或复现压缩实验的学生与开发者。压缩包共185个文件&#xff0c;约4.03MB&#xff0c;以79个…

作者头像 李华
网站建设 2026/9/23 17:25:43

微信小程序制作平台有哪些?2026年经营型商家的筛选清单

直接答案&#xff1a;微信小程序制作平台主要有四类——电商交易型SaaS&#xff08;凡科商城、有赞、微盟、微店&#xff09;、官网展示型建站工具、行业垂直型平台&#xff08;餐饮、酒店、零售专用&#xff09;、定制开发服务商。 经营型商家要做接单收钱的小程序&#xff0c…

作者头像 李华