简介:这是一款基于Java Web开发的在线答题平台项目源码,面向Java初学者、毕业设计以及课程设计人群,以学生在线自测与教师后台管理为主线,完整覆盖用户登录、答题、评分、统计等核心业务闭环。压缩包共388个文件,大小约6.1MB,内部包含Java源代码、JSP动态页面、JavaScript脚本、CSS样式文件等程序核心文件,辅以125个GIF动图和65张PNG截图,用于直观展示学生答题、个人中心和后台管理等场景的操作过程。目前已有62人学习下载,适合直接部署或作为二次开发的基础。在学生端,项目实现首页一次性限答,系统会拦截重复提交,个人中心支持查看与修改资料、密码,并按答题分数自动分配班级;教师端则提供学院、专业、班级、试题、学生等基础数据的增删改查,支持按整体、地区、班级生成成绩统计图,方便掌握学情分布。随包附上项目运行截图与说明文档,既能快速导入IDE运行,也能作为毕业设计答辩或JavaWeb实训的完整参考,帮助理清前后端交互关系。
1. 在线答题平台.zip:一份能跑通的 JavaWeb 完整案例,值得花半小时拆开
如果你正在找 JavaWeb 课设需要的完整案例,大概率会碰到两种东西:只有代码片段没有工程结构的博客,或者下载下来缺 SQL、缺配置的残包。这份基于 JavaWeb 的在线答题平台 zip 属于少见能跑通的一类:解压后有源码、数据库脚本、页面资源和运行说明,配合 MySQL 就能把注册登录、随机抽题、交卷判分、成绩统计完整跑一遍。它不是 Spring Boot 全家桶,而是更贴近教学标准的 Servlet + JSP + JDBC 结构,特别适合需要讲清楚三层架构的课设答辩,也适合第一次做 JavaWeb 项目完整案例的人照着复现。我拿到这类项目的第一反应是先确认 IDEA 运行 JavaWeb 项目的最小环境,再读代码,这份资源正好把最磨人的环境部分压到了最低。
2. 先拆项目骨架:目录结构、技术栈、数据库表能告诉我们什么
拿到 zip 后不要急着当成成品来跑,先看三样东西:目录结构、配置文件、数据库脚本。我一般会按“源码能不能对上层页面负责、连接配置藏在哪里、表结构能不能解释答题业务”这三个问题去检查,顺了再往下走。
2.1 解压后的目录结构:一个可运行的 JavaWeb 工程该有哪几块
一个没有目录结构的压缩包,后面跑起来大概率是你自己在那补天补地。就这套在线答题平台而言,典型的工程组织方式是这样的:
online-exam/ ├── src/ │ ├── com/exam/ │ │ ├── dao/ # 数据访问层,JdbcTemplate 或原生 JDBC │ │ ├── entity/ # 用户、题目、记录等实体 │ │ ├── servlet/ # 登录、注册、考试等控制层 │ │ ├── filter/ # 登录验证、编码过滤器 │ │ └── util/ # DBUtil、MD5 加密等 │ └── resources/ │ └── db.properties # 数据库连接配置 ├── web/ │ ├── css/ │ ├── js/ │ ├── images/ │ ├── admin/ # 管理端页面 │ ├── login.jsp │ ├── exam.jsp │ └── WEB-INF/ │ └── web.xml # Servlet 映射与 index 配置 ├── sql/ │ └── online_exam.sql # 建库建表数据脚本 └── README.md # 部署说明这不是标准答案,每个资源包组织方式不一样,但判断标准相同:源码、页面、SQL、说明四件套缺一不可。WEB-INF下的web.xml在旧工程里是核心,新版 Servlet 3.0 可以只靠注解,但web.xml仍然会提供欢迎页和全局过滤器顺序,要重点看。db.properties里通常放着 JDBC URL 和密码,读代码前先把这儿的坑找出来。
如果看到pom.xml,说明是 Maven 工程;没有则意味着 jar 包要么在lib目录,要么需要自己找。很多 JavaWeb 完整案例资源是非 Maven 的,部署时最常出的错就出在 jar 包没进 Artifact,后面第 5 章会专门写。
2.2 技术栈选型:Servlet、JSP、MySQL 这套组合为什么是课设“标准答案”
在线答题平台用 Servlet + JSP 而不是 Spring Boot,不是因为它先进,而是因为课程大纲里教的就是这一套。课设答辩时间通常只有几分钟,老师更想知道你能不能讲清楚一次完整的 HTTP 请求如何被 Servlet 接收、如何调用 DAO、如何把结果转发到 JSP。Spring Boot 会把太多细节藏起来,讲起来反而容易被问住。
| 组件 | 这里用什么 | 替代方案 | 选择理由 |
|---|---|---|---|
| Web 容器 | Tomcat 8.5/9 | Jetty | 课设环境最常见,IDE 集成度高 |
| 业务控制 | Servlet | Spring MVC | 手动配置映射和过滤器,原理清晰 |
| 数据访问 | JDBC + DAO | MyBatis | 能讲清楚连接、预处理、事务边界 |
| 数据库 | MySQL 5.7+ | Oracle、H2 | 免费,SQL 脚本通用性好 |
这也是为什么这类 javaweb 项目完整案例 mysql 版的资源特别受欢迎:它正好落在教学标准答案上。版本上我一般会用 JDK 1.8 + Tomcat 8.5 + MySQL 5.7 这套组合,兼容性最好;如果你的电脑是更新的 JDK,至少要保证 Tomcat 版本跟得上,否则会报不兼容。
2.3 数据库设计:五张核心表如何支撑一次在线考试
在线答题平台看似简单,但业务闭环至少需要五张表:用户表、题库表、试卷表、答题记录表、答题明细表。如果还要做错题本,再加一张错题表,但五张表已经足够把一套基干功能撑起来。这里给出一个符合常见设计的建表脚本:
CREATE DATABASE IF NOT EXISTS online_exam DEFAULT CHARACTER SET utf8mb4; USE online_exam; -- 用户表:role=1 管理员,role=2 考生 CREATE TABLE t_user ( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) NOT NULL UNIQUE, password VARCHAR(64) NOT NULL, real_name VARCHAR(50), role TINYINT NOT NULL DEFAULT 2, create_time DATETIME DEFAULT CURRENT_TIMESTAMP ); -- 题库表:type 1单选 2多选 3判断 CREATE TABLE t_question ( id INT PRIMARY KEY AUTO_INCREMENT, type TINYINT NOT NULL, content TEXT NOT NULL, option_a VARCHAR(255), option_b VARCHAR(255), option_c VARCHAR(255), option_d VARCHAR(255), answer VARCHAR(20) NOT NULL, score INT DEFAULT 5, status TINYINT DEFAULT 1 ); -- 试卷表:考试场次,start_time/end_time 控制可用时间 CREATE TABLE t_exam ( id INT PRIMARY KEY AUTO_INCREMENT, title VARCHAR(100) NOT NULL, duration INT DEFAULT 60, start_time DATETIME, end_time DATETIME ); -- 答题记录表:每个用户每场考试一条主记录 CREATE TABLE t_record ( id INT PRIMARY KEY AUTO_INCREMENT, exam_id INT, user_id INT, total_score INT DEFAULT 0, create_time DATETIME DEFAULT CURRENT_TIMESTAMP, CONSTRAINT fk_record_exam FOREIGN KEY (exam_id) REFERENCES t_exam(id), CONSTRAINT fk_record_user FOREIGN KEY (user_id) REFERENCES t_user(id) ); -- 答题明细表:记录用户每道题的答案和判分结果 CREATE TABLE t_record_detail ( id INT PRIMARY KEY AUTO_INCREMENT, record_id INT, question_id INT, user_answer VARCHAR(20), is_correct TINYINT, CONSTRAINT fk_detail_record FOREIGN KEY (record_id) REFERENCES t_record(id) );这里的字段设计有几个值得注意的地方。answer字段用VARCHAR(20)而不是存 JSON,因为单选和判断只存A/B/C/D这样的单字母,多选存ABD这类连续字符串,判空和比对都容易。status字段用来下架旧题,防止后台删除的时候影响外键关系。t_exam和t_record之间的外键,可以做到每场考试只允许一次完整交卷,重复提交时先查询已有记录再决定是否覆盖。
交卷之后,成绩统计用一条JOIN就能完成,明细里is_correct是 0/1,题目表里的score是每题分值:
SELECT u.username, SUM(d.is_correct * q.score) AS total_score FROM t_record r JOIN t_record_detail d ON d.record_id = r.id JOIN t_question q ON q.id = d.question_id JOIN t_user u ON u.id = r.user_id WHERE r.id = 1 GROUP BY u.id;这个查询把整个判分结果汇总在主记录上,也是答辩时最容易被问到的 SQL 之一。如果你拿到的资源里没有t_exam表,也不要紧,考试场次可能被设计成了固定题目列表,但t_record和t_record_detail这两张表几乎是绕不开的。
3. 在 IDEA 里把它跑起来:环境搭配、数据库导入与 Tomcat 部署
上一章读了骨架,现在进入动手环节。这一步我会把 IDEA 运行 JavaWeb 项目配置的每一步写清楚,包括版本选择、数据库导入和 Tomcat 部署。很多课设项目跑不起来,不是代码问题,而是环境没有对齐。
3.1 环境版本:先用这套组合跑通,再考虑升级
先确定最小环境,再动代码。我一般会先保证四样东西:
- JDK 1.8:Tomcat 8.5 和旧 JSP 兼容最好,IDEA 中 Project SDK 设为 1.8。JDK 11 以上也行,但需要把 Tomcat 升到 9/10,否则可能出现初始化失败。
- Tomcat 8.5.xx:支持 Servlet 3.1,和大多数 JavaWeb 资源包里的
web.xml头声明一致,不需要改配置。 - MySQL 5.7 或 8.0:字符集选 utf8mb4。如果资源里的驱动 jar 是
mysql-connector-java-5.1.47,连接 MySQL 8 会有兼容问题,最好用 5.7。 - IDEA Ultimate 版:Tomcat 集成在 Ultimate 里,Community 版需要装 Smart Tomcat 插件,新手不建议在这里折腾。
```properties jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/online_exam?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai jdbc.username=root jdbc.password=123456参数说明:serverTimezone=Asia/Shanghai解决 MySQL 8 默认 UTC 导致的时间差;useSSL=false去掉握手警告;characterEncoding=utf8与建库字符集保持一致。如果 MySQL 是 8.0,请把jdbc.driver改成com.mysql.cj.jdbc.Driver;如果项目里没有db.properties,搜索jdbc.url就能找到连接配置写在哪里。
3.2 从导入到启动:IDEA 运行 JavaWeb 项目配置全流程
这个流程我每跑一个 JavaWeb 项目都会走一遍,已经快成肌肉记忆了:
- 解压 zip,用 IDEA 的 File → Open 选择项目目录。如果项目里有
.idea文件夹,说明别人导入过,配置参考价值有限,不一定适合你本地的 Tomcat 路径。 - 设置 Project SDK:File → Project Structure → Project,选择已安装的 JDK 1.8,Language level 选 8。
- 添加 Artifact:Project Structure → Artifacts → 点 + → Web Application Exploded,选择当前项目。确认 Output Layout 里有
WEB-INF/lib,并把项目依赖的 jar 包放进去。 - 配置 Tomcat:Run → Edit Configurations → 点 + → Tomcat Server → Local。Application server 选择 Tomcat 安装目录。
- 在 Deployment 标签页点 + → Artifact,选择刚才的 war exploded。Application context 建议设为
/online_exam。 - 启动前检查
db.properties里的用户名、密码、数据库名是否和本机 MySQL 一致。
第 5 步的 Application context 最容易翻车。默认值往往是online_exam_war_exploded,启动后浏览器访问路径又长又丑,而且页面内部的相对路径会因此错位。直接改成/online_exam,后面访问首页就是http://localhost:8080/online_exam/,清爽得多。
3.3 初始化数据库:SQL 脚本执行的两种方式和注意事项
数据库脚本是这份资源里最值钱的部分之一,因为它不只含建表语句,通常还带测试数据。执行方式有两种,我优先推荐命令行,因为能看到更明确的报错信息:
mysql -uroot -p --default-character-set=utf8 < sql/online_exam.sql这个命令会读取项目里的sql/online_exam.sql文件,并按 UTF-8 编码执行。如果脚本里没有CREATE DATABASE语句,需要先手动建立数据库,否则会报No database selected。执行完后建议验证一下:
SHOW TABLES; SELECT COUNT(*) FROM t_question;看到五张表且t_question有数据,说明导入成功。如果表存在但没有数据,检查脚本末尾是否被TRUNCATE或DELETE清空过,有些资源为了方便重复执行会在开头清空表,这属于正常现象。
如果使用 Navicat 或 MySQL Workbench,执行时同样要注意选择 utf8mb4 字符集,尤其是 Windows 环境。用 SQL 文件导入时,如果文件头没有SET NAMES utf8mb4,中文题目就有可能在导入时就变成问号,后面再处理就很被动。
3.4 部署到 Tomcat:访问路径与启动日志怎么看
配置好之后点击 Debug 启动,正确现象是控制台输出INFO: Server startup in [xxx] milliseconds,之后浏览器可以访问http://localhost:8080/online_exam/login.jsp。如果直接访问根路径 404,说明web.xml里没有欢迎页配置,需要加:
<welcome-file-list> <welcome-file>login.jsp</welcome-file> </welcome-file-list>这里有个容易踩的小坑:JSP 里写静态资源时,如果写成/css/style.css这种绝对路径,项目部署到 Tomcat 后浏览器会去请求http://localhost:8080/css/style.css,少了/online_exam前缀,页面就会“裸奔”。正确写法是带上当前项目的上下文路径:
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/style.css">另外,启动后先看日志里有没有ClassNotFoundException或NoClassDefFoundError,有就说明依赖 jar 没有进入 Artifact,后面会专门讲。这一步如果只是访问login.jsp,不需要数据库真的连上;但要登录,第 3 节的数据库导入就必须先完成。
4. 核心业务实现:登录鉴权、随机抽题、交卷判分的代码长什么样
在线答题平台的三个核心点是鉴权、抽题、判分,每一个都会在答辩时被追问。以下分析基于这类平台的常见实现方式,即使你拿到的资源里代码组织不完全一样,思路也是通用的。
4.1 登录与 Session 鉴权:用一个 Filter 挡住未登录访问
登录成功后的标准做法是把用户对象放进HttpSession,然后对所有受保护页面做过滤器判断。下面这段过滤器是这类项目的标配:
public class AuthFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse resp = (HttpServletResponse) response; String path = req.getRequestURI().substring(req.getContextPath().length()); if (path.equals("/login.jsp") || path.equals("/login") || path.equals("/register") || path.endsWith(".css") || path.endsWith(".js")) { chain.doFilter(req, resp); return; } HttpSession session = req.getSession(false); Object loginUser = session == null ? null : session.getAttribute("loginUser"); if (loginUser == null) { resp.sendRedirect(req.getContextPath() + "/login.jsp"); return; } chain.doFilter(req, resp); } }这里有两个细节值得注意。req.getSession(false)不会新建 session,避免未登录用户访问时也产生会话对象,减少内存垃圾。path.endsWith(".js")必须放行,否则页面里的脚本会被过滤器拦截,前端报一堆 ReferenceError,很多人排查半天才发现是过滤器把它们拦了。
过滤器写好后,需要在web.xml里注册映射:
<filter> <filter-name>AuthFilter</filter-name> <filter-class>com.exam.filter.AuthFilter</filter-class> </filter> <filter-mapping> <filter-name>AuthFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>/*代表拦截所有请求,所以放行列表要写全。如果用的是 Servlet 3.0 注解@WebFilter("/*"),过滤器的执行顺序按类名决定,不容易控制,建议保留web.xml声明。
4.2 随机抽题:从 ORDER BY RAND 到按题型分组抽题
题库数据量小的时候,最简单直接的抽题方式就是让数据库随机排序:
-- 从单选题中抽 5 道 SELECT * FROM t_question WHERE type = 1 AND status = 1 ORDER BY RAND() LIMIT 5;这里status = 1是为了排除已下架的题目,ORDER BY RAND()会在全表随机排序后取前 5 条。数据量只有几百条时,性能不是问题;但如果题库上万,RAND()会让 MySQL 全表扫描,卡顿明显。课设场景下通常不需要优化,答辩时能说清楚“现在数据量小所以直接用 RAND,后续可以改成预取题号再IN查询”就已经够了。
更完整一点的做法是按题型分组,每种抽固定数量,再在前端打乱选项顺序:
List<Question> singleList = dao.findByType(1, 5); List<Question> multiList = dao.findByType(2, 5); List<Question> judgeList = dao.findByType(3, 5); Collections.shuffle(judgeList); request.setAttribute("singleList", singleList);findByType方法内部就是上面那条带WHERE type = ?的 SQL。注意我这里的Collections.shuffle只是打乱判断题顺序,如果要做到每个人面前的题目顺序都不同,需要在加载列表时也把singleList和multiListshuffle 一次。在 JSP 输出选项时,可以额外用一个随机数控制 A/B/C/D 的渲染顺序,更防作弊,但实现复杂度也会上升。
4.3 交卷判分:为什么分数不能信任前端计算
交卷时前端把答案提交到 Servlet,Servlet 不能直接用页面传过来的分数,必须重新从数据库读正确答案,逐题比对,再把明细写入事务。原因是用户可以修改页面源码,把“计算分数”的 JS 删掉,甚至直接伪造提交。服务端判分才是可信的。
核心思路是这样:
String[] answers = request.getParameterValues("answer_" + questionId); // 多选时 answers 可能是一个数组,单选时也可以统一取第一个 Map<Integer, String> correctMap = examService.getCorrectAnswers(examId); List<Detail> detailList = new ArrayList<>(); for (Map.Entry<Integer, String> entry : correctMap.entrySet()) { String userAnswer = request.getParameter("answer_" + entry.getKey()); boolean correct = entry.getValue().equalsIgnoreCase(userAnswer); Detail d = new Detail(); d.setQuestionId(entry.getKey()); d.setUserAnswer(userAnswer); d.setCorrect(correct ? 1 : 0); detailList.add(d); }这里有个容易翻车的点:多选题如果用getParameterValues取到数组,不要只取[0],要把数组元素拼接起来再比对。比如正确答案是ABD,用户勾了A、B、D,数组是["A","B","D"],拼接成"ABD"才能做字符串比较。
判分完成之后,主记录和明细要放在同一个事务里:
try (Connection conn = dataSource.getConnection()) { conn.setAutoCommit(false); int recordId = examDao.insertRecord(conn, examId, userId, totalScore); for (Detail d : detailList) { examDao.insertDetail(conn, recordId, d); } conn.commit(); } catch (Exception e) { conn.rollback(); log.error("交卷失败", e); }setAutoCommit(false)之后,如果明细插入中途失败,rollback()会让主记录也一起消失,避免留下一张“半卷”。添加唯一索引在t_record的(exam_id, user_id)上,还可以防止重复交卷导致成绩被覆盖两次。这些细节在课设答辩里属于加分项,能说出来基本就能证明你理解了事务。
5. 避坑指南:把这套在线答题平台跑起来后我踩过的 5 个坑
项目本身能跑,不代表你本地一次就能跑起来。下面五条是我在实际跑同类 JavaWeb 项目时最常遇到的问题,每一条都按“现象、原因、解决”的路径走,你如果卡在哪一步,直接对号入座。
5.1 启动后首页 404:Application context 没对上
现象:IDEA 里 Tomcat 正常启动,控制台没有报错,但浏览器访问http://localhost:8080/显示 404,只能敲长路径/online_exam_war_exploded/login.jsp才打开。
原因:IDEA 部署时的 Application context 默认是war_exploded长路径,页面里的资源链接又往往写成相对路径,导致跳转后找不到 CSS 和 JSP。
解决:在 Run/Debug Configurations → Deployment 里,把 Application context 改成/online_exam,重启。如果资源依旧 404,把 JSP 里的静态资源全部改成以${pageContext.request.contextPath}开头:
<link rel="stylesheet" href="${pageContext.request.contextPath}/css/style.css">不统一改的话,也可以一直用长路径访问,但每次跳转都容易漏写前缀,而且会让你误以为代码有问题。这套改法属于一劳永逸。
5.2 数据库连接失败:驱动类名、时区、SSL 三个信号
现象:点登录直接报CommunicationsException: Communications link failure,或Public Key Retrieval is not allowed,控制台显示驱动连接被重置。
原因:MySQL 8 的驱动类名从com.mysql.jdbc.Driver改成了com.mysql.cj.jdbc.Driver;连接 URL 缺乏serverTimezone;MySQL 服务本身没启动。也有可能是密码里带特殊字符在配置文件中没转义。
解决:先确认 MySQL 进程在运行,再检查驱动类。如果是 MySQL 5.7,用com.mysql.jdbc.Driver;如果是 MySQL 8,改成:
jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/online_exam?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=trueallowPublicKeyRetrieval=true是为了兼容 MySQL 8 的caching_sha2_password认证,不加就会在第一次连接时报错。如果改完还不行,检查jdbc.username是否有权限访问online_exam库,很多坑不是驱动问题,而是用户密码配错。
5.3 中文乱码:三层编码只改了一层
现象:注册页面输入“张三”,数据库里存的是???;或者登录页标题出现乱码。
原因:JSP 页面编码、Servlet 请求编码、MySQL 连接编码不一致。常见错误是web.xml里的编码过滤器没有forceEncoding=true,或者 SQL 脚本以 GBK 导入。
解决:统一成 UTF-8。先检查 JSP 第一行:
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>再检查web.xml里的编码过滤器:
<filter> <filter-name>encoding</filter-name> <filter-class>com.exam.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter>最后确认 MySQL 表结构是utf8mb4:
SHOW CREATE TABLE t_user;这里有个判断经验:输入中文后立刻变问号,多半是连接 URL 或请求编码的问题;如果页面能正常显示但数据库里是问号,多半是表结构或 SQL 文件导入时的问题。按层次排查,不要每次只改一处。
5.4 交卷空指针:参数名对不上
现象:做完题提交,页面直接报 500,控制台出现java.lang.NullPointerException,定位在request.getParameter("answer_" + questionId)这一行。
原因:JSP 里input的 name 与 Servlet 接收的参数名不一致。比如单选题名用了answer_1,多选题名用了answers_1,后台统一用answer_开头去取,多选数组取到的是 null。
解决:打开 JSP 源码,确认每个输入控件的 name。多选数组必须用getParameterValues:
String[] selected = request.getParameterValues("answer_" + q.getId()); if (selected != null) { String userAnswer = String.join("", selected); }HTML 中多选 checkbox 同名,后台如果用getParameter只能取到第一个值,判分结果就会变成漏选。这个坑在在线答题平台里特别常见,因为你可能一道题有单选也有多选,参数命名稍不注意就撞了。处理原则是:前端传值只当字符串,后端必须重新按题号读正确答案再判。
5.5 Artifact 部署失败:依赖没进 WEB-INF/lib
现象:IDEA 配置完 Tomcat,启动时报Error during artifact deployment,日志里出现ClassNotFoundException: com.mysql.jdbc.Driver。
原因:非 Maven 项目通常把 jar 放在src/lib或外部目录,但 IDEA 的 Artifact 没有把这些 jar 打包进去,Tomcat 运行目录下的WEB-INF/lib是空的。
解决:Project Structure → Artifacts → 选中 web artifact → Output Layout → 展开WEB-INF,在 lib 节点右键 Add Copy of,把项目 lib 目录里的所有 jar 加进去,然后重新 Build Artifact。
这里注意war exploded和war的差别。war exploded是解压目录直接跑,启动快;war是打包后再部署。课设阶段用war exploded就够了。如果你在 Project Structure 里半天没找到 Output Layout,先确认是否已经添加了 Web Application Artifact,没有的话全白看。
6. 把它改成你的课设:三个定制点和一次完整验收
原始包跑通以后,接下来最想做的就是把标题改成自己的、把题库换成自己的。这里分享三个低成本定制点。
第一个定制点是替换题库数据。打开sql/online_exam.sql里t_question的 INSERT 语句,如果只有几条,直接换成自己的题目。注意answer字段的约定:单选存A/B/C/D,多选存ABD这种连续字符串,判断存A/B或T/F,一定要和原表保持一致。选项不足四个时留空字符串,不要写 NULL,否则 JSP 输出选项会遍历到空值:
INSERT INTO t_question (type, content, option_a, option_b, option_c, option_d, answer, score) VALUES (1, 'Java 中 int 类型的长度是多少?', '8位', '16位', '32位', '64位', 'C', 5), (2, '下列哪些是运行时异常?', 'NullPointerException', 'ClassCastException', 'IOException', 'SQLException', 'AB', 10);第二个定制点是隐藏管理员入口。登录成功后根据t_user.role决定跳转地址,role=1 去/admin/index.jsp,role=2 去/exam.jsp。如果你不想让普通用户猜到管理员目录,可以在 session 里多放一个isAdmin=true,管理员页面再做一次过滤。这样改动量不大,答辩时还能顺口讲一句“权限控制做了两层”。
第三个定制点是快速验证整条链路。修改完数据后,不要只从浏览器反复点点点,我一般会直接执行这条 SQL:
SELECT u.username, r.total_score, COUNT(d.id) AS answer_count FROM t_record r LEFT JOIN t_user u ON r.user_id = u.id LEFT JOIN t_record_detail d ON d.record_id = r.id GROUP BY r.id;如果交卷后能查到总评分和明细数,说明从登录到判分的链路是通的。如果查不到,就回 Tomcat 日志里看AuthFilter有没有把考试请求拦掉,再看 Servlet 映射是否匹配。这比反复点击更容易定位问题。
以前我拿到这种 JavaWeb 案例,总是跳过环境验证直接改代码,结果一个 404 能消耗一下午。后来学乖了,不管是新项目还是旧资源,都先跑通原始包,再做任何定制。你可以把这份 zip 按上面的流程先跑一遍,再用这三个技巧换成自己的题库,大概率会顺利得多。希望帮到你。
本文还有配套的精品资源,点击获取