ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

JavaWeb课程设计源码实战:从作业管理网站到答辩冲刺

JavaWeb课程设计源码实战:从作业管理网站到答辩冲刺 简介一个基于Java Web的作业管理网站课程设计源码面向计算机、通信、人工智能、自动化等专业的学生、老师或从业者可用作期末课程设计、课程大作业或毕业设计参考。项目将作业发布、提交、汇总、查看等核心模块整合到一起包含完整的登录与作业流转页面后台采用JSP、Servlet、Java Bean与JDBC数据库访问方式前端搭配Bootstrap样式整体结构清晰、代码经过调试运行。压缩包共有54个文件主要类型包括Java源文件、JSP页面、CSS样式表、JavaScript脚本、JAR依赖库和数据库配置说明文档压缩后约7.73MB便于按目录逐模块阅读或二次改造。项目答辩评分达到95分适合有一定编程基础的学习者借鉴作业管理系统的设计思路也可作为毕业设计的起步框架。目前已有237人学习是快速理解Java Web项目分层与前后端交互的实用资源。1. 从 zip 到能跑的 JavaWeb 作业管理网站先搞清楚这套源码在讲什么你从网盘或课程群资源里下到的“基于JavaWeb的作业管理网站源码(课程设计).zip”解压后通常是一堆 src 文件夹、十几个 jsp 页面、一个 sql 脚本运气好的话还带 pom.xml。这套源码要做的事很典型学生登录看老师布置的作业上传文件交作业再查成绩教师登录布置作业、看提交记录、打分管理员维护用户基础数据。业务边界很窄核心就是 Servlet、JSP、JDBC 和 MySQL 四样没有 Spring 框架。它适合两类人第一类是 JavaWeb 课设临近截止、想弄懂一个现成工程并顺利答辩的学生第二类是刚学完 Servlet 和 JSP、想找一个完整案例看看页面、业务、数据库怎么组织的新手。对第一类人这份源码的“可抄作业”点在于分层controller/service/dao 各司其职Filter 做登录拦截文件上传用 Servlet 的 getPart。对第二类人它是很好的课程设计案例源码——结构够小知识点够全半小时能读完。理解了它是什么之后后面几章我按四步走先拆结构和数据库设计再配好 IDEA、Tomcat、MySQL 把项目真正跑起来然后挑登录、过滤、上传三段核心代码讲清楚最后给出踩坑清单和答辩前升级 Spring Boot 的迁移思路。2. 源码怎么拆作业管理网站的分层结构与数据库表设计拿到一个 zip 先别急着点运行很多同学直接在 IDEA 里 Open 然后按绿三角结果报错跑不起来根源在于没先建立“这个工程由哪些零件组成”的认知。第二章花十五分钟把功能、目录、表结构三张地图画出来后面所有配置和改代码都会顺手很多。2.1 先看功能边界三种角色各能做什么这种课设最常见的功能矩阵是固定的不同老师让学生做的差异只在“有没有公告栏”“能不能导出 Excel 成绩单”“要不要管理员审核作业”。我们先按最标准的版本拆角色核心功能后端落点学生登录注册、查看已布置作业、提交作业文件、查看分数与评语LoginServlet、HomeworkServlet、UploadServlet教师登录、布置作业、查看提交列表、打分写评语TeacherHomeworkServlet、GradeServlet管理员用户管理、重置密码、删除用户UserManageServlet拿到源码后的第一个动作我一般建议先花十五分钟把“谁在哪个页面、点了什么按钮、请求会跳到哪个 Servlet”画在纸上而不是直接点开 Java 文件。因为 JavaWeb 工程里代码之间的跳转关系散落在三处jsp 里的 form action、web.xml 里的 servlet-mapping、以及 Servlet 里的 sendRedirect 和 forward 目标。这三处对不上就是你后面遇到 404、页面疯狂跳回登录页的主要来源。另外要留个心眼部分网上下载的源码里“管理员”模块是空壳按钮在页面上但点过去只有一页报错或者根本没写逻辑。遇到这种情况不用慌课设答辩时只要能把学生和教师的主流程串起来再补一句“管理员模块因为时间关系只完成了用户维护”老师通常能接受。2.2 目录结构与分层controller/service/dao 为什么要分开一个规范点的 JavaWeb 课程设计源码目录一般长这样src/main/java/ ├── controller/ # Servlet 层接收请求、调用业务、跳转页面 │ ├── LoginServlet.java │ ├── HomeworkServlet.java │ └── UploadServlet.java ├── service/ # 业务层登录校验、作业提交校验 │ ├── UserService.java │ └── HomeworkService.java ├── dao/ # 数据访问层纯 JDBC只负责 SQL │ ├── UserDao.java │ └── HomeworkDao.java ├── entity/ # 实体类User、Homework、Submission ├── filter/ # 过滤器AuthFilter 登录拦截 └── util/ # 工具类DBUtil 获取连接 webapp/ # 之前叫 WebContent ├── jsp/ # 页面文件 ├── WEB-INF/ │ ├── web.xml │ └── lib/ sql/ └── schema.sql # 建库建表脚本这个分层是这套源码里最重要的东西。Servlet 只做三件事从 request 拿参数、调用 service、把结果转发给 jspservice 里写业务判断比如“当前作业是否已截止”“是不是教师角色才能布置作业”dao 里只写 SQL 和 JDBC 操作。哪怕源码里的 service 层写得很薄只要它存在说明作者大概理解了分层的意思答辩时老师一定会问“为什么不让 Servlet 直接查数据库”——因为 Servlet 职责是控制转发SQL 混进来以后页面跳转逻辑和数据库逻辑耦合在一起改一个需求要动两层代码。如果你拿到的版本没有 Maven 结构而是一个扁平的 Web 工程也不用担心。区别只在于第三方 jar 放在 webapp/WEB-INF/lib 下面而不是由 pom.xml 管理后面导入 IDEA 时处理方式不同我会在第三章说。jsp 页面不一定要在 jsp 目录里也可能直接放 webapp 根目录这种版本更老但不影响运行。2.3 数据库三张核心表用户、作业、提交记录课设作业管理系统的数据量很小三张表足够。见过很多同学一上来就建七八张表把权限模型搞得很复杂没必要。标准版本如下表名关键字段作用t_userid, username, password, role, real_name学生、教师、管理员统一存这张表用 role 区分t_homeworkid, title, content, deadline, create_time老师布置的作业截止时间用于提交校验t_submissionid, homework_id, student_id, filename, file_path, score, comment, submit_time每次提交记录是学生和作业的多对多关联这里有一个答辩必问点为什么提交记录要单独建一张表而不是在 t_user 里加一个 homework_id 字段因为一个学生要提交多份作业一份作业又要被多个学生提交这是典型的多对多关系必须用中间表承接。t_submission 里存 homework_id 和 student_id 两个外键再加 score 和 comment成绩直接挂在提交记录上不需要另建成绩表。我在 2.1 里说“管理员重置密码”功能在部分源码里是空壳原因在表结构上也能看出来——如果 t_user 里没有 create_time、status 这类字段说明作者根本没给管理员模块留数据支撑你复现的时候别花太多时间纠结这个模块。2.4 顺着 web.xml 找跳转路径先画请求流程图旧版 JavaWeb 工程里每个 Servlet 的访问路径定义在 web.xmlservlet-mapping servlet-nameloginServlet/servlet-name url-pattern/login/url-pattern /servlet-mapping新版如果用了注解就是 LoginServlet 类上的WebServlet(/login)。拿到源码第一步不是读每个 Java 文件而是把所有 url-pattern 列成一张清单再看 jsp 页面的 form action 指向哪里两边一对账流程图就出来了/login - LoginServlet用户名密码校验 /register - RegisterServlet学生自助注册 /homework/list - HomeworkServlet查询作业列表 /homework/submit - UploadServlet文件上传 /grade - GradeServlet教师打分我一般用笔在纸上画箭头箭头两端分别是页面和 Servlet。画完你会发现这套系统的所有逻辑全在这五六个虚线框里后面读代码只需要挑最核心的三个 Servlet 看就够。这也是判断下载的源码是否完整的一个技巧如果 web.xml 里声明了一堆 Servlet但对应的 jsp 里根本没有 form action 指向它说明这个文件可能是从别的项目拼过来的或者模块没做完复现时可以直接跳过。3. 让源码在 IDEA 里跑起来JavaWeb 连接 MySQL 数据库的配置路径与部署参数这一章标题里的“连接 MySQL”是大多数人失败的地方。代码本身很难跑挂挂都是挂在环境Tomcat 版本不对、MySQL 驱动类名写错、数据库没建、连接串里的时区没配。按下面的顺序一步步来半小时内能见到登录页。3.1 环境选型JDK 8、Tomcat 8.5、MySQL 5.7 是最稳组合先看一组我踩过坑之后固定的版本组合组件推荐版本原因JDK1.8 或 11JDK 17 上老式 JDBC 驱动反射可能报错Tomcat8.5 或 9.0千万别用 Tomcat 10包名改成 jakarta 后旧源码全编译不过MySQL5.7 或 8.05.7 最稳8.0 要改驱动类和时区IDEA2021 以后任意版本社区版也够用这套组合几乎是 JavaWeb 课设源码的“安全区”。Tomcat 10 的问题尤其隐蔽源码里所有import javax.servlet.*在新版里变成import jakarta.servlet.*肉眼看不出来启动直接抛 ClassNotFoundException。很多人以为是自己代码错了其实是容器版本选错了。MySQL 8.0 用户后面会在 db.properties 里额外处理两处驱动类名从com.mysql.jdbc.Driver改成com.mysql.cj.jdbc.Driver连接串加serverTimezoneAsia/Shanghai否则会报时区错误。如果不想折腾直接用 MySQL 5.7 最省事。3.2 在 IDEA 中导入工程并挂载 Tomcat先解压 zip然后用 IDEA 的 File - Open 选中项目根目录。这里会出现两种分支如果是 Maven 工程能看到根目录下有 pom.xml耐心等右下角依赖下载完即可。如果是传统 Web 工程IDEA 会把它当成普通 Java 项目打开此时 Java 文件全部爆红是正常的因为工程还没挂上 Tomcat 运行库。处理步骤如下打开 Project Structure选中 Modules给项目添加 Web 特性选中 Libraries点 号添加 Tomcat 安装目录下 lib 文件夹里的 servlet-api.jar选中 Artifacts点 号添加 Web Application: Exploded打开 Run - Edit Configurations点 号选 Tomcat Server - Local在 Deployment 页签把刚才的 Artifacts 加进去Application context 填/在 Server 页签确认 HTTP port 是 8080这里有个常被忽略的参数Application context。它决定访问路径的前缀。填/后启动完直接访问http://localhost:8080/login.jsp如果你填了/homework访问路径就变成http://localhost:8080/homework/login.jsp。源码里跳转写的是response.sendRedirect(login.jsp)这种相对路径时context 对跳转影响不大但如果用了request.getContextPath()它就会自动带上这个前缀。建议统一填/让前后路径保持一致排查起来省心。war exploded 和 war 的区别也要说一下war exploded 是把解压后的目录作为部署目标改 jsp 和静态文件不用重新打包刷新浏览器就能看到效果适合开发调试war 是一个压缩包适合最后部署到真实 Tomcat。IDEA 里默认选择 Exploded 没问题。3.3 建库建表与 db.properties三个必改参数数据库初始化脚本一般就在源码的 sql 目录里别自己手写。打开看一遍如果里面有DROP TABLE IF EXISTS之类的清理语句直接执行即可。没有现成脚本时自己建库和核心表示例CREATE DATABASE homework_db DEFAULT CHARSET utf8mb4; USE homework_db; CREATE TABLE t_user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(100) NOT NULL, role VARCHAR(20) DEFAULT student, real_name VARCHAR(50) );注意编码必须选 utf8mb4否则插入中文时报错或者显示乱码。这个库名后面要写进连接串里如果脚本里写的是CREATE DATABASE homework而源码连接的是homework_db启动后必定报Unknown database这是最常见的低级翻车点之一。连库信息通常在 db.properties内容一般是这个样子jdbc.drivercom.mysql.jdbc.Driver jdbc.urljdbc:mysql://localhost:3306/homework_db?useSSLfalsecharacterEncodingutf8 jdbc.usernameroot jdbc.password123456三个必改参数url 里的数据库名、username、password。其它别动尤其是 characterEncodingutf8 和 useSSLfalse 一定要保留前者避免中文乱码后者避免 MySQL 8 的 SSL 握手警告。MySQL 8 用户把 driver 换成com.mysql.cj.jdbc.Driverurl 最后加上serverTimezoneAsia/Shanghai。改完配置记得重新 build 一下项目再启动properties 文件是编译时被拷贝到 classpath 的只保存不重新构建不生效这一条值得划线。3.4 部署启动war 与 war exploded 的选择和启动验证如果走 Maven最直接的启动方式是这样的命令行流程mvn clean package cp target/homework.war $CATALINA_HOME/webapps/ cd $CATALINA_HOME/bin catalina.bat runmvn clean package会先清理旧产物再打包war 生成在 target 目录。把它丢进 Tomcat 的 webapps 目录启动 Tomcat 时会自动解压部署。这个方式的优点是和 IDEA 解耦答辩时借一台没装 IDEA 的电脑也能跑。缺点是每次改 Java 代码都要重新打包不适合开发阶段。IDEA 里配置好 Tomcat 后直接点 Debug 启动。启动成功的标志不是控制台不报错而是浏览器能打开登录页面。常见验证三步打开http://localhost:8080/看是否进入登录页检查 Tomcat Localhost Log 有没有Deployment of web application archive ... has finished最后在 IDEA 控制台看有没有 Exception 堆栈。如果满足前两步说明 web 容器没问题业务问题留到第五章排查。3.5 初始账号从哪来先查 t_user 表跑起来后登录页摆在那但账密是什么很多源码会在 schema.sql 末尾带 INSERT 语句。我一般先登录不是去猜密码而是用数据库客户端执行查询SELECT id, username, password, role FROM t_user;正常情况下能看到初始数据常见的初始账号是 admin/admin123、teacher/123456、student/123456。如果查询结果是空表自己补一条管理员INSERT INTO t_user(username, password, role, real_name) VALUES (admin, 123456, admin, 管理员);密码字段如果是 MD5 加密存储直接插明文是登录不了的。此时你需要看源码里登录逻辑怎么加密常见的做法是MD5Util.md5(password)那插入前就得手动把密码也过一遍同样的加密。还有更老的项目直接存明文那 INSERT 语句里的密码原样写就能通。分辨方法很简单看数据库里现有数据的 password 列是202cb962ac59075b964b07152d234b70这种 32 位字符串还是123456明文前者需要加密。4. 读核心代码登录校验、AuthFilter 权限过滤、文件上传的三段必读代码环境跑通后源码对你来说就不是黑匣子文件了。第四章专门挑答辩时最常被追问的三段代码讲透。读懂这三段你基本就掌握了这套源码的所有门道。4.1 LoginServlet登录逻辑为什么放在 Servlet 而不是 JSP这段是所有 JavaWeb 课设的核心代码一般长这样WebServlet(/login) public class LoginServlet extends HttpServlet { private UserService userService new UserService(); Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username request.getParameter(username); String password request.getParameter(password); // 业务判断交给 service 层 User user userService.login(username, password); if (user null) { request.setAttribute(msg, 用户名或密码错误); request.getRequestDispatcher(login.jsp).forward(request, response); return; } // 登录成功后把用户对象放进 session request.getSession().setAttribute(loginUser, user); response.sendRedirect(index.jsp); } }关键在最后两行。就是把 user 放进 session 后为什么用sendRedirect而不是forward因为 forward 是服务端转发浏览器地址栏还停留在/login此时按 F5 刷新会再次提交 POST 请求导致重复登录或表单重复提交。而sendRedirect让浏览器重新发起一次 GET 请求地址变成index.jsp刷新只是刷新页面不会重复提交表单。这个细节答辩时说出来老师会觉得你真读过代码。再就是为什么不在 Servlet 里直接拼 JDBC 查数据库。这里体现了 service 层的意义登录后续还要加“错误次数限制”“状态校验”时只改 service 层Servlet 不用动。哪怕这个项目的 service 层只有一行return userDao.findByUsername(username)只要它存在结构上就说得通。4.2 AuthFilter拦不住未登录访问系统就等于裸奔没写 Filter 的作业管理系统只要知道 URL 路径就能绕过登录直接访问。这就是 AuthFilter 存在的意义WebFilter(/*) public class AuthFilter implements Filter { Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request (HttpServletRequest) req; HttpServletResponse response (HttpServletResponse) resp; String uri request.getRequestURI(); // 白名单登录页、登录接口、注册接口、静态资源 if (uri.endsWith(/login.jsp) || uri.endsWith(/login) || uri.endsWith(/register) || uri.contains(/static/)) { chain.doFilter(req, resp); return; } // 没登录就去登录页 Object loginUser request.getSession().getAttribute(loginUser); if (loginUser null) { response.sendRedirect(request.getContextPath() /login.jsp); return; } chain.doFilter(req, resp); } }注意过滤器的拦截路径是/*意思是所有请求都会过这道门。白名单里必须放行两条链路登录页面本身和登录处理逻辑否则会死循环——请求 login.jsp 被拦截重定向回 login.jsp又被拦截页面疯狂刷。另外静态资源 CSS 和 JS 也要放行否则页面会变成纯 HTML 裸样式。如果是老式 web.xml 配置 Filter注意 filer-mapping 里url-pattern/*/url-pattern不要写成/只写斜杠意味着只拦截根路径等于没写。Filter 里没有登录用户时的标准处理方式是response.sendRedirect(request.getContextPath() /login.jsp)别漏了getContextPath()否则 context 不是/时会跳到不存在的路径。4.3 作业提交与文件上传getPart 的正确打开方式作业提交页面必须用 multipart 表单提交代码用的是 Servlet 3.0 的 getPart。页面侧的要点是 form 表单上的 enctypeform actionuploadHomework methodpost enctypemultipart/form-data input typehidden namehomeworkId value1 input typefile namefile button typesubmit提交作业/button /form对应的上传逻辑WebServlet(/uploadHomework) MultipartConfig public class UploadServlet extends HttpServlet { Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // 取文件部分 Part part request.getPart(file); String fileName Paths.get(part.getSubmittedFileName()).getFileName().toString(); // 用 UUID 改名避免中文名和重名 String ext fileName.substring(fileName.lastIndexOf(.)); String saveName UUID.randomUUID().toString().replace(-, ) ext; String dir getServletContext().getRealPath(/upload); Files.createDirectories(Paths.get(dir)); part.write(dir File.separator saveName); // 把文件记录写库 int homeworkId Integer.parseInt(request.getParameter(homeworkId)); submissionService.add(homeworkId, currentStudentId, saveName); response.sendRedirect(submissionSuccess.jsp); } }类上的MultipartConfig不能漏它告诉容器这个 Servlet 能处理 multipart/form-data 请求。漏了它request.getPart直接返回 null文件传不上去。Tomcat 8 之后加了它getParameter(homeworkId)才能正常读到隐藏字段如果getParameter拿到 null优先怀疑注解没写而不是过滤器问题。part.write(dir File.separator saveName)是重点参数说明dir 是把/upload映射到部署目录的真实磁盘路径。IDEA 里使用 war exploded 部署时这个目录每次重新部署可能被覆盖或清空文件会神秘消失。常见做法是把它改成项目外固定路径比如D:/uploads或 Linux 下的/var/uploads用绝对路径存文件不依赖工程目录。文件名用 UUID 而不是原名是为了避免张三的作业最终版(1).docx这种含中文和括号的文件名在跨平台时乱码同时防止两个学生传同名文件互相覆盖。另外 Tomcat 对 POST 请求大小默认限制在 2MB 左右传大作业文件会直接报错或返回 500。真要大文件在 Tomcat 的 server.xml 里给 Connector 加一个属性maxPostSize-1负值表示不限大小。4.4 JDBC 连接的黑匣子DriverManager、Class.forName 与连接池最后一段必读代码是工具类几乎所有课设都会有这么一段public class DBUtil { private static String url; private static String user; private static String password; static { try { Class.forName(com.mysql.jdbc.Driver); // 从 db.properties 读取连接参数 } catch (ClassNotFoundException e) { throw new ExceptionInInitializerError(e); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(url, user, password); } }Class.forName的作用是把驱动类加载进 JVM触发驱动注册到 DriverManager。MySQL 8 用户把类名com.mysql.jdbc.Driver改成com.mysql.cj.jdbc.Driver同时 url 加时区参数。之所以说这是黑匣子是因为很多人配环境时只改密码不改驱动名报错信息又长又绕根本想不到是这里的问题。答辩时老师很可能问“每次请求都创建 Connection项目上线能扛住吗” 标准回答课设里这样写是为了演示 JDBC 流程生产环境会用连接池。然后能说出 Druid 或 HikariCP 的名字就够。如果想在源码基础上直接优化最常见的做法是引入 Druiddb.properties 改成druid.driverClassNamecom.mysql.jdbc.Driver druid.urljdbc:mysql://localhost:3306/homework_db?useSSLfalsecharacterEncodingutf8 druid.usernameroot druid.password123456 druid.initialSize5 druid.maxActive20initialSize5表示启动时初始化 5 个连接maxActive20表示连接池最多同时持有 20 个连接。这个改动不大但在答辩中属于“我不仅会跑代码还能指出它的短板并给出改进方案”的加分项。提示db.properties 在 classpath 下修改后必须重新 Build 项目并重启 Tomcat。很多人改完连接串发现没生效不是代码问题是 properties 文件没被重新拷贝到 target 或 classes 目录。5. 复现作业管理源码的 5 个常见问题现象、原因、解决办法这一章按出现频率从高到低排列每一条都是我在帮人调这种课设源码时真实见过的。现象描述直接对标你遇到的情况不要跳着往下读先定位到自己卡住的那条。5.1 导入 IDEA 后代码全部爆红javax.servlet 找不到现象打开项目后所有 Java 文件里javax.servlet.http.HttpServlet这一行标红整个文件满屏波浪线。原因项目没有挂载 Servlet 运行库。要么是普通 Java 项目没转成 Web 项目要么是 Maven 工程缺javax.servlet-api依赖。解决Maven 工程在 pom.xml 里加这段依赖并刷新dependency groupIdjavax.servlet/groupId artifactIdjavax.servlet-api/artifactId version4.0.1/version scopeprovided/scope /dependency非 Maven 工程则按第三章 3.2 的步骤在 Project Structure - Libraries 里手动添加 Tomcat 的 servlet-api.jar。scopeprovided的意思是打包时不需要带上这个 jar因为 Tomcat 容器本身提供 Servlet API带上反而可能和容器冲突。5.2 登录成功后马上弹回登录页Filter 没放行登录请求现象用户名密码明明正确登录后地址栏一闪又回到 login.jsp。原因AuthFilter 拦截了登录接口或登录页本身session 还没建立就被重定向。也可能是登录成功后sendRedirect(index.jsp)但 index.jsp 也被过滤器拦了而 session 里的 loginUser 没存入或者存取的 key 对不上。解决先把 Filter 放行路径检查一遍。/login、/login.jsp、/register必须出现在白名单里。再看登录 Servlet 存 session 用的 key 是什么loginUser还是userFilter 里取 Session 的 key 必须和存的时候一模一样。这两个 key 一个字母对不上就会出现“明明登录成功下一页又没登录”的诡异现象这也是最典型的“玄学” bug。5.3 MySQL 连接报错Communications link failure / Unknown database现象Tomcat 启动后只要一触发登录就抛异常控制台出现Communications link failure、Unknown database homework_db或Access denied for user rootlocalhost。原因三者原因不同。Communications link failure 是 MySQL 服务没启动、连接串的端口不对或者 MySQL 8 时区没配Unknown database 是连接串里的库名和实际数据库名不一致Access denied 是密码错误或者用户名不是 root。解决先别改代码用命令行验证数据库本身是健康的mysql -uroot -p能进说明服务正常。然后执行SHOW DATABASES;确认库名。最后把 db.properties 里的 url、username、password 逐字符比对这些信息。MySQL 8 用户检查两处驱动类名是否是com.mysql.cj.jdbc.Driverurl 最后有没有serverTimezoneAsia/Shanghai。这条链路的高频原因其实是库名不一致因为很多 zip 里自带的脚本建的是homework连接串写的却是homework_db差一个下划线就报错。5.4 作业文件上传后出现乱码、文件丢失或者 500现象上传中文文件名课程设计报告.docx后页面上文件名乱码或者提交成功后去 upload 目录找不到文件传大文件直接 500。原因乱码是页面或请求编码不是 UTF-8文件丢失大概率是保存目录经过了 IDEA 的重新部署被清空500 一般是 Tomcat 默认 POST 大小限制约 2MB触发了异常。解决三层排查。第一层登录 Servlet 的 doPost 开头或 Filter 里设置request.setCharacterEncoding(UTF-8)同时数据库连接串保证characterEncodingutf8第二层把保存目录从getServletContext().getRealPath(/upload)改成项目外的绝对路径比如D:/uploadsJDBC 或 Service 层把这个路径写进 t_submission 的 file_path 字段第三层如果作业文件超过 2MB在 Tomcat 的 server.xml 里给 Connector 加maxPostSize-1或者限制前端只能传 2MB 以内文件并给出提示。5.5 端口被占用8080 起不来Tomcat 显示白屏现象IDEA 启动 Tomcat 后弹出提示端口被占用或者浏览器打开http://localhost:8080白屏控制台日志里有一行Port 8080 was already in use。原因之前启动的 Tomcat 没关掉或者系统里别的进程占用了 8080常见的是另一个 Java 服务。解决在命令行里找到占用进程再结束它netstat -ano | findstr 8080 taskkill /F /PID 这里替换成上一条命令查到的PID或者更省事的办法在 IDEA 的 Run Configurations 里把 Tomcat 端口改成 8081访问地址也跟着变成http://localhost:8081/。注意上下文里如果代码写死了跳转路径带 8080改端口后跳转可能失效但绝大多数课设用相对路径不受影响。6. 答辩前把它升级成 Spring Boot一张最小迁移清单如果你课设要求写明“技术栈为 JavaWeb”那保持原样即可。如果你想让项目看起来比同组同学“新一个时代”或者答辩时被问“这套结构能不能改进”最稳妥的加分操作是把 Servlet 加 JSP 的老骨架迁移到 Spring Boot但三张数据库表完全不用动。迁移后的项目既保留了原有的业务逻辑又用上了 Spring Boot 的自动配置讲起来也有话题。6.1 三层可以保留先替换掉的是 Servlet 和 JDBC原项目的 controller/service/dao 三层直接平移需要替换的只有接入层。新旧写法的对应关系如下原 JavaWeb 写法Spring Boot 等价物web.xml WebServletController RequestMappingAuthFilterHandlerInterceptor 或 WebFilter ServletComponentScanrequest.getPart 上传MultipartFile 参数DBUtil DriverManagerspring-boot-starter-jdbc 数据源JSP 页面可选保留 JSP 或换 Thymeleaf最小依赖只用两个 starterdependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-jdbc/artifactId /dependency数据库配置从 db.properties 挪进 application.yml内容基本就是复制粘贴再换个形式spring: datasource: url: jdbc:mysql://localhost:3306/homework_db?useSSLfalsecharacterEncodingutf8 username: root password: 123456 driver-class-name: com.mysql.jdbc.Driver连接池不用自己配Spring Boot 默认注入 HikariCP这正好回应第四章说过的“生产环境用连接池”的问题。上传的 MultipartFile 参数天生支持 multipart 解析连MultipartConfig都不需要写。6.2 迁移完按这个顺序验证迁移完成后不要一口气把登录、上传、过滤全改完再启动。我一般按这个顺序验证出问题时能立刻定位到具体环节启动应用确认数据源配置无误没有报数据库连接异常先测登录直接用 Postman 往/login发 POST看能否正常返回因为此时登录接口还是原逻辑能跑通说明 controller 包扫描正常再测上传用浏览器或 Postman 的 multipart 表单上传一个文件检查保存目录里有没有文件出现数据库里有没有新增提交记录最后加上 Filter 或拦截器验证未登录访问/homework/list是否会被拦截跳转如果迁移后登录失败最常见的问题只有一个原 LoginServlet 的WebServlet(/login)路径和 Spring Boot 里 controller 的RequestMapping(/login)重复映射了Spring Boot 报错 “Ambiguous mapping”删掉旧的 Servlet 类即可。这不算坑是迁移必须做的事。我当年做课设时把老师给的模板整段复制PPT 上写着“本项目采用 MVC 架构”但被问“那你的 Filter 在哪”直接愣住。后来才想明白这种国产课设源码里最容易拿分的东西从来不是页面做得多花哨而是分层、过滤器和数据库设计这几个硬骨架。现在再拿到这种 zip我一定是先画请求路径图再改连接配置最后才动代码。希望帮到你。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进