servlet的请求转发和响应重定向

1. 简介

请求转发(Request Forwarding):请求转发是指服务器端将请求从一个 Servlet 转发到另一个 Servlet、JSP 页面或 HTML 页面,整个过程在服务器内部进行,对于客户端来说,只发送了一次请求,地址栏的 URL 不会发生改变
响应重定向(Response Redirect):响应重定向是指服务器向客户端发送一个特殊的响应,告诉客户端重新发送一个新的请求到另一个 URL,客户端收到这个响应后,会自动向新的 URL 发送请求,这会导致地址栏的 URL 发生改变

2. 请求转发

特点:

  1. 通过HttpServletRequest对象获取请求转发器实现。
  2. 服务器内部行为,对客户端屏蔽。
  3. 客户端只发送一次请求,地址栏不变。
  4. 服务端产生一对请求和响应对象,传递给下一个资源。
  5. 请求参数和请求域数据可传递。
  6. 可转发给动态或静态资源,包括WEB-INF下受保护资源。
  7. 不能转发到本项目外的外部资源。

具体实现:

  • 通过DispatcherServlet类实现请求转发,设置请求属性并使用RequestDispatcher对象进行转发。

2.1 forword的请求转发

forward()方法用于在服务器端将请求从一个Servlet转发到另一个资源,允许第一个组件预处理请求,而让第二个组件处理并返回响应。

工作原理:

  • 当使用forward()方法时,请求完全交给目标资源处理,源组件不作出任何响应处理。
  • 请求对象和响应对象没有重新创建,而是传递给了目标组件。
  • 请求转发可以帮助完成页面跳转,可以转发至WEB-INF目录下的资源,但不能转发至外部资源。

特点:

  • 转发是服务器的行为,浏览器在转发过程中仅执行一次
  • URL不会改变
  • 可以携带数据,这些数据存储在request对象中。
  • 必须在HTTP响应被“确认”(即内容主体送回用户端)之前调用,否则将抛出IllegalStateException异常。
  • 调用后,原HttpResponse对象中的内容将被自动清除
RequestDispatcher dispatcher = req.getRequestDispatcher("/testzhujie");
dispatcher.forward(req, res);

我们做个测试:

@WebServlet(name = "RequestDispatcherTest", value = "/request-dispatcher-test")
public class RequestDispatcherTest extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        PrintWriter out = res.getWriter();
        out.println("<h1>" + "RequestDispatcherTest" + "</h1>");
        RequestDispatcher dispatcher = req.getRequestDispatcher("/testzhujie");
        dispatcher.forward(req, res);
        System.out.println("RequestDispatcherTest");

        out.println("<h1>" + "RequestDispatcherTest1111111" + "</h1>");
    }
}

@WebServlet(name = "TestZhujie",
        urlPatterns = "/testzhujie",
        loadOnStartup = 1, initParams = {
            @WebInitParam(name = "username", value = "yxz2"),
            @WebInitParam(name = "password", value = "123456")
})
public class TestZhujie extends HttpServlet {
    @Override
    public void service(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
        resp.setCharacterEncoding("UTF-8");
        resp.getWriter().write("...........zhujie");
    }
}

访问结果:
在这里插入图片描述

2.2 include的请求转发

include()方法用于在响应中包含另一个资源的响应内容,最终产生的响应并入原响应对象。

工作原理:

  • 当使用include()方法时,源组件包含目标组件,由源组件显示响应正文结果(还会把目标的响应结果包含进来)。
  • 服务器会将标准响应输出流开启,当前Servlet可以向输出流中写入数据,并且服务器还会将要转向的资源的输出流中数据合并到当前的输出流中
  • 目标资源对响应状态码或响应头的修改会被忽略。

特点:

  • 源Servlet与目标资源的输出数据都会被添加到响应结果中。
  • 目标资源对响应状态码或响应头的修改会被忽略。
  • 返回源Servlet的服务方法,继续执行后续代码。
  • 可以在新资源处理后继续处理原始请求

做个测试:

@WebServlet(name = "RequestDispatcherTest2", value = "/request-dispatcher-test2")
public class RequestDispatcherTest2 extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        PrintWriter out = res.getWriter();
        out.println("<h1>" + "RequestDispatcherTest222222222" + "</h1>");
        // 请求转发
        RequestDispatcher dispatcher = req.getRequestDispatcher("/testzhujie");
        dispatcher.include(req, res);
        out.println("<h1>" + "RequestDispatcherTest222222222" + "</h1>");
    }
}
@WebServlet(name = "TestZhujie",
        urlPatterns = "/testzhujie",
        loadOnStartup = 1, initParams = {
            @WebInitParam(name = "username", value = "yxz2"),
            @WebInitParam(name = "password", value = "123456")
})
public class TestZhujie extends HttpServlet {
    @Override
    public void service(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
        resp.setCharacterEncoding("UTF-8");
        resp.getWriter().write("...........zhujie");

    }
}

访问结果:
在这里插入图片描述

2.3 其他

对于WEF-INF中受保护的文件,也可以访问到。
在这里插入图片描述

@WebServlet(name = "RequestDispatcherTest2", value = "/request-dispatcher-test2")
public class RequestDispatcherTest2 extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        // 请求转发
        RequestDispatcher dispatcher = req.getRequestDispatcher("/WEB-INF/aaaa.html");
        dispatcher.include(req, res);
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
我是图图小淘气。。。
</body>
</html>

访问结果:
在这里插入图片描述

3. 响应重定向

响应重定向(Response Redirect) 是一种服务器通知浏览器去访问另一个URL的技术。与请求转发不同,重定向会导致客户端发起一个新的请求,因此浏览器的地址栏会显示新的URL。

响应重定向的特点:

  • 两次请求:重定向涉及两个独立的请求。客户端首先向服务器发送一个请求,然后服务器响应一个重定向指令,客户端根据这个指令再发送第二个请求。
  • 地址栏变化:由于重定向是由客户端执行的,因此客户端的地址栏会显示新的URL。
  • 不共享Request和Response对象:在重定向过程中,原始请求的HttpServletRequest和HttpServletResponse对象不会传递到新的资源。每个请求都是独立的。
  • 使用HTTP状态码:重定向通常使用状态码302 Found或303 See Other。

实现响应重定向的方法:
在Servlet中,可以使用HttpServletResponse对象来实现响应重定向。 主要方法是:

  • sendRedirect(String location):这个方法发送一个重定向响应到客户端,指示客户端访问另一个URL。调用这个方法后,原始Servlet的service方法应该立即返回,不应再对response对象进行任何写入操作。
@WebServlet(name = "RequestDispatcherTest2", value = "/request-dispatcher-test2")
public class RequestDispatcherTest2 extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
        // 重定向
        res.sendRedirect("/testServlet/testzhujie");
    }
}

访问后会跳转:
在这里插入图片描述
类似于拼接地址,所以对于WEF-INF中的文件不能访问。

4. 区别

  1. 请求次数:
    • 请求转发:仅涉及一次请求和一次响应。服务器内部将请求转发给另一个Servlet,客户端地址栏不会变化。
    • 响应重定向:涉及两次请求和两次响应。服务器向客户端返回一个重定向响应,指示客户端重新发送一个请求到新的URL,地址栏会显示新的URL。
  2. 地址栏变化:
    • 请求转发:地址栏保持不变,显示的是原始请求的地址。
    • 响应重定向:地址栏会变化,显示的是重定向后的URL。
  3. 范围限制:
    • 请求转发:只能在同一Web应用内进行资源跳转,目标地址必须是当前Web应用内的资源。
    • 响应重定向:可以跳转到任意URL,包括其他Web应用或外部资源。
  4. 数据共享:
    • 请求转发:转发过程中,request对象在同一请求范围内共享,可以在目标Servlet中获取到原始请求中的数据。
    • 响应重定向:由于涉及两次独立的请求,重定向后的请求无法直接获取到原始请求中的数据,通常需要通过session或其他机制传递数据。
  5. 行为性质:
    • 请求转发:是服务器端的行为,发生在服务器内部,客户端只感知到一次访问。
    • 响应重定向:是客户端的行为,服务器通过返回302状态码和Location头来指示客户端重新发送请求。
  6. 适用场景:
    • 请求转发:适用于需要在同一个Web应用内传递数据的场景,如前后端分离的应用中,前端页面需要跳转到后端处理逻辑并返回结果。
    • 响应重定向:适用于需要跳转到外部资源或改变客户端地址栏显示的场景,如登录成功后跳转到首页

5. 总结

无。。。。写的也算详细了,就不多说了。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值