Request forwarding and response redirection

什么是请求转发和响应重定向

  • 请求转发和响应重定向是web应用中间接访问项目资源的两种手段,也是Servlet控制页面跳转的两种手段
  • 请求转发通过HttpServletRequest实现,响应重定向通过HttpServletResponse实现
  • 请求转发生活举例: 张三找李四借钱,李四没有,李四找王五,让王五借给张三
  • 响应重定向生活举例:张三找李四借钱,李四没有,李四让张三去找王五,张三自己再去找王五借钱

我先来解释一下为什么请求转发通过HttpServletRequest实现,响应重定向通过HttpServletResponse实现

先来了解一下请求转发和响应重定向

请求转发

请求转发逻辑图

equest-forwardin

设计原理

  • 请求转发是服务器内部的行为,目的是将请求从一个资源(如 Servlet)传递到另一个资源(如 JSP 或另一个 Servlet)。
  • 它是服务器内部的协作机制,客户端对此无感知。

行为特点

  • 客户端只发送一次请求,服务器内部完成资源的跳转。
  • URL 不会改变,客户端不知道发生了转发。
  • 全程只有一个 HttpServletRequestHttpServletResponse 对象。

为什么通过 HttpServletRequest 实现?

  • 请求转发需要共享请求和响应对象。
  • HttpServletRequest 对象包含了客户端的请求信息(如参数、属性等),并且可以在多个资源之间传递。
  • 通过 HttpServletRequestgetRequestDispatcher() 方法获取请求转发器,然后调用 forward() 方法实现转发。

响应重定向

响应重定向逻辑图

esponse-redirec

设计原理

  • 响应重定向是服务器告诉客户端:“你去访问另一个资源吧。” 客户端会重新发送一个请求到新的地址。
  • 它是客户端的行为,服务器只是通过响应码和 Location 头提示客户端。

行为特点

  • 客户端至少发送两次请求,第一次请求服务器,第二次请求新的资源。
  • URL 会改变,客户端知道发生了重定向。
  • 每次请求都会创建新的 HttpServletRequestHttpServletResponse 对象。

为什么通过 HttpServletResponse 实现?

  • 响应重定向需要修改 HTTP 响应,告诉客户端去访问新的资源。
  • HttpServletResponse 对象用于控制 HTTP 响应,包括设置状态码和响应头。
  • 通过 HttpServletResponsesendRedirect() 方法设置 302 状态码和 Location 头,实现重定向。

所以请求转发用 HttpServletRequest,而响应重定向用 HttpServletResponse

  1. 请求转发
    • 需要共享请求和响应对象。
    • HttpServletRequest 包含了客户端的请求信息,可以在多个资源之间传递。
    • 通过 HttpServletRequestgetRequestDispatcher() 方法获取请求转发器,然后调用 forward() 方法实现转发。
  2. 响应重定向
    • 需要修改 HTTP 响应,告诉客户端去访问新的资源。
    • HttpServletResponse 用于控制 HTTP 响应,包括设置状态码和响应头。
    • 通过 HttpServletResponsesendRedirect() 方法设置 302 状态码和 Location 头,实现重定向。

请求转发的特点

  1. 实现方式

    • 通过 HttpServletRequest 对象的 getRequestDispatcher() 方法获取请求转发器,然后调用 forward() 方法实现。

    • 示例:

      1
      2
      3
      4
      5
      // 获取请求转发器,指定目标资源的路径为 "/target"
      RequestDispatcher dispatcher = request.getRequestDispatcher("/target");

      // 将当前的请求(request)和响应(response)对象转发到目标资源 "/target"
      dispatcher.forward(request, response);
  2. 行为性质

    • 请求转发是服务器内部的行为,客户端对此无感知。
    • 客户端只发送了一次请求,地址栏的 URL 不会改变。
  3. 请求和响应对象

    • 服务器只产生了一对 HttpServletRequestHttpServletResponse 对象。
    • 这对对象会继续传递给下一个资源(如 Servlet、JSP)。
  4. 数据传递

    • 因为全程只有一个 HttpServletRequest 对象,所以请求参数和请求域中的数据可以传递。

    • 示例:

      1
      2
      3
      4
      5
      6
      7
      8
      // 1. 向请求域中添加数据
      request.setAttribute("message", "Hello");

      // 2. 获取请求转发器,指定目标资源的路径为 "/target"
      RequestDispatcher dispatcher = request.getRequestDispatcher("/target");

      // 3. 执行请求转发,将当前的请求和响应对象传递给目标资源 "/target"
      dispatcher.forward(request, response);
  5. 资源类型

    • 可以转发给其他 Servlet 动态资源,也可以转发给静态资源(如 HTML、JSP)以实现页面跳转。
    • 可以转发到 WEB-INF 下受保护的资源(如 /WEB-INF/secret.jsp)。(我觉得这个很重要)
  6. 外部资源

    • 请求转发不能转发到本项目以外的外部资源。

响应重定向的特点

  1. 实现方式

    • 通过 HttpServletResponse 对象的 sendRedirect() 方法实现。

    • 示例:

      1
      response.sendRedirect("/target");
  2. 行为性质

    • 响应重定向是服务端通过 302 状态码和 Location 头,告诉客户端去访问另一个资源。
    • 客户端至少发送了两次请求,地址栏的 URL 会发生变化。
  3. 请求和响应对象

    • 服务器产生了多对 HttpServletRequestHttpServletResponse 对象。
    • 这些对象不会传递给下一个资源。
  4. 数据传递

    • 因为全程产生了多个 HttpServletRequest 对象,所以请求参数和请求域中的数据不能传递。

    • 如果需要传递数据,可以通过 URL 参数或会话(Session)实现。

    • 示例:

      1
      response.sendRedirect("/target?message=Hello");
  5. 资源类型

    • 可以重定向到其他 Servlet 动态资源,也可以重定向到静态资源(如 HTML、JSP)以实现页面跳转。

    • 不能重定向到 WEB-INF 下受保护的资源。(这个就是他们最本质的区别)

      可以这样理解,请求转发是A请你帮忙的东西你不会,然后你去找B求教,等你学会了再教A——>间接访问WEB-INF
      响应重定向是A请你帮忙你不会,你让他去找B——>这里就相当于直接访问了WEB-INF

  6. 外部资源

    • 响应重定向可以重定向到本项目以外的外部资源(如 https://example.com)。

对比总结

特性 请求转发(Forward) 响应重定向(Redirect)
实现方式 request.getRequestDispatcher().forward() response.sendRedirect()
客户端感知 无感知 感知
请求次数 一次 至少两次
URL 是否改变 不变 改变
请求和响应对象 一对 多对
数据传递 可以传递请求参数和请求域数据 不能传递请求参数和请求域数据
资源类型 可以访问 WEB-INF 下受保护的资源 不能访问 WEB-INF 下受保护的资源
外部资源 不能访问外部资源 可以访问外部资源

适用场景

请求转发(Forward)

  • 适用于需要在服务器内部完成处理的场景,如:
    • 登录验证后跳转到欢迎页面。
    • 表单提交后跳转到结果页面。
    • 权限验证失败后跳转到错误页面。

响应重定向(Redirect)

  • 适用于需要改变 URL 的场景,如:
    • 登录成功后跳转到主页。
    • 表单提交后防止重复提交。
    • 跳转到外部资源(如第三方支付页面)。