尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

基于Spring Boot的学生作业管理系统开发实战与避坑指南

基于Spring Boot的学生作业管理系统开发实战与避坑指南 你是要交课程设计还是要做毕设又或者单纯想把手上的学生作业管理流程从Excel和微信聊天记录里搬出来不管哪一种我建议你认真看一下这篇。基于Spring Boot的学生作业管理系统我不光说它是什么还会把从数据库设计到文件上传、角色权限、常见坑位这些实操层面的东西全部拆开讲。这篇文章适合两类人一是正在做Java Web课程设计或毕业设计的学生二是想快速了解Spring Boot单体应用完整搭建思路的初级后端开发者。看完你至少能明白一个作业管理系统从零到能跑到底要经历哪些环节。先交代背景。这类系统的核心诉求并不复杂传统作业收交靠学委催、课代表抱纸质作业给老师、老师批改完再发回学生整个过程信息不透明、文件易丢失、还容易积压。做成管理系统后核心闭环就变成了教师建课程 → 布置作业 → 学生提交 → 教师批改打分 → 结果回写 → 学生查看。Spring Boot在这个场景里是最合适的选择生态成熟、上手快、内嵌Tomcat直接打jar包跑一台普通电脑就能搞定。1. 项目整体设计与技术选型思路1.1 这个项目到底解决什么问题很多人写这类系统上来就堆功能恨不得把淘宝商城都搬进去结果糊了一个巨大的烂摊子。我还是建议从问题出发。作业管理系统的用户只有三种管理员、教师、学生。他们的痛点各不一样所以功能面其实是收敛的。学生关心的这周有哪些作业、截止时间是什么时候、怎么交、交了没有、老师给多少分。教师关心的哪些学生还没交、作业按什么标准打分、作业文件怎么收齐、成绩怎么导出、课后怎么把批改结果告诉学生。管理员关心的教师账户和学生账户怎么维护、课程怎么开、全系统的数据是否正常。因此功能模块不必贪多只要把“布置—提交—批改—统计”这条主线做成闭环就已经是一个合格的学生作业管理系统。加分项是通知提醒、成绩分析、Excel导出这些后面我会逐一说说怎么加合理。1.2 技术选型解析为什么是Spring Boot先说一个核心判断做这种规模的项目Spring Boot是当前最合理的方案没有之一。它的价值在于内嵌Tomcat不需要单独装容器大量自动装配不用写一堆XML配置文件生态成熟MyBatis-Plus、JPA、Thymeleaf、Redis、WebSocket所有你需要的轮子都有现成的加上Spring框架本身的学习资料密集出了问题搜得到答案。但你得注意Spring Boot版本不能乱选。热词里那句“Spring Boot版本太高”其实戳中了很多人的痛点。2024年以后Spring Boot 3.x成为主线但它强制要求JDK 17及以上同时很多第三方依赖比如一些老的MyBatis-Plus版本、某些网盘存储SDK并没有及时适配导致启动报错或者Bean加载异常。如果你是为了做课设或毕设又不想在环境问题上消耗大量精力稳妥的做法是Spring Boot 2.7.x JDK 8/11 MySQL 5.7/8.0 MyBatis-Plus 3.5.x。这套组合我已经反复确认过依赖兼容性好网上的案例也多。1.3 前端方案从简化到体验的梯度选择系统标题里有一个“基于web”的限定很多人卡在这儿以为不上Vue就不算web。这理解偏了。Web只是说通过浏览器访问和前后端分离没有必然关系。我给出两条路线建议。路线一服务端渲染Spring Boot Thymeleaf。这种方案适合需要在最短时间内看到完整效果、或者你对前端不熟悉的情况。页面直接由后端Controller返回模板引擎渲染数据不用考虑跨域问题代码量也少。缺点也很明显交互体验偏传统重一点的操作比如异步刷新成绩图表写起来更别扭。路线二前后端分离Spring Boot Vue。这种方案交互体验明显更好而且现在毕设答辩时老师大都倾向看到前后端分离项目。代价是要多维护一套前端工程开发链路变长还可能出现跨域配置、接口鉴权等问题。如果只是交课程设计优先选Thymeleaf。如果是做毕设且时间充裕Vue方案能给你加分。如果你已经会Vue了不要犹豫上Vue。这个系统前端的复杂度很低无非就是列表页、表单页、上传组件、成绩展示没有特别复杂的页面交互Vue写起来并不费劲。2. 核心功能拆解与数据模型设计2.1 角色权限模型怎么设计系统涉及三个角色权限天然分为三层管理员管基础数据教师管自己的课程和作业学生管自己的选课和提交。我做这类项目的时候第一件事不是写登录而是画一张权限矩阵。管理员能做的维护教师/学生账号、创建课程、查看系统所有数据但通常不动作业内容。教师能做的创建自己的课程、添加学生、布置作业、查看所负责课程的提交情况、批改打分、更新成绩。学生能做的选课、查看已加入课程的作业列表、提交作业、重新提交在未截止且有提交记录的情况下、查看成绩和评语。这种权限模型用Spring Boot实现最简单的方式是登录成功后在Session里存一个用户对象里面包含角色字段然后通过拦截器判断访问路径角色。比如/admin/**只允许管理员访问/teacher/**只允许教师访问/student/**只允许学生访问。不需要一上来就上Spring Security除非你的答辩老师明确要求“系统必须使用安全框架”。对多数场景来说拦截器Session已经能逻辑自洽且方便答辩时讲清楚。2.2 数据库表结构设计详解数据模型是整个系统的骨架表设计如果一开始就没想清楚后面每加一个功能都像在一堆乱麻里找线头。我给出一个最小但完整的表结构思路你可以按自己的需求增删字段。学生表(student)id、学号(student_no)、姓名、密码、班级、邮箱、电话、创建时间。教师表(teacher)id、工号(teacher_no)、姓名、密码、职称、邮箱、创建时间。课程表(course)id、课程名(name)、课程编号(code)、教师ID、开课学期(semester)、课程简介、创建时间。选课表(enrollment)ID、课程ID、学生ID、选课时间。注意这里要加一个唯一约束避免同一个学生重复选同一门课。作业表(assignment)id、课程ID、标题、内容要求、满分分值、截止时间(deadline)、创建时间。这个表是作业模块的源头批改和提交都围绕它展开。提交记录表(submission)id、作业ID、学生ID、提交的文件路径、文件的原始文件名、下载用文件名、提交时间、批改状态(status)、得分、教师评语、批改时间。另外可以再加一个通知表(notification)用于系统内部消息提醒比如教师布置新作业后给学生推送一条消息。如果没有通知需求这个表可以不加。2.3 文件存储本地存储方案就够了作业提交的核心难点在文件存储。有些同学一上来就惦记着OSS、云存储但对于校内作业这种量级本地磁盘存储完全够用。在项目根目录下建一个upload文件夹按课程ID和作业ID分目录存放例如/upload/courseId/assignmentId/学生学号_时间戳.ext。关键点有两个一是文件名必须重命名不能直接使用用户上传的原名容易冲突而且文件名里带有中文或特殊字符会引发一连串Bug二是在配置文件里把绝对路径做成可在application.yml中配置的项不要写死。上传文件的时候用UUID或者“学号时间戳”这种组合方式生成新文件名原始文件名单独存在数据库里。这样用户下载时能看到正确的文件名系统磁盘上存储的文件名又不会冲突两全其美。2.4 application.yml核心配置参考在你的Spring Boot项目中最核心的配置文件建议这样写server: port: 8080 spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/homework_system?useUnicodetruecharacterEncodingutf8useSSLfalseserverTimezoneAsia/Shanghai username: root password: 你的密码 servlet: multipart: max-file-size: 50MB max-request-size: 50MB thymeleaf: cache: false mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl map-underscore-to-camel-case: true global-config: db-config: logic-delete-field: deleted logic-delete-value: 1 logic-not-delete-value: 0 upload: dir: D:/homework-system-upload有几个细节要重点解释。第一数据源URL里必须加serverTimezoneAsia/Shanghai否则高版本JDBC驱动连MySQL时会报时区错误。第二max-file-size默认只有1MB不做学生作业系统的时候没什么感觉一旦需要交一个几十MB的视频作业就会失败所以务必调大。第三thymeleaf的cache在生产环境打开开发调试时关掉。MyBatis-Plus的map-underscore-to-camel-casetrue这个配置非常关键它能把数据库里的下划线字段自动映射到实体的驼峰字段省掉一堆TableField注解。另外如果涉及到逻辑删除场景建议在基础实体中加上deleted字段避免真实物理删除后续无法追溯这种细节在课程设计答辩时可以拿出来讲是加分项。3. 实操过程与核心环节实现3.1 用户登录与角色权限控制实现登录模块是整个系统的门面安全性不高会让你后面的功能全都有漏洞。我这里用的是最简单、最容易讲清楚的方式拦截器 Session。第一步登录接口从数据库里根据用户名找出用户比对密码密码建议用MD5加盐存储虽然用Spring Security里的BCrypt更健壮但很多课程设计只要体现“密码不是明文存储”即可MD5加盐已经比明文好得多。登录成功之后把用户ID、用户名、角色都存进Session。第二步写一个LoginInterceptor拦截器实现HandlerInterceptor接口的preHandle方法从Session中拿用户信息如果拿不到就重定向到登录页。再针对不同角色在WebMvcConfigurer的addInterceptors方法里配置路径匹配规则。核心代码看起来是这样Component public class LoginInterceptor implements HandlerInterceptor { Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { UserDTO loginUser (UserDTO) request.getSession().getAttribute(loginUser); if (loginUser null) { response.sendRedirect(/login); return false; } return true; } }Configuration public class WebConfig implements WebMvcConfigurer { Resource private LoginInterceptor loginInterceptor; Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(loginInterceptor) .addPathPatterns(/**) .excludePathPatterns(/login, /register, /doLogin, /css/**, /js/**, /images/**); } }这里有一个细节登录接口和静态资源路径必须放行不然前端样式全部加载不出来你排查半天可能都没想到是拦截器把所有静态资源一起拦了。如果需要彻底一点可以在LoginInterceptor里再做二次校验public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { UserDTO loginUser (UserDTO) request.getSession().getAttribute(loginUser); if (loginUser null) { response.sendRedirect(/login); return false; } // 根据请求路径前缀判断角色 String uri request.getRequestURI(); if (uri.startsWith(/admin) !ADMIN.equals(loginUser.getRole())) { response.sendError(403); return false; } if (uri.startsWith(/teacher) !TEACHER.equals(loginUser.getRole())) { response.sendError(403); return false; } if (uri.startsWith(/student) !STUDENT.equals(loginUser.getRole())) { response.sendError(403); return false; } return true; }3.2 文件上传与下载实现详解文件上传是作业管理系统的灵魂功能提交作业如果没有这个能力整个系统没有存在意义。前端表单要设置enctypemultipart/form-data后端的Controller方法直接接收MultipartFile参数。后端处理方式如下PostMapping(/student/submit) public String submitHomework(RequestParam(assignmentId) Long assignmentId, RequestParam(file) MultipartFile file, HttpSession session) { UserDTO user (UserDTO) session.getAttribute(loginUser); if (file.isEmpty()) { redirectAttributes.addFlashAttribute(error, 请选择要上传的文件); return redirect:/student/assignment/ assignmentId; } // 设置文件大小校验 if (file.getSize() 50 * 1024 * 1024) { redirectAttributes.addFlashAttribute(error, 文件大小不能超过50MB); return redirect:/student/assignment/ assignmentId; } // 生成存储文件名时间戳 随机串保留扩展名 String originalFilename file.getOriginalFilename(); String ext originalFilename.substring(originalFilename.lastIndexOf(.)); String storedFilename System.currentTimeMillis() _ UUID.randomUUID().toString().replace(-, ) ext; // 构造存储目录upload/{assignmentId} String realPath uploadDir File.separator assignmentId; File dir new File(realPath); if (!dir.exists()) { dir.mkdirs(); } File dest new File(dir, storedFilename); file.transferTo(dest); // 保存提交记录原文件名和存储文件名都存库 submissionService.saveSubmission(assignmentId, user.getId(), originalFilename, storedFilename, realPath); return redirect:/student/assignment/ assignmentId; }这里面有几个必须注意的点。文件重命名别用用户原始文件名。我见过一个真实案例两个学生交的文件都叫“作业.docx”后者直接把前者的文件覆盖了作业直接没法查。虽然提交记录还在但物理文件已经丢了。文件的扩展名要保留。判断文件类型不能只看扩展名但作为课设系统至少保证用户下载时能正常打开。存储路径在数据库里有两种存法。一是存文件的绝对路径简单直观二是存相对路径推荐后者因为系统部署到服务器后目录结构可能会变存相对路径只要配置一个根目录下载时再拼接灵活性高很多。下载接口的实现要点是设置Content-Disposition响应头同时把文件名做URL编码不然中文文件名下载时会变成一串乱码GetMapping(/student/download) public ResponseEntityResource download(RequestParam(submissionId) Long submissionId) { Submission submission submissionService.getById(submissionId); File file new File(uploadDir submission.getStoredPath()); if (!file.exists()) { return ResponseEntity.notFound().build(); } String originalFilename submission.getOriginalFilename(); // 对文件名做URL编码解决中文乱码 String encodedFilename URLEncoder.encode(originalFilename, StandardCharsets.UTF_8).replace(, %20); return ResponseEntity.ok() .header(HttpHeaders.CONTENT_DISPOSITION, attachment; filename*UTF-8 encodedFilename) .contentType(MediaType.APPLICATION_OCTET_STREAM) .body(new FileSystemResource(file)); }3.3 教师批改与成绩回写流程教师端的核心操作是查看某个作业下所有学生的提交列表、针对某个提交记录打分和写评语、发布成绩让学主即时看到。这里涉及两个关键问题。第一如何判断一个学生“交了”还是“没交”最简单的实现方式遍历选课表里该课程的所有学生逐个检查该作业在提交记录表中是否存在对应记录。如果提交记录不存在判断截止时间截止前显示“未提交”截止后显示“逾期未交”。第二成绩回写是直接更新提交记录表里的score和comment字段同时修改批改状态为已批改。学生端查询成绩时如果得分字段不为null就展示分数。这里有一种常见的错误做法——教师打分写在另外一张成绩表里导致批改页面和学生端成绩页面对不上。不要拆表提交记录本身就是“学生-作业”的一对一关系成绩字段直接挂在提交记录上最方便。批改接口的Service实现大致如下Transactional(rollbackFor Exception.class) public void gradeSubmission(Long submissionId, Integer score, String comment) { Submission submission submissionMapper.selectById(submissionId); if (submission null) { throw new ServiceException(提交记录不存在); } submission.setScore(score); submission.setComment(comment); submission.setStatus(1); // 1表示已批改 submission.setGradingTime(new Date()); submissionMapper.updateById(submission); // 可选根据分数更新某条作业的平均分缓存用于统计页面 refreshAssignmentStats(submission.getAssignmentId()); }注意我加了一个Transactional事务注解这是很多人容易忽略的细节。批改动作更新了字段、可能还更新了统计信息任何一步失败都应该回滚否则会出现分数更新了但状态没变的数据不一致情况。3.4 作业截止时间与逾期逻辑处理截止时间是一个作业系统中非常核心的业务规则。学生提交作业时后端必须在写入之前进行一次时间判断不能只看前端页面是否禁用了提交按钮因为请求可以被绕过。实现方式很简单在submissionService.saveSubmission里增加一段Assignment assignment assignmentMapper.selectById(assignmentId); if (assignment null) { throw new ServiceException(作业不存在); } if (new Date().after(assignment.getDeadline())) { throw new ServiceException(已超过截止时间无法提交); }对于“作业截止后还想查看作业内容”的需求学生端的列表页要能展示作业标题、截止时间但提交按钮在截止后置灰并显示“已截止”。后端接口同样需要做同样的判断防止有人绕过前端直接POST。3.5 通知与提醒功能扩展WebSocket还是轮询如果想让系统更完整可以加作业发布通知让学生在首页看到“老师刚布置了新作业三天后截止”。实现方式有两种。第一种是轮询前端每隔30秒请求一次新通知接口实现简单但实时性差对服务端有压力。第二种是WebSocket服务端主动推送消息给连接的学生体验更好。我建议优先考虑轮询因为通知场景对实时性要求不高延迟30秒完全没感觉。如果你确实想展示WebSocket的能力可以做一个简易版本学生登录后通过WebSocket连接服务端教师发布作业时触发一个消息推送。但WebSocket会引入跨域、Session管理和连接保活等问题答辩风险也会更高所以在基础功能全部稳定之后再做加分。3.6 前后端分离时的跨域与接口设计补充如果你选择了Vue分离方案有两个地方必须处理。第一是跨域问题。开发环境前端运行在localhost:8080后端在localhost:9090时浏览器会拦截跨域请求。最简单的办法是后端加一个全局CORS配置Configuration public class CorsConfig implements WebMvcConfigurer { Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping(/**) .allowedOriginPatterns(*) .allowedMethods(GET, POST, PUT, DELETE, OPTIONS) .allowedHeaders(*) .allowCredentials(true) .maxAge(3600); } }这在课程设计阶段已经够用。生产环境中的CORS配置不能这样放开但课设项目没必要在这个环节过度设计。第二个是Session跨域问题。如果前端和后端不在同一个域名下Session机制会失效。解决办法是改token方案登录后返回一个token前端每次请求都带上这个token后端拦截器每次从Header里取token并解析用户。改造并不复杂核心代码量可能增加100行左右但如果答辩老师让你讲权限控制时token方案讲起来比Session更“现代”。4. 前端页面与关键交互实现要点4.1 服务端渲染的页面规划如果用Thymeleaf页面建议页面最少覆盖这些视图登录页、管理员端三个页面学生管理、教师管理、课程管理、教师端五个页面我的课程、作业列表、布置新作业、学生提交列表、批改页、学生端四个页面我的课程、作业列表、提交作业页、成绩详情页、一个通用错误页。页面风格可以朴素但该有的交互不能漏表单校验、上传进度提示、列表分页。分页推荐用MyBatis-Plus自带的Page对象配合IPage返回前端直接展示页码按钮就行不用自己去写Limit和Offset。4.2 关键页面交互上传组件的细节上传页面是学生最常用的页面也是体验容易拉胯的地方。要注意几个点选择文件后显示文件名和大小点击提交后前端先做一次文件类型校验比如只允许doc、docx、pdf、zip、rar图片等常见格式提交期间按钮置灰并提示“正在上传请勿关闭页面”成功或失败都要有明显提示。一个比较省事又实用的做法是引入layui的upload组件一个文件选择框加上传进度条约20行配置就能跑起来。如果用Vue可以考虑Element Plus的el-upload组件。4.3 前端细节避坑指南写前端的时候有几个坑是新手高频踩的。第一个表单里的文件控件name属性必须和后端RequestParam里的参数名一致否则文件一直为null。第二个如果使用Thymeleaf回显提交结果建议用RedirectAttributes把操作结果放在flash作用域里这样刷新页面时不会出现“重复提交表单”的浏览器警告。第三个页面上的时间显示建议统一格式化为yyyy-MM-dd HH:mm直接输出后端Date对象会变成一大串带T的ISO字符串观感很差。时间格式化可以在后端用JsonFormat或Thymeleaf的#dates.format也可以在Vue中用dayjs做统一处理总之不能原样输出。5. 项目部署与常见问题排查技巧实录5.1 本地运行与打包部署本地开发阶段IDEA直接运行Spring Boot的main方法即可。这里要强调一下IDEA创建Spring Boot项目时最容易被卡住的两个地方。第一依赖下载慢。在maven的settings.xml中配置阿里云镜像仓库能明显加快下载速度。第二热更新问题。引入spring-boot-devtools依赖后改完代码按CtrlF9就可以实现热重启否则每次修改都要重启整个应用调试效率很低。课程设计阶段能跑在本地就足够。如果需要部署到服务器打jar包mvn clean package -DskipTests然后上传到服务器nohup java -jar homework-system-0.0.1-SNAPSHOT.jar --spring.config.location/opt/homework/application.yml app.log 21 注意参数--spring.config.location指向服务器上外置的application.yml不要把所有配置打进jar包这样换环境不需要重新打包。5.2 常见问题与解决方案速查表我把实际开发中踩过的坑整理成一张速查表基本上你遇到这些问题的时候可以参考这张表快速定位。问题现象可能原因解决方案上传文件超过1MB就报错Spring Boot默认上传大小限制为1MBapplication.yml中配置spring.servlet.multipart.max-file-size本地图片能显示部署后图片404上传目录在项目外未配置静态资源映射通过WebMvcConfigurer配置ResourceHandler映射到本地上传目录中文文件名下载乱码响应头文件名未做URL编码用URLEncoder.encode并设置filename*UTF-8数据库中文乱码连接URL未指定characterEncodingutf8在jdbc url中加上characterEncodingutf8Spring Boot启动报ClassNotFoundExceptionJDK版本和Spring Boot版本不匹配Spring Boot 2.7.x用JDK8/11Spring Boot 3.x用JDK17前端提交表单后文件字段为null表单忘记加enctypemultipart/form-data在form标签加上该属性页面样式加载不出来拦截器拦截了静态资源excludePathPatterns中加入/css/**、/js/**等路径更新成绩后学生端看不到查询时漏了状态过滤或在错误表查成绩成绩直接存submission表学生端按作业ID查提交记录数据库连接失败MySQL未启动或时区未设置启动MySQL服务并在URL加serverTimezoneAsia/Shanghai作业文件丢失或覆盖文件名未加唯一标识存储文件名必须使用时间戳UUID保留原文件名仅供展示5.3 部署到服务器后的目录与安全细节部署到Linux服务器后上传目录的权限需要特别处理。简单来说Java进程运行的用户如root或专门建的应用账户必须对上传目录有读写权限否则transferTo会抛IOException。可以做一次快速验证mkdir -p /opt/homework/upload chmod -R 755 /opt/homework/upload还要把上传目录放到应用目录之外不要在jar包同目录下的临时文件夹一旦重新部署就会丢数据。另外Linux服务器上注意防火墙端口如果是云服务器要记得在安全组里放行8080端口很多同学本地跑得好好的部署后却访问不了八成就是这个原因。文件防重名的问题再强调一次云服务器上大家可能涉及多用户并发提交不能用“课程ID学生ID”当文件名两个学生同一个作业时会出现覆盖。使用“UUID时间戳”命名的方案最稳。6. 一些额外的优化与扩展方向参考6.1 成绩统计与可视化基础版成绩查询只是表格展示如果想让项目更有层次感可以在教师端加一个按作业查看成绩分布的功能直接用ECharts画柱状图。这个加分项的工作量不大教师批改完成后的成绩都集中在submission表中后端写一个GROUP BY统计接口即可前端用ECharts几分钟就能出图。所谓的“Web可视化”在课程设计里不需要多复杂一张成绩分布柱状图、一张班级平均分曲线图就很到位了。这和热词里提到的“web vue开发配电工艺图”不同它们那个是专业的工控可视化这里只需要懂ECharts基本用法就足够。6.2 Excel导入导出教师经常需要把成绩单交给院系做一个简单的Excel导出功能价值很高。用EasyExcel或Apache POI都可以导出字段包括学号、姓名、作业名称、得分、评语、提交时间。如果还能加Excel批量导入学生名单管理员不用一个个手工添加学生账号体验会好很多。这里要注意批量导入时的账号生成策略初始密码统一设置成123456或者学号本身登录后让学生自行修改。这个功能在答辩现场演示时一眼就能看出和普通“CRUD系统”的差距。6.3 数据库备份策略虽然只是个课程作业或内部工具但数据无价。我把备份策略加在结尾是因为太多人忽略这个东西。本地开发可以手动导出SQL但部署到服务器后建议写一个定时脚本每天凌晨把MySQL的数据dump到备份目录。#!/bin/bash mysqldump -uroot -p你的密码 homework_system /backup/homework_$(date %Y%m%d%H%M).sql find /backup -mtime 7 -name *.sql -delete用crontab挂上每天01:00执行0 1 * * * /bin/bash /root/backup_homework.sh两周前我自己一个测试环境的数据库因为误操作丢了几天作业数据虽然能让学生重新提交但体验极差。从那以后所有项目我都会先配备份脚本再上线。在整个开发过程中我自己的体会是学生作业管理系统这样的题目代码量并没有多大难度真正拉开差距的地方在细节。你把文件命名、事务控制、权限校验、部署配置这些事情做扎实了答辩时能讲的东西就会非常多。如果时间允许建议把所有操作日志记录到一张log表里虽然看起来不起眼但却是很多正式系统必须具备的能力也方便你排查线上问题。另外分享一个小经验做这种系统不要追求一次写完所有代码再启动运行应该按照“搭工程 → 登录 → 建课 → 布置作业 → 提交 → 批改”这条链路一个环节一个环节跑通每跑通一个环节就提交一次代码这样出了问题范围非常小排查起来也快。等整条链路通了再回头加Excel导入导出、统计图表、WebSocket通知这些花活你会发现项目的完成度和稳定度都远超预期。
返回列表