基于Servlet和JSP的在线Quiz开发:如何获取用户选中的答题选项
解决Servlet/JSP在线Quiz的选项获取与结果存储问题
看起来你现在卡在两个核心问题上:单页展示题目时拿不到用户选中的选项,还有之前尝试分页展示题目没成功。我来一步步帮你理清思路、解决问题。
一、当前单页Quiz的核心错误分析
你的代码里有几个关键问题直接导致无法获取用户选项:
- 重复生成
<form>标签:在while循环里每输出一道题就生成一个表单,这会让HTML结构无效,浏览器只会识别最后一个表单,前面的选项根本不在提交范围内。 - Radio组name重复:所有题目的单选框都用了
name="answer",这会把所有选项归为同一组,用户只能选一个选项,而不是每个题目独立选择。 - 获取参数时机错误:你在生成题目的Servlet里尝试
request.getParameter("answer"),但此时用户还没提交表单,这个参数根本不存在——应该在处理提交的Results.jsp或者专门的结果Servlet里获取。
二、修正单页Quiz的代码实现
1. 调整Servlet的表单生成逻辑
把<form>标签移到循环外面,确保整个页面只有一个表单;给每个题目的单选框组设置唯一的name(比如answer_${i}),同时把题目和正确答案存入session时,和这个序号一一对应。
修改后的Servlet doPost 方法:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String url = "jdbc:mysql://127.0.0.1:3306/Quiz"; String username1="root"; String password1="root"; PrintWriter out= response.getWriter(); PreparedStatement st = null; ResultSet results = null; int limit=3; HttpSession session = request.getSession(); // 确保获取session对象 try { Class.forName("com.mysql.jdbc.Driver"); Connection con= DriverManager.getConnection(url,username1,password1); String sql="SELECT Questions.Question, Questions.option1, Questions.option2,Questions.option3, Questions.option4,Questions.correctanswer FROM Questions order by RAND() limit ?"; st = con.prepareStatement(sql); st.setInt(1,limit); results = st.executeQuery(); // 先输出页面头部和表单开始标签 out.println("<HTML><BODY BGCOLOR='powderblue'>"); out.println("<FORM method='post' action='Results.jsp'>"); out.println("<TABLE BORDER = 2 CELLPADDING = 4 CELLSPACING = 2>"); out.println("<TR><TD COLSPAN = 6 ALIGN = CENTER><H2><B>Quick Quiz</B></H2></TD></TR>"); int i=1; while (results.next()) { String question = results.getString(1); String opt1 = results.getString(2); String opt2 = results.getString(3); String opt3 = results.getString(4); String opt4 = results.getString(5); String correctAns = results.getString(6); // 输出带序号的题目 out.println("<TR><TD>" + i + ". " + question + "</TD></TR>"); // 输出选项,单选框name用answer_+序号,确保每组独立 out.println("<TR><TD><input type='radio' name='answer_" + i + "' value='1' required> " + opt1 + "</TD></TR>"); out.println("<TR><TD><input type='radio' name='answer_" + i + "' value='2'> " + opt2 + "</TD></TR>"); out.println("<TR><TD><input type='radio' name='answer_" + i + "' value='3'> " + opt3 + "</TD></TR>"); out.println("<TR><TD><input type='radio' name='answer_" + i + "' value='4'> " + opt4 + "</TD></TR>"); out.println("<TR><TD> </TD></TR>"); // 空行分隔题目 // 将题目和正确答案存入session,用序号区分 session.setAttribute("question_" + i, question); session.setAttribute("correct_answer_" + i, correctAns); i++; } // 输出提交按钮和页面收尾标签 out.println("</TABLE>"); out.println("<BR><BR><INPUT type='submit' value='Press to Submit'></FORM></BODY></HTML>" ); results.close(); st.close(); con.close(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } }
2. 在Results.jsp中处理提交并存储结果
现在在结果页面,你可以获取每个题目的选中选项,对比正确答案,然后把结果存入数据库。示例代码如下:
<%@ page import="java.sql.*" %> <%@ page import="javax.servlet.http.HttpSession" %> <html> <body> <h2>Quiz Results</h2> <% HttpSession session = request.getSession(); int totalQuestions = 3; int score = 0; // 这里替换成实际的用户名,比如用户登录后存入session的用户名 String username = "test_user"; // 数据库连接信息 String url = "jdbc:mysql://127.0.0.1:3306/Quiz"; String dbUser = "root"; String dbPass = "root"; Connection con = null; PreparedStatement stmt = null; try { Class.forName("com.mysql.jdbc.Driver"); con = DriverManager.getConnection(url, dbUser, dbPass); // 假设你有一个quiz_results表,字段:username, question, user_answer, is_correct String insertSql = "INSERT INTO quiz_results (username, question, user_answer, is_correct) VALUES (?, ?, ?, ?)"; stmt = con.prepareStatement(insertSql); for(int i=1; i<=totalQuestions; i++){ String question = (String)session.getAttribute("question_" + i); String correctAns = (String)session.getAttribute("correct_answer_" + i); String userAns = request.getParameter("answer_" + i); boolean isCorrect = correctAns.equals(userAns); if(isCorrect) score++; // 插入结果到数据库 stmt.setString(1, username); stmt.setString(2, question); stmt.setString(3, userAns); stmt.setBoolean(4, isCorrect); stmt.executeUpdate(); // 展示每题结果 out.println("<p>" + i + ". " + question + "<br>"); out.println("Your answer: Option " + userAns + "<br>"); out.println("Correct answer: Option " + correctAns + "<br>"); out.println(isCorrect ? "<span style='color:green'>Correct!</span>" : "<span style='color:red'>Incorrect!</span></p>"); } out.println("<h3>Total Score: " + score + "/" + totalQuestions + "</h3>"); } catch(Exception e){ e.printStackTrace(); } finally { if(stmt != null) stmt.close(); if(con != null) con.close(); // 清理session中的临时数据 for(int i=1; i<=totalQuestions; i++){ session.removeAttribute("question_" + i); session.removeAttribute("correct_answer_" + i); } } %> </body> </html>
三、可选:实现分页式Quiz(单页一题+Next按钮)
如果你想回到分页的思路,这里给你一个简单的实现方向:
- 初始化题目列表:第一次访问Servlet时,从数据库获取随机题目,存入session(比如
session.setAttribute("all_questions", 题目列表)),同时记录当前题目索引session.setAttribute("current_index", 0)。 - 处理答题提交:用户点击Next时,提交当前题目的答案,存入session(比如
session.setAttribute("answer_" + currentIndex, userAns)),然后索引+1。 - 判断是否完结:如果还有下一题,展示新题目;如果没有,跳转到结果页面计算得分并存储。
核心逻辑示例(需要先创建Question实体类封装题目信息):
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { HttpSession session = request.getSession(); List<Question> allQuestions = (List<Question>)session.getAttribute("all_questions"); Integer currentIndex = (Integer)session.getAttribute("current_index"); // 第一次请求,初始化题目列表 if(allQuestions == null){ // 从数据库查询随机题目,封装成Question对象存入列表 // ... 这里写数据库查询逻辑 session.setAttribute("all_questions", allQuestions); currentIndex = 0; session.setAttribute("current_index", currentIndex); } else { // 保存当前题目的答案 String userAns = request.getParameter("current_answer"); session.setAttribute("answer_" + currentIndex, userAns); currentIndex++; session.setAttribute("current_index", currentIndex); } // 判断是否还有题目 if(currentIndex < allQuestions.size()){ // 展示当前题目 Question currentQ = allQuestions.get(currentIndex); PrintWriter out = response.getWriter(); out.println("<HTML><BODY BGCOLOR='powderblue'>"); out.println("<FORM method='post' action='QuizServlet'>"); out.println("<h2>Question " + (currentIndex+1) + "/" + allQuestions.size() + "</h2>"); out.println("<p>" + currentQ.getQuestion() + "</p>"); out.println("<p><input type='radio' name='current_answer' value='1' required> " + currentQ.getOpt1() + "</p>"); out.println("<p><input type='radio' name='current_answer' value='2'> " + currentQ.getOpt2() + "</p>"); out.println("<p><input type='radio' name='current_answer' value='3'> " + currentQ.getOpt3() + "</p>"); out.println("<p><input type='radio' name='current_answer' value='4'> " + currentQ.getOpt4() + "</p>"); out.println("<input type='submit' value='Next'>"); out.println("</FORM></BODY></HTML>"); } else { // 所有题目答完,跳转到结果页面 response.sendRedirect("Results.jsp"); } }
总结
先把单页版本的表单结构和单选框name修正,确保每个题目的选项组独立,然后在结果页面正确获取参数并存储。如果想做分页,核心是用session维护题目列表和答题进度,逐步处理每个题目的提交。
内容的提问来源于stack exchange,提问作者Anonymous6
相关产品推荐
相关产品推荐

