请求转发
请求转发,是一种服务器行为,当客户端请求到达后,服务器进行转发,此时会将请求对象进行保存,地址栏中的URL地址不会改变,得到响应后,服务器端再将响应发送给客户端,这个过程只有一次请求发出。
实现方法如下,达到多个资源一起响应的效果。
request.getRequestDispatcher(url).forward(request,response)
- 特点:
- 服务器只能在当前内部资源进行跳转
- 浏览器地址栏不变
- 转发只有一次请求
- request数据可以共享
接下来通过代码解释下这几个特点。
这是requestDemo2
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/requestDemo2")
public class requestDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
System.out.println("requestDemo2-->"+username);
request.getRequestDispatcher("/requestDemo3").forward(request,response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
这是requestDemo3
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/requestDemo3")
public class requestDemo3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("这是requestDemo3的页面");
String username = request.getParameter("username");
System.out.println("requestDemo3-->"+username);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
向requestDemo2传入username=zhangsan的参数,接下再看这张图片。
Server打印这两条结果,我们发现通过访问requestDemo2的同时也访问到了requestDemo3页面,只是浏览器的地址栏没有改变。
还有通过浏览器的抓包可以发现,在这次转发的过程中至始至终只有一次请求,服务器只发起了一次请求,但是结果是两个资源都被访问了,所以说转发只有一次请求。
如果将getRequestDispatcher(url)替换成百度的网址,页面发生跳转就会发生404页面不存在错误,因为百度的网址不是服务器内部的资源。
request作用域
通过request对象可以在一次请求中传递数据,经过请求转发,request域中的数据依然存在,可以通过request传输和共享数据。
// 设置域对象内容
request.setAttribute(String name, String value)
// 获取域对象内容
request.getAttribute(String name)
// 删除域对象内容
request.removeAttribute(String name)
重定向
重定向是服务器指导客户端的行为,客户端发出第一个请求,被服务器接收处理后,服务器会作出响应,在响应的同时,服务器会给客户端一个新的资源地址(就是下次请求的地址),当客户端拿到接受到响应后,会马上根据新地址发起第二个请求,服务器接收请求并作出响应,重定向完成。
/*第一种方法*/
// 设置状态码302
response.setStatus(302);
// 设置响应头location
response.setHeader("location",url);
/*第二种方法*/
response.sendRedirect(url)
废话不多说上代码
这是requestDemo2
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/requestDemo2")
public class requestDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
System.out.println("requestDemo2-->"+username);
response.sendRedirect("/requestDemo3");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
这是requestDemo3
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/requestDemo3")
public class requestDemo3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
System.out.println("requestDemo3-->"+username);
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("demo3....");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request,response);
}
}
向requestDemo2传入username=zhangsan的参数,接下再看这张图片。
通过浏览器的抓包,可以得出重定向的过程有两次请求,并且requestDemo2的状态码为302,location为/requestDemo3,浏览器的地址栏发生改变。
Server的打印结果可以看出,requestDemo3打印zhangsan而requestDemo2却没有,所以重定向不能用request共享数据,因为这是两次请求。重定向还可以访问其他服务器的资源。
总结
请求转发与重定向的比较
| 请求转发forward | 重定向redirect |
|---|---|
| 一次请求 | 两次请求 |
| 数据在request域中共享 | request域中数据不共享 |
| 浏览器地址栏不改变 | 浏览器地址栏改变 |
| 只能访问当前服务器下的资源 | 可以访问其他服务器的资源 |
| 服务器行为 | 客户端行为 |