转发VS重定向
转发VS重定向
1-参考文档:
https://blog.csdn.net/weixin_51418964/article/details/123454677
https://blog.csdn.net/pison007/article/details/112323155
2-转发(forward)
一种在服务器内部的资源跳转方式。
服务端转发
2.1-实现步骤
- 通过 request 对象获取请求转发器对象:RequestDispatcher,
getRequestDispatcher(String path)
- 然后使用 RequestDispatcher 对象来进行转发:
forward(ServletRequest request, ServletResponse response)
req.getRequestDispatcher("/requestTest").forward(req, resp);
注意:这里是给服务器用的,所以不需要获取虚拟目录(/项目名),即 request.getContextPath();
2.2-图解
.
解释:客户端浏览器发送请求到 Request1,Request1 转发请求到 Request2,并且 Request1 和 Request2 共享 这次 request 请求中的 request 域数据。
2.3-代码示例
2.3.1-请求转发
设置一个数据域,并且把它转发到 request2
@WebServlet("/req1")
public class 请求转发 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setAttribute("name", "软柠柠吖");
req.getRequestDispatcher("/req2").forward(req, resp);
System.out.println("request1 被访问了。。");
}
}
2.3.2-共享数据
获取 Request1 中的数据域,并打印信息。
@WebServlet("/req2")
public class 共享数据 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Object name = req.getAttribute("name");
System.out.println("name = " + name);
System.out.println("Request2 被访问了。。。");
}
}
2.3.3-结果
当我们在浏览器中输入 http://localhost:8080/project/req1 并敲击回车后,可以看到:
- req2 居然输出了 req1 的 “软柠柠吖”。
- req2 和 req1 同时被访问了,而 req2 先被访问,req1 后被访问。
.
2.4-特点
- 抓包分析后,发现虽然访问到了 2 个 servlet,但是实际上却是一次请求。
.
- 当我们把要转发的资源 /req2 换成 同在一个服务器但是不同的项目中的资源 /req3 发现并不能实现转发(404 Not Found),这说明了只能转发到当前服务器的内部的同一个项目的资源。
@WebServlet("/req3")
public class 同一个服务器但是不同项目 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Object name = req.getAttribute("name");
System.out.println("req3 name = " + name);
System.out.println("req3 被访问了。");
}
}
@WebServlet("/req1")
public class 请求转发 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setAttribute("name", "软柠柠吖");
req.getRequestDispatcher("/req3").forward(req, resp);
System.out.println("request1 被访问了。。");
}
}
.
- 浏览器地址栏路径不发生变化。
.
- 可以访问 WEB-INF 目录下的资源文件。
@WebServlet("/req1")
public class 请求转发 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.getRequestDispatcher("/WEB-INF/web.xml").forward(req, resp);
}
}
- 成功访问到了 WEB-INF 下的 web.xml 文件
.
3-重定向(redirect)
另一种资源跳转方式。
客户端重定向
3.1-实现步骤(2种)
3.1.1-完整版
3.1.1.1-设置状态码为 302
resp.setStatus(302);
3.1.1.2-设置响应头
resp.setHeader("location", "/project/response2");
3.1.2-简洁版【常用】
resp.sendRedirect(req.getContextPath() + "/response2");
3.2-图解
.
3.3-代码示例
3.3.1-编写 response1,将请求重定向到 response2
@WebServlet("/response1")
public class 重定向 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("redirect1~");
/*
resp.setStatus(302); // 设置状态码为 302(重定向)
resp.setHeader("location", "/project2/response2"); // 设置响应头 location
*/
// 给客户端用,需要加虚拟目录 /project2
resp.sendRedirect("/project2/response2");
}
}
注意:这里给客户端使用,需要加虚拟目录。即 req.getContextPath()
;
3.3.2-编写 response2,直接输出信息
@WebServlet("/response2")
public class Response2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("response2~~");
}
}
3.3.3-结果
当我们输入 http://localhost:8080/project1/response1 敲击回车,发现浏览器地址会瞬间变成 http://localhost:8080/project2/response2,抓包分析发现浏览器一共发送了 2 次请求。
.
3.4-特点
- 地址栏发生变化。
这个不用再解释了,看上图即可~
- 重定向可以访问其他站点(服务器)的资源。
@WebServlet("/response1")
public class 重定向 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 重定向到百度
resp.sendRedirect("http://www.baidu.com");
}
}
注意:如果重定向到外部网站,必须加上 http://
.
.
- 重定向是两次请求。不能使用 request 对象来共享数据。
每一次浏览器发起的请求报文,都会被 Tomcat 封装到 Request 对象中。当第二次请求发出的时候,浏览器又发起了新的请求报文,Tomcat 会重新创建一个 Request 对象,去封装第二次请求报文,所以就会出现 req1 有参数,req2 无参数。
- 给 reqest 设置 name 参数并重定向
@WebServlet("/response1")
public class 重定向 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setAttribute("name", "软柠柠吖");
Object name = req.getAttribute("name");
resp.sendRedirect("/project2/response2");
System.out.println("req1 name = " + name);
}
}
- 获取 reqest 中的 name 参数
@WebServlet("/response2")
public class Response2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Object name = req.getAttribute("name");
System.out.println("req2 name = " + name);
}
}
- 结果
.
- 无法访问 WEB-INF 目录下的资源文件
原因:由于 WEB-INF 文件夹下的 html 等资源文件会受到服务器的保护,浏览器无法直接访问。在第二次请求访问的时候就被服务器拒绝了。
@WebServlet("/response1")
public class 重定向 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.sendRedirect("/project/WEB-INF/web.xml");
}
}
.
4-转发和重定向的区别【总结】
- 转发的地址栏不变,而重定向变成转发后的资源路径。
- 转发是一次请求,而重定向是两次请求。所以一般可以说重定向是 2 次转发。
- 转发只能在自己内部服务器资源内相互转发(同一项目内),而重定向可以访问其他站点。
- 推荐使用请求转发,因为请求转发耗的网络资源相对比重定向少。(因为请求转发是服务器内部行为)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!