【Java Web】请问:请求转发与响应重定向有什么区别?

一、前言

在Servlet中,请求转发响应重定向是两种重要的机制,用于控制客户端与服务器之间的交互。本文将探讨Servlet请求转发和响应重定向,更好地理解它们的工作原理和应用场景。


二、内容

2.1 概述

在开发中,我们需要在不同的Servlet(或Servlet)之间进行跳转,以实现功能的模块化,或者说分层设计。

有两种主要的方式可以用于在多个Servlet(JSP)之间进行跳转,即请求转发响应重定向。下面我们简单来看一下二者的定义。

(1)请求转发

首先是请求转发。

请求转发是一种将请求从一个Servlet或JSP页面转发到另一个Servlet或JSP页面的方式 。注意,请求转发是服务器跳转,只会产生一次请求(它是服务器内部的操作,客户端对此一无所知。)。

请求转发的代码通常如下所示:

java 复制代码
request.getRequestDispatcher("/direct/index").forward(request, response);

对于请求转发来说,是在服务器内部完成的,此时浏览器地址栏中的URL并不会发生变化。

注意,在请求转发中,原始请求的信息,包括请求参数和属性,是可以被传递到目标Servlet或JSP页面。

这个在后面示例中会体现。

(2)响应重定向

下面来看一些响应重定向。

响应重定向指的是将请求从一个Servlet或JSP页面重定向到另一个URL的方式 。它会向客户端浏览器发送一个新的URL,然后浏览器会重新发送请求到该URL。注意这里的变化,这就和请求转发不同了。请求转发只会产生一次请求,而响应重定向会产生两次请求

响应重定向的代码通常如下所示:

java 复制代码
response.sendRedirect("/MyServlet/direct/index");

注意,在使用响应重定向时,通常需要在目标URL中包含应用程序的上下文路径(context path)。

上下文路径是Web应用程序在服务器上的根路径,通常是项目名称。


2.2 代码示例

(1)准备工作

下面我们创建一个工程,名称为 MyServlet

接着,我们创建两个 Servlet,分别是 CheckLoginServletIndexServlet

两个 Servlet 的映射地址分别是 /direct/check/direct/index,初始代码如下:

对于一个简单的用户登录操作来说,首先需要用户信息校验,其次是登录成功后的首页显示。

现在,我们简单来模拟一下用户登录过程,并实现这两个Servlet的跳转。

(2)请求转发的示例

在这里,我们修改 CheckLoginServlet 中的 doGet() 方法:

java 复制代码
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	// 在控制台输出信息,模拟用户登录成功
	System.out.println("用户登录成功...");
	// 实现请求转发功能
	request.getRequestDispatcher("/direct/index").forward(request, response);
}

这样,就可以在运行时就可以把请求从当前的地址转发给了 IndexServlet 进行处理。

我们来验证一下实现效果。

首先修改配置服务器(Tomcat)上的资源,将我们的工程添加过去:

接着,启动服务器。

在浏览器的地址栏中输入

bash 复制代码
http://localhost:8080/myServlet/direct/check

回车后效果如下:

从上图中我们可以发现什么?

页面的输出内容是 IndexServlet 的作用效果。同时,地址栏中的URL映射是 direct/check。没错,这是与CheckLoginServlet关联的路径,这样的结果表明,请求转发功能设置成功了。

当浏览器请求匹配路径 localhost:8080/myServlet/direct/check 的URL时,CheckLoginServletdoGet 对其打印 "用户登录成功...",接着将我们当前的请求给转发到了 IndexServlet 上。从而触发了 IndexServlet 中的 doGet() 方法。

java 复制代码
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	// 模拟登录成功后的首页展示效果
	response.getWriter().println("Index Page!");
}

(3)响应重定向的示例

在之前的例子中,我们使用了请求转发来实现两个 Servlet 的跳转。现在我们换成另一种方式来实现这个效果。

我们修改 CheckLoginServlet 中的 doGet() 方法,如下所示:

java 复制代码
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	// 在控制台输出信息,模拟用户登录成功
	System.out.println("用户登录成功...");
	// 实现响应重定向功能
	response.sendRedirect("/MyServlet/direct/index");
}

需要注意的是,响应重定向需要增加 contextPath,即上下文路径(通常是工程名字)。不加这个,访问是有问题的。

我们再来看一下程序的运行效果,当我们再次输入 地址:

bash 复制代码
http://localhost:8080/myServlet/direct/check

回车后效果如下:

可以看到,我们的结果没有发生变化,但是需要注意到,地址栏中的映射地址发生了变化。从原先的 /direct/check 请求变成了 /direct/index


2.3 工作原理对比

我们再来回顾一下。

首先,请求转发是在服务器内部将一个请求发送到另一个资源的处理过程,在整个过程中,客户端(浏览器)并不知道服务器端发生了什么

大致工作流程如下:

  1. 客户端发起HTTP请求。
  2. 第一个Servlet处理请求,然后使用RequestDispatcher将请求传递给第二个Servlet
  3. 第二个Servlet处理请求并生成响应。
  4. 响应返回给客户端。

在这个过程中,客户端只知道自己向第一个Servlet发送了请求,不知道第二个Servlet的存在。

而响应重定向不一样,它指的是客户端(浏览器)重新定向到一个新的URL。在重定向的过程中,服务器会返回一个状态码和一个新的URL给客户端,客户端(浏览器)需要重新发起一个新的请求。

工作流程如下:

  1. 客户端发起HTTP请求。
  2. 第一个 Servlet 处理请求,然后通过 response.sendRedirect() 将响应中的目标URL发送回客户端。
  3. 客户端浏览器收到响应后,会发起第二次HTTP请求,前往目标URL。
  4. 第二个 Servlet 处理第二次请求并生成响应。
  5. 第二个响应返回给客户端。

如下图所示:

因此,我们可以简单记住,请求转发是服务器跳转,只会产生一次请求。而重定向则是浏览器端跳转,会产生两次请求。


2.4 设置请求自定义属性

我们可以在 Servlet 中创建自定义属性(设置请求属性)和获取请求属性。这些操作允许我们在处理请求期间存储和检索自定义数据。

(1)设置请求属性

使用request.setAttribute(属性名, 属性值)方法可以设置请求属性。请求属性允许你存储数据,以便在同一请求的不同ServletJSP页面中共享。

(2)获取请求属性

使用request.getAttribute(属性名)方法可以获取请求属性的值。

(3)示例

还是之前的例子。

我们在 CheckLoginServlet 中的 doGet() 方法中添加一行代码:

java 复制代码
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	// 在控制台输出信息,模拟用户登录成功
	System.out.println("用户登录成功...");
    // 设置请求属性
	request.setAttribute("userName", "admin");
	// 实现请求转发功能
	request.getRequestDispatcher("/direct/index").forward(request, response);
}

这里使用的是请求转发

当跳转到 IndexServlet 时,我希望输出上面自定义的属性。

简单修改一下代码:

java 复制代码
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	String userName = (String)request.getAttribute("userName");
	// 模拟登录成功后的首页展示效果
	response.getWriter().println("Index Page! Hello, " + userName);
}

启动服务器,访问地址:

bash 复制代码
http://localhost:8080/myServlet/direct/check

效果如下:

从输出结果也可以看出来,在这个转发过程中,对于 CheckLoginServletIndexServlet使用的都是同一个请求对象。

否则,我们在CheckLoginServlet 中设置请求对象的 userName 属性是无法被获取到的

下面,我们再修改一下程序,将跳转方式改为使用响应重定向

java 复制代码
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	// 在控制台输出信息,模拟用户登录成功
	System.out.println("用户登录成功...");
    // 设置请求属性
	request.setAttribute("userName", "admin");
	// 实现响应重定向功能
	response.sendRedirect("/myServlet/direct/index");
}

重新加载后,页面效果如下:

可以看到,此时输出结果变为了 null 。这是因为 userName属性在这里是一个空字符串,所以输出 null

通过这个例子,也证明了对于重定向来说,实际上浏览器产生了两个请求,在这种情况下,两个 Servlet 是无法共享请求属性的,第一个Servlet设置的请求属性,跳转到第二个Servlet后是无法获取的。


三、总结

本文深入探讨了Servlet请求转发与响应重定向两种机制。

请求转发是一种在服务器内部完成的机制,适用于模块化开发和数据共享,而响应重定向是一种客户端行为,通常用于跳转到不同的URL。了解它们的工作原理和应用场景,可以帮助我们更好地选择合适的机制,以满足不同的需求。

相关推荐
哎呦没15 分钟前
SpringBoot框架下的资产管理自动化
java·spring boot·后端
2401_8576009518 分钟前
SpringBoot框架的企业资产管理自动化
spring boot·后端·自动化
m0_571957582 小时前
Java | Leetcode Java题解之第543题二叉树的直径
java·leetcode·题解
魔道不误砍柴功4 小时前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
NiNg_1_2344 小时前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
闲晨4 小时前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
Chrikk6 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*6 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go
canyuemanyue6 小时前
go语言连续监控事件并回调处理
开发语言·后端·golang
杜杜的man6 小时前
【go从零单排】go语言中的指针
开发语言·后端·golang