资讯动态

基于JSP+Servlet的在线考试管理系统设计与部署实践

发布时间:2026/10/1 12:22:05 来源:尧图企业网站定制
简介这套基于JSP与Servlet的在线考试管理系统面向计算机专业毕业设计和Java Web课程设计适合有一定Java基础的开发者学习。系统包含学生端和管理员端学生可以随机或指定试卷进行在线答题答题过程中显示倒计时与进度交卷后自动比对答案红色标记错题、绿色显示正确答案便于复习管理员可完成试题的增删改查、试卷发布、用户与角色管理以及权限分配覆盖从题库维护到成绩查看的完整考试流程。资源包共104个文件主体为43个Java源文件和22个JSP页面另含12个JAR依赖库以及CSS、JS、SQL等配置与脚本资源压缩后约6.14MB数据库脚本可快速初始化环境。目前已有43人学习下载。整套资料包含完整可运行源码和数据库能帮助读者理清Servlet与JDBC的交互、MVC分层和后台管理页面的实现思路可作为毕业设计蓝本也可在此基础上进行二次开发与功能扩展。1. 基于jspservlet的在线考试管理系统毕业设计选题的完整落地样本如果你正在为毕业设计选题发愁或者想快速理解jspservlet这种传统Java Web项目是怎么组织起来的这套在线考试管理系统是一个很好的参考样本。它不是一个只有登录注册的空壳而是把“学生在线答题、交卷后查看错题、管理员维护题目和试卷、角色权限分配”这一整条链路做完了前端用jspjquerybootstrap后端就是servletjdbc没有Spring那套复杂的东西逻辑全部暴露在明面上很适合用来做课程设计或毕业设计的基础框架。你需要关注的核心问题是这套代码能不能跑通、数据库脚本怎么导入、Tomcat部署有哪些坑、往上加功能容不容易。2. 技术栈梳理jspservletjdbc 的选型逻辑与三层架构边界2.1 为什么这种“过时”组合反而适合做毕设现在很多课程已经不讲jsp了但打开各大毕设选题库基于jsp的毕设选题依然占相当比例。原因是它的技术边界清晰jsp负责页面展示servlet负责接收请求和跳转jdbc负责数据库操作三层之间没有Spring那种自动装配的黑匣子每一个请求从浏览器发出到数据库返回结果的过程都可以在代码里跟踪到。对于答辩来说这种项目反而好讲清楚。这套系统的请求流转是典型的jspservlet结构浏览器访问jsp页面页面里的表单或超链接提交到servletservlet里用jdbc操作MySQL数据库拿到结果后通过request.setAttribute传回jsp再forward或redirect到目标页面。所有的Java代码都集中在src目录下的servlet类和dao类里jsp目录下则按学生端和管理员端做了划分。2.2 数据库设计登录、试卷、题库、答题记录的角色划分从功能反推表结构这套系统至少需要五张表用户表用于学生和管理员的登录验证角色表用于区分权限试题表用于存放题干、选项和标准答案试卷表用于把多道题目组织成一套卷答题记录表用于保存学生的提交内容和判错结果。角色和用户之间通过角色id关联试卷和试题之间通过试卷id关联。建表时有个细节值得留意试题表除了题干和四个选项还要有一个字段标记标准答案同时有一个锁定状态字段锁定后题目不可用。管理员端项目里已经内置了关键词搜索功能所以在表设计时要考虑后续的模糊查询需求题目标题和试卷名称字段建议建普通索引。MySQL字符集统一使用utf8mb4不然中文选项存进去后查询出来乱码的概率极大。数据库脚本一般会附带在源码包的doc目录或sql目录下导入时直接source执行即可。如果你拿到的版本里没有初始化数据那就需要手动构造一套演示数据三五个学生账号、一个管理员账号、两三套试卷、每套试卷十到十五道题这样演示时才不会显得空。2.3 JDBC连接的常见写法和连接失败的真正原因这套系统的数据访问层用的是原生JDBC常见做法是写一个DBUtil类里面用静态代码块加载驱动再提供一个获取Connection的方法。很多新手抄代码时只搬了Class.forName那三行却忽略了mysql驱动jar包是否放进了WEB-INF/lib目录这是连不上数据库的头号原因。public class DBUtil { private static final String DRIVER com.mysql.jdbc.Driver; private static final String URL jdbc:mysql://localhost:3306/exam_db?useUnicodetruecharacterEncodingutf8; private static final String USER root; private static final String PASSWORD 123456; static { try { Class.forName(DRIVER); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public static Connection getConnection() throws SQLException { return DriverManager.getConnection(URL, USER, PASSWORD); } public static void close(Connection conn, PreparedStatement ps, ResultSet rs) { if (rs ! null) { try { rs.close(); } catch (SQLException ignored) {} } if (ps ! null) { try { ps.close(); } catch (SQLException ignored) {} } if (conn ! null) { try { conn.close(); } catch (SQLException ignored) {} } } }逻辑说明静态代码块只执行一次保证驱动只注册一次getConnection每次调用都创建一个新连接虽然效率不高但对于课程设计这种低并发场景完全够用。close方法按照先ResultSet再PreparedStatement最后Connection的顺序关闭避免资源泄漏。参数说明URL里的useUnicode和characterEncoding是中文不乱码的关键characterEncoding指定为utf8后数据库连接层面就不会出现简体中文显示成问号的问题。USER和PASSWORD根据你自己的MySQL配置修改注意MySQL 5.7默认的root密码和你本地可能不一致第一件事就是核对这两项。这个类的包名一般是com.xxx.util你再把具体包名替换到import里就行。这里有一个很容易翻车的地方MySQL 8.x的驱动类名已经变成了com.mysql.cj.jdbc.DriverURL还得加上serverTimezone参数。这套项目环境是MySQL 5.7和JDK 1.8如果你本机装的是MySQL 8直接用原脚本大概率会报连接失败。我一般会换成JDBC驱动的兼容写法见上方代码注释。2.4 servlet生命周期在答题场景中的体现servlet在项目里承担的是控制器角色。你可能被问到“servlet生命周期是什么”答案是init、service、destroy三个阶段。在答题场景中init在Tomcat启动后第一次访问servlet时执行用于初始化一些全局数据service每次请求都会执行用于分发get和post请求。WebServlet(/exam) public class ExamServlet extends HttpServlet { Override public void init() throws ServletException { // 初始化试卷列表可以加载到application作用域避免每次查询 System.out.println(ExamServlet初始化加载试卷列表); } Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String action request.getParameter(action); if (list.equals(action)) { request.getRequestDispatcher(/student/examList.jsp).forward(request, response); } else if (start.equals(action)) { // 根据试卷id加载试题存到session里 } } Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }逻辑说明doGet和doPost都走同一个分发方法是为了前端提交方式不一致时不会出现405错误。action参数是这些老项目的通用做法相当于一个简易的路由。init阶段在当前项目里被用来做初始化加载你可以改成从数据库加载试卷列表到application范围减少后续访问数据库的次数。参数说明WebServlet注解是Servlet 3.0以后支持的写法Tomcat 7.0.73完全兼容不需要再在web.xml里配置servlet映射。如果你的Tomcat版本低于7就只能在web.xml里手动配置了。这里的url-pattern是/exam所以页面里提交或跳转的路径必须是contextPath /exam 参数经常有人在jsp里少写了contextPath导致404。提示仔细检查jsp里链接的写法。老项目里最常见的问题是c:url或者request.getContextPath()没写全浏览器地址栏直接变成localhost:8080/exam?actionlist而不是localhost:8080/项目名/exam?actionlistTomcat会给你一个404。3. 学生端在线答题错题回顾核心链路的实现拆解3.1 在线答题的会话控制倒计时、进度条和实时作答记录在线答题是这套系统最核心的学生端功能。从交互上看学生从试题列表选择一套试卷点击开始答题页面右上角出现倒计时和答题进度每答完一题进度实时刷新全部答完点击最下方的交卷按钮提交。这里的实现难点其实是两个问题每道题之间的跳转是刷新页面还是局部刷新倒计时是前端递减还是依赖服务器时间。从这套系统的技术栈看它采用的是jQuery局部刷新方案。答题页面加载第一题点击“下一题”时通过jQuery的ajax请求把当前题的作答选项传到servletservlet返回下一题的题干和选项页面用jQuery更新题干区域和选项区域。进度条则是根据当前题目序号和总题数计算百分比用jQuery设置bootstrap进度条的width属性。// 答题卡上方进度条更新 function updateProgress(current, total) { var percent Math.round(current / total * 100); $(.progress-bar).css(width, percent %).text(percent %); } // 点击下一题时发送当前选项并获取下一题 function nextQuestion(examId, paperId, currentIndex) { var selected $(input[nameanswer]:checked).val(); if (!selected) { alert(请先选择答案); return false; } $.ajax({ url: contextPath /exam?actionnextQuestion, type: POST, dataType: json, data: { examId: examId, paperId: paperId, currentIndex: currentIndex, answer: selected }, success: function(res) { if (res.hasNext) { // 更新题干、选项和进度条 $(#questionTitle).text(res.title); $(#optionA).text(res.optionA); $(#optionB).text(res.optionB); $(#optionC).text(res.optionC); $(#optionD).text(res.optionD); $(#currentIndex).val(res.currentIndex); updateProgress(res.currentIndex, res.total); $(input[nameanswer]).prop(checked, false); } else { // 已经是最后一题提示交卷 $(#submitBtn).show(); } } }); }逻辑说明把当前选择的答案随请求带到servletservlet连同学生的作答一起存入答题记录表这样即使答题中途浏览器崩溃也不会丢数据。success回调里根据返回的hasNext字段决定是更新题目还是显示交卷按钮更新时使用了jQuery的prop方法重置radio选中状态避免上一题的选中痕迹残留。参数说明contextPath是你在jsp页面顶部定义的全局变量等于request.getContextPath()ajax请求必须带这个前缀否则路径会错。dataType使用json因此服务端要通过Gson或fastjson把结果序列化后再写出。数据类参数里examId代表一次答题任务的idpaperId代表试卷idcurrentIndex表示当前题号初次加载时默认为0。发请求时建议不要传明文答案否则抓包就能看到正确答案更好的做法是只传选项下标在service层再做比对。3.2 交卷判分与错题标记的数据库操作交卷逻辑比常见的一提交就显示总分要复杂一点。这套系统的实现是用户点击交卷后servlet把所有已保存的作答记录取出来与试题表里的标准答案逐题比对把结果更新到答题记录表然后跳转到结果页。结果页里错题用红色标记正确答案用绿色标记方便复习。// 判分核心逻辑逐题比对并生成错题列表 ListAnswerRecord records answerDao.findRecordsByExamId(examId); for (AnswerRecord record : records) { Question q questionDao.findById(record.getQuestionId()); boolean isCorrect (record.getUserAnswer() ! null record.getUserAnswer().equals(q.getCorrectAnswer())); record.setCorrect(isCorrect); if (!isCorrect) { // 收集错题信息用于结果页展示 wrongList.add(record); } answerDao.updateCorrectStatus(record.getId(), isCorrect); } request.setAttribute(wrongList, wrongList); request.setAttribute(totalCount, records.size()); request.getRequestDispatcher(/student/result.jsp).forward(request, response);逻辑说明先按examId查出所有作答记录id说明一次答题任务产生一批记录。然后循环里每次查询试题表用当前记录的userAnswer和标准答案的correctAnswer做equals比较。比较结果更新回答题记录表这样错题状态是持久化保存的学生退出后重新登录还能看到错题历史。wrongList只收集错误记录最终传给结果页面渲染。参数说明examId在开始答题时就生成是一个自增idsession里保存的关联信息也需要对应。userAnswer存的是选项文本比如“A”或“B”而correctAnswer也是同样的格式这要求建表时两者的字段类型和长度保持一致否则取出时带空格或大小写不一致会导致比对失败。常见坑是数据库中题目选项带了HTML标签答案文本比对时出现前后空格这属于脏数据问题。3.3 倒计时的前端实现和服务端兜底倒计时这块新手容易直接写一个JavaScript的setInterval每秒递减。但这里有一个实际问题如果学生切到别的页面待了十分钟再回来前端计时器会被浏览器节流甚至完全暂停。真正能兜底的做法是在开始答题时记录服务端时间前端倒计时只做展示交卷时服务端再校验是否超时。// 倒计时初始化从服务端下发的剩余秒数开始 var remainSeconds parseInt($(#remainSeconds).val(), 10); var timer setInterval(function() { remainSeconds--; if (remainSeconds 0) { clearInterval(timer); alert(答题时间到系统自动交卷); $(#examForm).submit(); } else { var minutes Math.floor(remainSeconds / 60); var seconds remainSeconds % 60; $(#timeLabel).text(minutes 分 (seconds 10 ? 0 : ) seconds 秒); } }, 1000);逻辑说明remainSeconds从服务端下发的隐藏域读取初始值是试卷的时长限制。每秒减一刷新页面时重新获取剩余时间。到零时直接提交表单触发后端的自动交卷逻辑避免给恶意用户留出“前端绕过倒计时”的漏洞。参数说明隐藏域的value在jsp里用el表达式或者jstl标签写入来源可以是session中存储的考试开始时间。如果试卷未设置时长限制默认可以给一个120分钟的标准值小时级别的倒计时状态恢复不会造成明显延迟。setInterval的返回值要保存到变量里否则页面跳转前无法清除会出现多个计时器并发递减的bug。4. 管理员端题目、试卷、角色三条配置链路4.1 题目管理的增删改查与数据校验细节题目管理是管理员端最高频的操作页面涉及题目的增删改查、按关键词搜索、题干和选项编辑、标准答案设置、锁定状态切换。这里的关键在于题目表结构里题干用大字段存储四个选项用四个短文本字段标准答案是一个单字符字段锁定状态是一个tinyint字段0表示可用1表示锁定。新增或修改题目时要做的校验逻辑是题干不能为空至少两个选项不能为空标准答案必须是A到D中的一个。这套系统里校验逻辑是放在servlet里用一堆if判断来写的。实际项目中我建议也做前端校验两个地方都校验减少无效数据进库的可能。// 新增或修改题目处理 String title request.getParameter(title); String optionA request.getParameter(optionA); String optionB request.getParameter(optionB); String optionC request.getParameter(optionC); String optionD request.getParameter(optionD); String correctAnswer request.getParameter(correctAnswer); String isLocked request.getParameter(isLocked); if (title null || title.trim().isEmpty()) { request.setAttribute(errorMsg, 题干不能为空); request.getRequestDispatcher(/admin/questionEdit.jsp).forward(request, response); return; } if (correctAnswer null || !ABCD.contains(correctAnswer)) { request.setAttribute(errorMsg, 标准答案必须是A、B、C、D中的一个); request.getRequestDispatcher(/admin/questionEdit.jsp).forward(request, response); return; } Question q new Question(); q.setTitle(title.trim()); q.setOptionA(optionA.trim()); q.setOptionB(optionB.trim()); q.setOptionC(optionC.trim()); q.setOptionD(optionD.trim()); q.setCorrectAnswer(correctAnswer); q.setLocked(1.equals(isLocked)); boolean ok questionDao.insertOrUpdate(q);逻辑说明先把页面表单参数全部取出来逐项做非空和合法性校验任何一项不满足就直接转发回编辑页面并带上errorMsg提示。用trim方法去掉用户误输的首尾空格。校验通过后封装成Question对象调用dao层的insertOrUpdate方法。这里insert和update判断的是questionId参数是否为空为空走插入不为空走更新。参数说明correctAnswer这里用了字符串contains的判断方式如果correctAnswer是nullcontains方法会返回true先把null排除再判断是否属于ABCD集合。isLocked参数来自下拉框或单选按钮值为1时锁定否则可用。页面上编辑按钮的href需要携带questionId查询按钮的表单method必须是get才能把keyword参数拼到URL里供servlet取用。4.2 试卷管理的组卷方式名称传入和题量映射试卷管理的核心操作是增删改查和关键词搜索新增一条试卷记录时填入试卷名称和题目数量。这套系统的组卷方式比较轻量试卷表并不实际存储题目列表而是通过试题表里的paper_id字段关联。你新建一张试卷后会自动生成一个试卷id然后往试卷里添加题目时把题目的paperId字段更新为该试卷的id即可。这种设计的问题在于删除试卷时容易产生孤儿数据。如果直接从试卷表删除记录而试题表里的paperId还指向已经被删除的试卷id学生端就可能出现试卷查询不到详情的情况。我的处理习惯是删除试卷前先执行一条update语句把该paperId下的所有试题的paperId置为null再删除试卷记录保持引用完整。-- 删除试卷前先释放关联题目 UPDATE question SET paper_id NULL WHERE paper_id #{paperId}; -- 解除关联后再删除试卷 DELETE FROM paper WHERE id #{paperId};逻辑说明两条SQL必须放在一个事务里执行否则中途出错会出现一部分题目被置空而试卷仍然存在的脏状态。在dao层的deletePaper方法里先打开连接调用setAutoCommit(false)执行完两条update和delete后commit再在finally块里恢复autoCommit并关闭连接。参数说明SQL中的#{}是MyBatis的占位符写法这个项目是原生JDBC的话你需要改成PreparedStatement的?占位符再通过setInt绑定paperId。手动操作MySQL时setAutoCommit(false)后如果忘了commit数据不会真正写入这是事务操作里最容易踩的坑。4.3 角色管理与权限分配的实现思路角色管理部分支持角色信息的增删改查和权限分配这是快速评分点时容易得分的一块。核心表设计是用户表持有roleId角色表持有权限描述。学生登录后只能看到在线答题和错题回顾两个入口管理员登录后能看到题目管理、试卷管理、系统功能管理、用户管理和角色管理五个入口。登录页面根据roleId跳转到不同首页这是jsp里最常见的分支逻辑先判断session里loginUser的roleId等于管理员角色值时跳转到admin/index.jsp否则跳转到student/index.jsp。有些项目会直接用过滤器来拦截未登录用户访问管理端页面如果这套系统的源码里没有过滤器建议你自己补一个LoginFilter优先级放到最高避免未登录状态直接访问管理员页面报500。WebFilter(urlPatterns {/admin/*, /student/*}) public class LoginFilter implements Filter { Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req (HttpServletRequest) request; HttpServletResponse resp (HttpServletResponse) response; Object loginUser req.getSession().getAttribute(loginUser); if (loginUser null) { resp.sendRedirect(req.getContextPath() /login.jsp); return; } chain.doFilter(request, response); } }逻辑说明通过注解拦截admin和student两个路径前缀所有进入这两个目录的请求都会先经过过滤器。如果session里没有loginUser就重定向到登录页有则放行。这个过滤器能顺手解决两件事一是未登录用户直接访问管理页面二是学生访问管理页面被拦截权限控制在路径层面就完成了一层。参数说明/admin/*和/student/*是路径通配中间注意不要漏掉斜杠花号组合。如果是tomcat7WebFilter注解同样受支持。过滤器里放行的代码chain.doFilter必须写在最后否则过滤器链会提前打断导致后端servlet无法收到请求。5. 部署与避坑IDEA 2021.3 Tomcat 7 MySQL 5.7 环境下的常见问题排查5.1 从导入源码到浏览器访问的完整部署步骤拿到源码包后不要急着用IDEA打开先把部署顺序理一遍。第一步在MySQL中执行源码包里的sql脚本生成数据库和表结构。第二步解压源码包在IDEA里通过File Open选择项目目录等待Maven或普通项目结构识别完成。如果没有pom.xml说明这是一个普通Web项目要右键点击项目选择Add Framework Support勾选Web Application把Web Resource Directory指定到WebContent或webapp目录。第三步在Project Structure里设置Artifacts把项目打成war exploded再配置Tomcat local设置Deployment为这个exploded目录。第四步修改数据库连接配置启动Tomcat访问登录页。5.2 踩坑实录六条真实遇到过的部署问题问题一Tomcat启动时报ClassNotFoundException: com.mysql.jdbc.Driver。现象是控制台在启动阶段出现驱动类找不到的错误。原因是MySQL驱动jar包没有放到WEB-INF/lib目录下IDEA里即使添加了Libraries部署到Tomcat时也可能不会自动拷贝。解决方法是确认Project Structure Artifacts Output Layout里lib下包含了mysql-connector-java的jar然后重新构建项目。问题二jsp页面中文全部变成问号。现象是浏览器里显示题目内容没乱码但后台录入的中文数据在页面显示为?。原因是数据库表的字符集不是utf8mb4大概率是当时的建表语句少了DEFAULT CHARSETutf8mb4。解决方法是对已存在的表执行ALTER TABLE question CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci同时确认jsp页面开头的pageEncoding也设置为utf8。问题三登录成功后跳转404。现象是浏览器地址是正确的项目路径但页面找不到。原因是跳转用的路径没有加contextPath比如request.getRequestDispatcher(/admin/index.jsp)在根路径部署时没问题但war包部署时项目名就是上下文根jsp路径必须拼上contextPath。解决方法是统一使用request.getContextPath()拼接或者在response.sendRedirect里加上contextPath。问题四答题页面刷新后回到第一题。现象是学生答到第十题时按F5刷新页面回到第一题。原因是session中的当前题号和已选答案只在内存里刷新动作触发了重新加载试卷列表的请求。解决方法是把当前题号存到session的attribute里加载题目时先检查session中是否已有记录。问题五管理员修改题目后学生端看到的还是旧答案。现象是题目内容改了但在线答题时显示的还是修改前的题干。原因是题目列表查询时加了浏览器缓存Tomcat返回304导致实战数据没有重新拉取。解决方法是在jsp页面的response头部加Cache-Control: no-cache或者查询时给SQL加一个时间戳条件。问题六Tomcat 7在JDK 1.8环境下出现内存溢出。现象是频繁部署重启后Tomcat报java.lang.OutOfMemoryError: PermGen space。原因是Tomcat 7的默认永久代大小只有几十MB多次热部署后classLoader泄漏。解决方法是在Tomcat的catalina.bat或catalina.sh的JAVA_OPTS里增加-XX:MaxPermSize256m如果是JDK 8以上还需要确认使用的是Metaspace而不是PermGen。提示IDEA里配置Tomcat时在VM options中写入-XX:PermSize64m -XX:MaxPermSize256m能让开发期频繁重启更稳定。另外如果你的机器装的Tomcat 10它默认是Jakarta EE命名空间servlet和jsp的包名都变了这套系统的代码大概率跑不起来直接用Tomcat 9以下比较稳妥。5.3 端口占用和热部署失败的规避技巧端口占用是开发期最常见的问题。8080端口被其他进程占用时IDEA里部署时会提示Address already in use。多数情况下使用命令netstat -ano | findstr 8080然后按住PID在任务管理器里结束进程。更推荐的做法是给本机的Tomcat单独设置一个不常用的端口比如8888在IDEA的Tomcat Server配置页修改HTTP port顺便把JMX port也改掉避免与其他项目的端口冲突。热部署失败的本质是资源文件没有被同步到目标的classes或webroot目录。IDEA中如果是普通web项目修改了jsp后需要手动执行Build Recompile修改了Java文件后要重新Artifacts只点浏览器刷新往往不生效。我一般习惯把Tomcat的on frame deactivation设置为Update resources并把build project automatically打开虽然会消耗一点CPU但能省去大量“改完没生效”的排查时间。6. 进阶改动把这套源码升级成能拿出手的毕业设计作品6.1 把JDBC裸连改成Tomcat连接池原生JDBC每次都要创建和销毁连接虽然毕设答辩时不一定会被追问性能但面试官大概率会问“你项目里是怎么管理数据库连接的”。最轻量的修改是使用Tomcat自带的JDBC连接池在META-INF/context.xml配置一个数据源在DAO里通过JNDI获取连接代码改动量很小。Context Resource namejdbc/examDB authContainer typejavax.sql.DataSource maxActive20 maxIdle8 maxWait10000 usernameroot password123456 driverClassNamecom.mysql.jdbc.Driver urljdbc:mysql://localhost:3306/exam_db?useUnicodetrueamp;characterEncodingutf8/ /Context逻辑说明maxActive表示最大活跃连接数maxIdle控制在空闲时最多保留的连接maxWait是请求连接时最长等待毫秒数超出后抛超时异常。driverClassName继续使用MySQL 5.7的这个类名URL里注意XML的符号必须改写成。使用JNDI获取连接后DBUtil要调整把原来DriverManager.getConnection的写法替换成从DataSource中取连接。这种改造方式在答辩里很好解释你也可以顺带引出“数据库连接池的作用”这个问题展示你对性能优化有基本认知。6.2 给项目加一个统一异常的JSP错误页老项目中jsp报错时经常抛出黄底的异常堆栈这在实际演示时非常不体面。在web.xml里配一个error-page把500和404都指向一个美观的错误提示页能显著提升演示观感。注意这个项目里如果是你自己配置了过滤器拦截到异常可以记录到日志中同时提示用户“系统开小差了请稍后重试”而不是把SQL异常直接抛给浏览器。6.3 演示前的检查清单与解说路径演示毕设前我建议你按这个顺序过一遍先用管理员账号录一套10道题左右的试卷再建五个学生账号然后用学生账号跑一遍完整的答题流程确认倒计时、进度条、交卷、错题标记都正常。把项目里自带的示例数据清空换一套与毕设主题匹配的题目数据这一步是防止演示时出现与论文题目无关的内容。答辩时从“登录重定向到不同首页”开始讲把请求经过servlet再到jdbc返回这一条线串联起来扩展部分讲你改造的连接池和过滤器。从那以后我每拿到一套jspservlet源码都会先检查它的数据库连接方式和路径处理不再盲目点击运行按钮。因为毕设项目翻车多半不是功能写不出来而是部署环节的环境差异没有提前铺平。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑