当前位置: 首页 > article >正文

sendRedirect()和forward()方法有什么区别?

前言     

        在 Java Web 开发中,sendRedirect()forward() 是两种用于页面跳转的方法,它们的本质区别在于 跳转方式是否能共享请求数据


1. sendRedirect()(客户端重定向)

概述

sendRedirect() 方法会让服务器返回 HTTP 302 状态码新的 URL,通知浏览器重新请求该 URL。这相当于让客户端发起两次 HTTP 请求,因此 地址栏会发生变化

定义

sendRedirect() 方法用于 客户端重定向,让浏览器重新发送请求到一个新的 URL。

语法

response.sendRedirect("https://www.example.com");

特点

地址栏变化:浏览器的地址栏会更新为新的 URL。
是两次请求:第一次请求访问 sendRedirect(),服务器返回 302,然后浏览器再发送新的请求。

请求方式改变

  • 如果原请求是 POST,则重定向后变为 GET(默认行为)。
  • 如果希望保持 POST 请求,需要使用 POST-Redirect-GET(PRG)模式307 Temporary Redirect

不能共享 request 作用域的数据(因为是两个不同的请求)。
用于跳转到外部网站或不同的 Web 应用
性能稍差,因为有两次请求,增加了网络开销。

示例:

@WebServlet("/redirectExample")
public class RedirectExample extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.sendRedirect("https://www.baidu.com");
    }
}

执行过程

  1. 客户端请求 http://localhost:8080/redirectExample

  2. 服务器返回 302 Found,并告知浏览器跳转到 https://www.baidu.com

  3. 浏览器重新发起请求,访问 https://www.baidu.com


2. forward()(服务器端请求转发)

概述

forward() 方法是在 服务器端 内部完成跳转,浏览器不会感知跳转,因此 地址栏不会发生变化,请求仍然是同一个。

定义

forward() 方法用于 服务器端请求转发,将请求转发到 同一个 Web 应用的另一个资源

语法

RequestDispatcher dispatcher = request.getRequestDispatcher("newPage.jsp");
dispatcher.forward(request, response);

特点

地址栏不变:用户访问的 URL 仍然是原来的地址。
是一次请求,请求对象 (request) 和响应 (response) 可以共享数据。
只能转发到同一个 Web 应用的资源(不能跳转到外部网站)。
性能更好,不需要客户端发起二次请求。
不适用于跨域或跨应用跳转

示例

@WebServlet("/forwardExample")
public class ForwardExample extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.setAttribute("message", "Hello, this is a forwarded request!");
        RequestDispatcher dispatcher = request.getRequestDispatcher("newPage.jsp");
        dispatcher.forward(request, response);
    }
}

 执行过程

  1. 客户端请求 http://localhost:8080/forwardExample

  2. 服务器内部转发请求到 newPage.jsp,但地址栏仍显示 forwardExample

  3. newPage.jsp 可以使用 request.getAttribute("message") 读取共享数据。


3. sendRedirect() vs. forward() 总结对比

特性sendRedirect()(重定向)forward()(请求转发)
请求次数两次请求一次请求
地址栏是否改变
数据共享不能共享 request 作用域数据可以共享 request 数据
是否能跳转到外部可以(可以跳转到其他网站)不能(仅限本 Web 应用)
性能相对较低(多一次 HTTP 请求)较高(在服务器内部处理)
适用场景跳转到外部站点、不同 Web 应用访问同一应用内的页面

4. 何时使用?

  • 使用 sendRedirect()

    • 需要跳转到外部站点(如 response.sendRedirect("https://www.google.com"))。

    • 需要让用户看到新 URL(如 OAuth 登录跳转)。

    • 不能共享 request 数据,或希望开始一个新的请求时。

  • 使用 forward()

    • 需要在同一个 Web 应用内跳转,并且共享 request 数据(如 request.setAttribute())。

    • 服务器端控制跳转,并且不希望 URL 变化时。

    • 适用于 MVC 模式中从 Servlet 跳转到 JSP 处理页面。


5. 代码示例:对比两者

@WebServlet("/redirectOrForward")
public class RedirectOrForwardServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
        String type = request.getParameter("type");
        
        if ("redirect".equals(type)) {
            response.sendRedirect("https://www.baidu.com"); // 重定向
        } else if ("forward".equals(type)) {
            RequestDispatcher dispatcher = request.getRequestDispatcher("newPage.jsp");
            dispatcher.forward(request, response); // 请求转发
        }
    }
}

测试

  • 访问:http://localhost:8080/redirectOrForward?type=redirect → 跳转到 Baidu

  • 访问:http://localhost:8080/redirectOrForward?type=forward → 服务器内部转发到 newPage.jsp


6. 结论

  • sendRedirect() 适用于外部跳转,是两次请求,地址栏变化不能共享 request 数据

  • forward() 适用于内部跳转,是一次请求,地址栏不变可以共享 request 数据

  • 一般情况下,性能要求高的跳转可选 forward(),跳转外部或不同应用时选 sendRedirect()

🚀 面试技巧:如果面试官问你区别,一定要结合 HTTP 请求次数、地址栏变化、数据共享等角度回答,并尽量提供代码示例!

 

如果觉得这篇博客对你有帮助,记得点赞 ⭐、收藏 📌、关注 🚀!


http://www.kler.cn/a/600844.html

相关文章:

  • 嵌入式系统应用-拓展-STM32 低功耗设计
  • unittest自动化测试实战
  • 【ESP32S3】esp32获取串口数据并通过http上传到前端
  • Docker 搭建 PlantUML 服务:高效生成 UML 图的最佳实践
  • 36.评论日记
  • QT原子变量:QAtomicInteger、QAtomicPointer、QAtomicFlag
  • Win11 环境使用WSL安装Ubunut系统
  • winstart.wsf 病毒清理大作战
  • “需求引致供给“在互联网时代的范式重构:基于开源AI智能名片链动2+1模式S2B2C商城小程序源码的技术经济学分析
  • 计算机网络 --应用层
  • 【设计模式】深入解析装饰器模式(Decorator Pattern)
  • 什么是Dify,以及我们能用它来做什么
  • Docker镜像相关命令(Day2)
  • 【leetcode hot 100 394】字符串解码
  • 【ARM】MDK-解决单机版LIC获取报错
  • 05、Tools
  • JupyterLab 导出中文 PDF 方案
  • 《算法笔记》9.6小节 数据结构专题(2)并查集 问题 D: More is better
  • 特殊行车记录仪DAT视频丢失的恢复方法
  • 日志截断/日志中途清空/不停止程序