请求转发和响应重定向
请求转发和响应重定向是 web 应用中间接访问项目资源的两种手段,也是 Servlet 控制页面跳转的两种手段。
请求转发通过 HttpServletRequest
实现,而响应重定向通过 HttpServletResponse
实现。
请求转发举例:张三找李四借钱,李四没有,李四找王五,让王五借钱给张三。
响应重定向举例:张三找李四借钱,李四没有,李四让张三找王五借钱,最终王五借钱给张三。
请求转发
请求转发是指 在服务器端,一个 Servlet 接收到客户端请求后,将请求对象(request)和响应对象(response)转发给另一个资源的过程。
提示
这里的另一个资源可以是 一个Servlet、也可以是静态的HTML文件、或者JSP文件。
特点
- 客户端只发送了一次请求,地址栏的 URL 是不会发生变化的;
- 客户端发送请求时,携带的 参数 也是可以在服务端进行传递的;
- 服务端只产生了一组 request 和 response 对象,他们会随着传递器传递给下一个资源;
- 请求转发是服务端内部的行为,客户端是不知道的;
- 请求转发可以转发到 web 目录下,也可以转发到受保护的 WEB-INF 目录下;
- 请求转发不能转发到本项目以外的资源(例如请求转发到 http://www.baidu.com,报404);
下面的案例,请求由 ServletA 转发到 ServletB 或 web/a.html 或 web/WEB-INF/b.html。
java
@WebServlet("/servletA")
public class ServletA extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("ServletA 执行了...");
// 获取客户端传递的参数,参数也是可以请求转发的
String username = req.getParameter("username");
System.out.println("ServletA => username = " + username); // admin
// 获取请求转发器,配置请求转发路径
// 1、请求转发到servletB(注意,这里写的是 ServletB 的请求地址,不是类名称)
RequestDispatcher dispatcher = req.getRequestDispatcher("servletB");
// 2、请求转发到web/a.html
RequestDispatcher dispatcher = req.getRequestDispatcher("a.html");\
// 3、请求转发到web/WEB-INF/b.html
RequestDispatcher dispatcher = req.getRequestDispatcher("WEB-INF/b.html");
// ❌请求转发是不可以请求项目外的资源的
RequestDispatcher dispatcher = req.getRequestDispatcher("http://www.baidu.com");
// 执行请求转发,并携带 请求参数和响应参数
dispatcher.forward(req, resp);
}
}
java
@WebServlet("/servletB")
public class ServletB extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("ServletB 执行了...");
// 在 servletB 中依然可以获取到客户端传递的 username 参数
String username = req.getParameter("username");
System.out.println("ServletB => username = " + username); // admin
// 获取响应输入流,向客户端返回用户输入的 username 的值
PrintWriter writer = resp.getWriter();
writer.print("<h1>" + username + "</h1>");
}
}
响应重定向
响应重定向 是指服务器收到请求后,告诉客户端去访问另一个地址(URL),客户端随后会再发起一次新的请求去访问那个地址。
响应重定向分为两步:
- 服务器返回一个
302
状态码,并在响应头中设置location: "新的URL地址"
; - 客户端收到后,自动跳转到新的URL地址,重新发起请求;
特点
- 响应重定向导致客户端至少发送了两次以上的请求;
- 响应重定向时,服务端的 request 和 response 对象是不能进行传递的,请求中携带的参数也不能传递;
- 响应重定向可以是动态的 Servlet 对象、web目录下的静态资源,但是不能是 WEB-INF 下的受保护资源;
- 响应重定向可以到本项目以外的外部资源;
java
@WebServlet("/servletC")
public class ServletC extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("ServletC go go go...");
// servletC中可以获取到请求体中的参数
String username = req.getParameter("username");
System.out.println("servletC username = " + username); // admin
// 设置状态码为302
resp.setStatus(302);
// 设置location响应头为重定向的路径
resp.setHeader("location", "servletD");
// 上面两步等价于下面一步
resp.sendRedirect("servletD");
// 1、重定向到web/a.html
resp.sendRedirect("a.html");
// 2、重定向到外部资源
resp.sendRedirect("http://www.atguigu.com");
// ❌不能重定向到 WEB-INF 受保护的资源
resp.sendRedirect("WEB-INF/b.html"); // 失败
}
}
java
@WebServlet("/servletD")
public class ServletD extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("ServletD go go go...");
// servletD中获取不到请求体中的参数
String username = req.getParameter("username");
System.out.println("servletD username = " + username); // null
}
}