关键词: MVC 、Servlet 、 EL表达式 、 Session 、 作用域(Scope) 、 表单 、 doGet() 、request 、 JSP 、 转发与重定向
MVC
MVC基本概念
MVC(Model-View-Controller)是一种软件架构模式,将应用程序分为三个核心组件:
组件 | 说明 |
---|---|
Model | 处理业务逻辑和数据持久化,代表应用程序的数据和业务规则 |
View | 用户界面层,负责数据的展示和用户交互 |
Controller | 接收用户输入,协调Model和View之间的交互 |
MVC工作流程
例题
MVC只能用Servlet/JSP实现(×)
MVC是一种设计模式,可以用多种技术实现:
- Java:Spring MVC(Controller)+ JSP/Thymeleaf(View)
- PHP:Laravel框架
- JavaScript:Angular/React+Vue(前端MVC)
- Python:Django MTV模式(本质是MVC变体)
在MVC设计模式中,( )负责接收客户的请求数据
A.JavaBean B.Servlet C.HTML D.JSP
正确答案:B.Servlet
解析:
- Servlet是Java Web中标准的控制器组件
- 现代框架中可能是Spring的@Controller或@RestController
- JSP(D)本质属于View层,虽然能接收请求但不符合MVC规范
Servlet
1. Servlet 基础概念
Servlet(Server + Applet)是运行在 Web 服务器(如Tomcat) 上的 Java程序,用于 处理HTTP请求并生成动态响应。
- 核心作用:
- 接收客户端(浏览器)的请求(
HttpServletRequest
)/接受客户的请求数据。 - 处理业务逻辑(如查询数据库)。
- 返回响应(
HttpServletResponse
,如HTML/JSON)。
- 接收客户端(浏览器)的请求(
2. Servlet 核心方法
方法 | 说明 |
---|---|
init() |
Servlet初始化时调用(仅一次) |
service() |
根据请求类型(GET/POST)调用doGet() 或doPost() (由容器自动处理) |
doGet() |
处理HTTP GET请求 |
doPost() |
处理HTTP POST请求 |
destroy() |
Servlet销毁时调用(服务器关闭或Servlet被移除) |
3. Servlet 生命周期
生命周期阶段
- 加载与实例化
- Web容器(如Tomcat)加载Servlet类并调用无参构造器创建实例。
- 初始化(
init()
)- 调用
init(ServletConfig config)
方法,仅执行一次(用于加载资源)。
- 调用
- 处理请求(
service()
→doGet()
/doPost()
)- 每次请求都会调用
service()
方法,并根据请求类型分发到doGet()
或doPost()
。
- 每次请求都会调用
- 销毁(
destroy()
)- 服务器关闭时调用,释放资源(如数据库连接)。
4. 请求处理与作用域
request
vs sendRedirect
request.setAttribute()
+ 转发(forward
)- 数据在同一个请求链中共享(可跨Servlet/JSP)。
response.sendRedirect()
- 发送302重定向,新建请求,原
request
中的数据丢失。
- 发送302重定向,新建请求,原
5. 过滤器(Filter)
过滤器的作用
- 在请求到达Servlet前或响应返回客户端前执行预处理(如权限检查、日志记录)。
- 与Servlet的区别:
- Filter不直接处理请求,而是对请求/响应进行过滤。
- Servlet是请求的最终处理者。
例题
Servlet的doGet()和doPost()方法的两个参数类型是:
- HttpServletRequest和HttpServletResponse 。
Servlet的主要作用是获取请求参数和跳转页面。( √ )
- 正确。Servlet的核心功能是:
- 通过
request.getParameter()
获取请求参数。 - 通过
response.sendRedirect()
或RequestDispatcher
实现页面跳转。 - 除此以外,Servlet还能处理业务逻辑、生成动态内容等。
- 通过
JSP页面的本质也是Servlet。( √ )
- 正确。JSP在部署时会被Web容器(如Tomcat)编译成Servlet(Java类)
给定下面HTML代码:
<html><body><a href=”/servlet/MyServlet”>Click Me</a></body></html>
当用户单击“Cliick Me”链接时,将调用Servlet的( A )方法。
A.doGet() B.doPost() C.Get() D.Post()
- 正确答案:A. doGet()
- 解析:
<a>
标签默认发起的是HTTP GET请求,因此会调用Servlet的doGet()
方法。POST需要通过<form method="post">
触发。
下面有关Servlet的描述错误的是( C )。
A.一个Servlet就是一个Java类
B.Servlet是位于Web服务器内部的服务器端的Java应用程序
C.Servlet可以由客户端的浏览器解释执行
D.加载Servlet的Web服务器必须包含支持Servlet的Java虚拟机
- 正确答案:C. Servlet可以由客户端的浏览器解释执行
- 解析:Servlet在服务器端由JVM执行,浏览器只能接收响应结果(如HTML),无法解释Servlet代码。
Servlet的生命周期由一系列事件组成,把这些事件按先后顺序排列,正确的是( B )。
A.加载类,实例化,请求处理,初始化,销毁
B.加载类,实例化,初始化,请求处理,销毁
C.实例化,加载类,初始化,请求处理,销毁
D.加载类,初始化,实例化,请求处理,销毁
- 正确答案:B. 加载类→实例化→初始化→请求处理→销毁
- 关键步骤:
- 容器加载Servlet类(
.class
文件)。 - 实例创建(调用无参构造器)。
- 初始化(调用
init()
,仅一次)。 - 处理请求(多次调用
service()
及doGet()
/doPost()
)。 - 销毁(调用
destroy()
释放资源)。
- 容器加载Servlet类(
给定一个Servlet的doGet()方法中的代码片段,如下:
request.setAttribute(“name”,”张三”);
response.sendRedirect(“http://localhost:8080/helloweb/my-servlet”);
那么在my-servlet中可以使用( D )方法把属性name的值取出来。
A.String name = request.getAttribute(“name”);
B.String name = (String)request.getAttribute (“name”);
C.Object name = request.getAttribute (“name”);Get()
D.无法取出来
- 正确答案:D. 无法取出来
- 解析:
sendRedirect()
是客户端重定向(响应码302),会发起新的请求,原请求的request
对象及其属性已失效。- 若需传递数据,可用
session
或追加参数到URL(如?name=张三
)。
以下关于过滤器的说法错误的是( D )。
A.是向Web应用程序的请求和响应处理添加功能的Web服务组件
B.Filter不是一个Servlet
C.能够在一个请求request到达Servlet之前预处理request,在离开Servlet时处理response
D.Filter是一个Servlet
- 正确答案:D. Filter是一个Servlet
- 解析:
- Filter与Servlet是并列概念,均实现特定接口,但职责不同:
- Filter:预处理请求(
doFilter()
)、后处理响应。 - Servlet:处理业务逻辑。
- Filter需在
web.xml
或注解中配置URL映射。
简述Servlet的生命周期。
- 加载和实例化:容器加载Servlet类并创建实例
- 初始化:调用init()方法
- 处理请求:调用service()方法,根据请求类型调用doGet()/doPost()
- 销毁:调用destroy()方法释放资源
EL表达式
获取请求作用域request中的名为“uname”的值的EL表达式是
${requestScope.name}
或者${uname}
解析:
${requestScope.uname}
:显式指定从request
作用域获取uname
属性${uname}
:EL 表达式会按照pageScope
→requestScope
→sessionScope
→applicationScope
的顺序自动查找uname
在一个JSP页面中,有表达式<%=’2’+3 %>,它将输出( B )
A.2+3 B.53 C.23 D.不会输出,因为表达式是错误的
解析:
'2'
是一个字符(ASCII 码值为 50),3
是数字,+
运算会先提升'2'
为 ASCII 码值(50),然后计算50 + 3 = 53
- 如果写成
"2" + 3
,则输出"23"
(字符串拼接)
使用JSP脚本定义了变量a,在页面中输出a的正确表达式是( B )
A.<%=a;%>
B.<%=a%>
C.<%==a;%>
D.<%a%>
解析:
- JSP 输出表达式
<%= ... %>
不能加分号;
,因此 B 正确
在JSP页面中,与EL表达式${user.loginName}
等价的是( A )
A.<%=user.getLoginName()%>
B.<% user.getLoginName();%>
C.<%=user.loginName()%>
D.<% user.loginName;%>
解析:
- EL 表达式
${user.loginName}
会自动调用user.getLoginName()
方法(遵循 JavaBean 规范) - A 正确:显式调用
getLoginName()
表达式语言中可使用的隐含变量名
作用域
四种作用域对象对比
作用域 | 范围 | 生命周期 |
---|---|---|
pageContext | 当前JSP页面 | 页面执行期间 |
request | 一次请求(可能含多次转发) | 请求开始到响应完成 |
session | 用户会话(浏览器不关闭) | 会话创建(首次请求)到超时或手动失效 |
application | 整个Web应用(所有用户共享) | 应用启动到停止 |
例题
要将一个名为“student”的对象student存储在会话作用域中语句是
session.setAttribute("student",student)
Session通常情况下存活时间默认是半小时( √ )
应用作用域中存储的数据可以在会话作用域中取出( × )
如果想要实现购物车功能,应该使用下面哪个知识点( B )
A.Filter B.Session C.Response D.application
解析:
购物车功能需要跨多个请求保存用户选择的商品信息,而 Session(会话) 是最适合的机制:
- 会话级存储:Session 在用户整个浏览期间有效,适合保存临时数据(如购物车商品)。
- 用户隔离:每个用户的 Session 独立,避免数据混淆。
- 安全性:Session 数据存储在服务器端,比 Cookie 更安全。
其他选项分析:
- A. Filter(过滤器):
- 用于拦截请求/响应(如权限控制、日志记录),不涉及数据存储。
- C. Response(响应对象):
- 用于向客户端返回数据,无法持久化购物车信息。
- D. Application(ServletContext):
- 全局作用域,所有用户共享数据,不适合存储用户私有的购物车数据。
请求转发(Forward)与响应重定向(Redirect)对比
相同点:均用于页面跳转,跳转逻辑由后端代码决定。
不同点:
对比项 | 请求转发(Forward) | 响应重定向(Redirect) |
---|---|---|
机制 | 服务器内部跳转,客户端无感知 | 服务器返回新地址,客户端重新发起请求 |
URL 变化 | 浏览器地址栏不变 | 浏览器地址栏变为新地址 |
请求次数 | 1 次(服务器内部完成跳转) | 2 次(客户端先请求原地址,再请求新地址) |
数据共享 | 共享同一个request 作用域 |
不共享request ,通过session 或URL 传递 |
HTTP状态码 | 无特殊状态码(对客户端透明) | 302(临时重定向) 或 301(永久重定向) |
在JSP页面中,使用( )对象的( )方法实现请求转发。( A ) |
A.request.getRequestDispatcher()
B. request.getRequestDispatcher().forward()
C.response.sendRedirect()
D.response.sendRequestDispatcher()
解析:
在 JSP 页面中,请求转发(Forward) 是通过 request.getRequestDispatcher()
获取分发器,再调用 forward()
方法实现的。
正确用法:
request.getRequestDispatcher("目标页面.jsp").forward(request, response);
getRequestDispatcher()
:获取请求转发器(选项 A 正确)。forward()
:执行实际的转发操作(但题目问的是哪个方法获取转发器,而非执行转发)。
其他选项分析:
- B.
request.getRequestDispatcher().forward()
:- 语法正确,但题目问的是获取转发器的方法,而非完整调用链。
- C.
response.sendRedirect()
:- 用于重定向(Redirect),而非转发(Forward)。
- D.
response.sendRequestDispatcher()
:- 无此方法,属于干扰项。
题目问的是如何获取请求转发器,因此正确答案是 A(request.getRequestDispatcher()
)。
若题目问如何执行转发,则需调用 forward()
方法(如选项 B 的完整写法)。
关键区别:
- 转发(Forward) →
request.getRequestDispatcher().forward()
- 重定向(Redirect) →
response.sendRedirect()