【web考试系统的设计】
文章目录
- 一、实验背景与目的
- 二、实验设计与实现思路
- 1. 功能架构
- 2. 核心代码实现
- 总结
一、实验背景与目的
本次实验旨在深入理解Request、response对象的作用,Request对象的作用是与客户端交互,收集客户端的Form、Cookies、超链接,或者收集服务器端的环境变量。客户端可通过表单或在网页地址后面提供参数的方法提交数据,然后服务器通过Servlet控制器获得request对象封装的这些数据,经过逻辑运算后利用Response对象发送信息给用户,完成对客户端的动态响应,掌握基于Servlet的动态Web工程框架的搭建,熟悉Request、Response等内置对象在JSP编程中的运用
二、实验设计与实现思路
1. 功能架构
(1)考试页面(test.jsp)
表单结构:
5 道单选题采用,每个题目设置唯一name属性(如 “1”、“2”),确保后端能精准获取对应答案。
提交按钮绑定action=“test.do”,指定请求路径为 Spring MVC 映射的控制器。
用户体验:
题干使用 空格符优化排版,确保选项对齐;重置按钮type="reset"方便用户重新答题。
(2)评分页面(grade.jsp)
动态渲染:通过 EL 表达式${score}直接获取控制器传递的分数,避免 Java 代码嵌入页面,保持视图纯净。
样式优化:使用 CSS 类.center居中显示分数,红色加粗字体突出成绩,提升视觉反馈。
2. 核心代码实现
(1)web.xml配置
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"><display-name>test8</display-name><welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list><servlet><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class></servlet><servlet-mapping><servlet-name>myspringmvc</servlet-name><url-pattern>*.do</url-pattern></servlet-mapping>
</web-app>
(2)Servlet逻辑
package com.jmu.controller;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;public class Controller1 extends AbstractController {@Overrideprotected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {String key1 = request.getParameter("1");String key2 = request.getParameter("2");String key3 = request.getParameter("3");String key4 = request.getParameter("4");String key5 = request.getParameter("5");String rightkey1 = "C";String rightkey2 = "A";String rightkey3 = "C";String rightkey4 = "D";String rightkey5 = "C";int score = 0;if (rightkey1.equals(key1)) {score+=20;}if (rightkey2.equals(key2)) {score+=20;}if (rightkey3.equals(key3)) {score+=20;}if (rightkey4.equals(key4)) {score+=20;}if (rightkey5.equals(key5)) {score+=20;}ModelAndView modelAndView=new ModelAndView("grade");modelAndView.addObject("score", score);return modelAndView;}}
(3)JSP页面
1.test.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>测试页面</title>
</head>
<body>
<form id="form1" name="form1" method="post" action="test.do"><h2>C语言标准化测试</h2><p>1.C语言程序是由(  )构成的。</p><input type="radio" name="1" value="A">A) 一些可执行的语言 <input type="radio" name="1" value="B">B) main函数 <input type="radio" name="1" value="C">C) 函数 <input type="radio" name="1" value="D">D) 包含文件中的第一个函数 <p>2.(  )是构成C语言程序的基本单位。</p><input type="radio" name="2" value="A">A) 函数 <input type="radio" name="2" value="B">B) 过程 <input type="radio" name="2" value="C">C) 子程序 <input type="radio" name="2" value="D">D) 子例程 <p>3.C语言可执行程序从(  )开始执行。</p><input type="radio" name="3" value="A">A) 程序中第一条可执行语句 <input type="radio" name="3" value="B">B) 程序中第一个函数&emsp<p>4.C语言程序从main( )函数开始执行,所以这个函数要写在(  )。</p><input type="radio" name="4" value="A">A) 程序文件的开始 <input type="radio" name="4" value="B">B) 程序文件的最后 <input type="radio" name="4" value="C">C) 它调用的函数的前面 <input type="radio" name="4" value="D">D) 程序文件的任何位置 <p>5.以下说法中正确的是(  )。</p><input type="radio" name="5" value="A">A) C语言程序总是从第一个定义的函数开始执行 <input type="radio" name="5" value="B">B) 在C语言程序中,要调用的函数必须在main( )函数中定义 <p><input type="radio" name="5" value="C">C) C语言程序总是从main( )函数开始执行  <input type="radio" name="5" value="D">D) C语言程序中的main( )函数必须放在程序的开始部分 <p>  <input type="reset" name="reset" value="重置"/>  <input type="submit" name="submit" value="提交"/>
</form>
</body>
</html>
2.grade.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>成绩页面</title>
<style>.center {text-align: center;}
</style>
</head>
<body>
<tr><td class="center"><h1 style="color:red;">您本次C语言测试成绩是:${score}分</h1></td>
</tr>
</table>
</body>
</html>
总结
本次实验结果符合预期,当我们选中选项时,后端会进行判断,并进行分数的累加。
最后i显示成绩页面。
- 遇到的问题
- 前端表单
在设计 5 道单选题时,我一度将 radio 的 name 统一写成 “question”,导致后端只能获取最后一个题的答案。调试时发现request.getParameter(“1”)返回 null,才惊觉每个题的 name 必须唯一(如 “1”、“2”)。这个细节让我明白:前端表单的 name 属性是后端数据提取的 “钥匙”,必须与业务逻辑一一对应。 - 逻辑漏洞
当用户未选任何答案直接提交时,request.getParameter(“1”)返回 null,与预设的 “C” 比较导致空指针。通过添加key1 == null ? “未选” : key1的防御性判断,最终在 grade.jsp 显示 “0 分” 而非报错。这教会我:永远假设用户输入是 “恶意” 的,后端必须做好参数校验。
这次实验让我告别 “纸上谈兵”,真正体会到 Web 开发是 “带着镣铐跳舞”—— 既要遵守 HTTP 协议的规则,又要在框架约束中实现创意。那些曾让我头疼的 web.xml 配置、ModelAndView 传参,如今都变成了脑海中清晰的流程图。或许,这就是实践的力量:让抽象的概念,落地成可运行的代码,最终内化为解决问题的能力。