[toc] 在一个web应用中通过两种方式,可以完成资源的跳转:
- 第一种方式:转发
- 第二种方式:重定向
1. Forward 转发
转发 :指内部转发。当一个Servlet处理请求的时候,它可以决定自己不继续处理,而是转发给另一个Servlet处理。
// 获取请求转发器对象
RequestDispatcher dispatcher = request.getRequestDispatcher("/dept/list");
// 调用请求转发器对象的forward方法完成转发
dispatcher.forward(request, response);
// 合并一行代码
request.getRequestDispatcher("/dept/list").forward(request, response);
// 转发的时候是一次请求,不管你转发了多少次。都是一次请求。
// AServlet转发到BServlet,再转发到CServlet,再转发到DServlet,不管转发了多少次,都在同一个request当中。
// 这是因为调用forward方法的时候,会将当前的request和response对象传递给下一个Servlet。
复制代码
注意: 因为转发是服务器内部的进行的,所以 request.getRequestDispatcher(/不要项目名的).forward(request, response);
编写的转发路径是不要加项目名的。
举例: 浏览器向 AServlet 发送请求,AServlet 将该请求 “转发
”给了 BServlet。但是前端的浏览器并不知道该请求被 BServlet 处理了,浏览器的地址栏上显示的还是发送给 AServlet 请求的路径信息。
package com.RainbowSea.servlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
public class AServlet extends HttpServlet {
// 地址栏上回车操作是 doGet()请求
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
IOException {
// 转发到 BServlet,转发的路径不要加项目名
request.getRequestDispatcher("/b").forward(request, response);
}
}
复制代码
package com.RainbowSea.servlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class BServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
IOException {
// 设置浏览器端显示响应的,格式类型,以及字符集
response.setContentType("text/html;charSet=UTF-8");
PrintWriter writer = response.getWriter();
writer.println("<h2> 这里是BServlet 的响应处理 </h2>");
}
}
复制代码
转发是由WEB服务器来控制的。A资源跳转到B资源,这个跳转动作是Tomcat服务器内部完成的 ,而我们前端也就是浏览器端是不知道我们服务器端对这个请求内部转发处理了多少次。 并且无论我们服务器内部转发了多少次,前端浏览器都仅仅只会认为仅仅只转发了一次,也就是仅仅发送了一次请求 。因为我们服务器端虽然进行了转发但是,浏览器的地址栏上的请求路径的地址是没有改变的(还是初始的请求路径)
转发:是可以将 一个Servlet 类当中的信息转发到另一个 Servlet 当中去的,可以实现 Servlet 数据的共享,需要用到 请求域
注意: 请求域的作用域(请求域当中存储的信息),只在一次 请求
范围内有效。而转发机制的特点决定了可以实现请求域的共享:因为无论服务器内部转发了多少次,前端浏览器都只视为是一次请求。
转发机制,将AServlett 类当中的信息转发到 BServlet 当中去
package com.RainbowSea.servlet;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
public class AServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
IOException {
// 设置,在浏览器上响应的格式类型
Date nowTime = new Date(); // 创建当前时间的 Date 对象
// 将 nowTime 的数据存储(绑定)到请求域当中
request.setAttribute("sysTime",nowTime);
// 第一步: 获取到转发对象,注意:/ 开始,不家项目名 , / + 对应跳转的 Servlet 当中的 web.xml 当中的url映射的路径
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/B");
// 第二步: 调用转发器的forward方法完成跳转/转发
requestDispatcher.forward(request,response);
}
}
复制代码
package com.RainbowSea.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
public class BServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException,
IOException {
// 设置,在浏览器上响应的格式类型
response.setContentType("text/html;charSet=utf-8");
PrintWriter writer = response.getWriter();
// 取出请求域当中的数据: 这里的name值与上面setAttribute(String name,Object obj) 保持一致。
Object sysTime = request.getAttribute("sysTime");
writer.println("sysTime = " + sysTime); // 显示到浏览器页面当中的数据
}
}
复制代码
转发的下一个资源必须是一个Servlet吗 ?