1. 重定向与转发的区别:
1.重定向访问服务器两次,转发只访问服务器一次。
2.转发页面的URL不会改变,而重定向地址会改变
3.转发只能转发到自己的web应用内,重定向可以重定义到任意资源路径。
4.转发相当于服务器跳转,相当于方法调用,在执行当前文件的过程中转向执行目标文件,两个文件(当前文件和目标文件)属于同一次请求,前后页 共用一个request,可以通过此来传递一些数据或者session信息,request.setAttribute()和 request.getAttribute()。而重定向会产生一个新的request,不能共享request域信息与请求参数
5.由于转发相当于服务器内部方法调用,所以转发后面的代码仍然会执行(转发之后记得return);重定向代码执行之后是方法执行完成之后进行重定向操作,也就是访问第二个请求,如果是方法的最后一行进行重定向那就会马上进行重定向(重定向也需要return)。
6.无论是RequestDispatcher.forward方法,还是HttpServletResponse.sendRedirect方法,在调用它们之前,都不能有内容已经被实际输出到了客户端。如果缓冲区中已经有了一些内容,这些内容将被从缓冲区中移除。
可以这么理解:
转发相当于,张三向你借钱,但是你兜里没钱,所以你去找李四借到钱之后借给张三。对于张三而言并不知道你的钱是和李四借的。
重定向相当于,张三向你借钱,你兜里没钱,你告诉他李四有钱,所以张三再次去找李四借钱。
2. 调用方式
转发和重定向在Java中的方法如下:
request.getRequestDispatcher("/SecondServlet?addParam=newParam").forward(request, response);
response.sendRedirect("/WebSocket/SecondServlet");
WebSocket相当于项目名称,SecondServlet是具体的servlet请求。也就是转发不加项目名称,重定向可以写绝对URL,也可以写相对URL。
补充:3xx状态码与重定向相关。301是永久重定向,302是临时重定向,我们有时候希望发送永久重定向的code。上面sendRedirect默认是302。如下:
response.setStatus(301);
response.addHeader("Location", "/WebSocket/SecondServlet");
3. 应用场景
1. 转发 request.getRequestDispatcher().forward(request,response):
1、属于转发,也是服务器跳转,相当于方法调用,在执行当前文件的过程中转向执行目标文件,两个文件(当前文件和目标文件)属于同一次请求,前后页 共用一个request,可以通过此来传递一些数据或者session信息,request.setAttribute()和 request.getAttribute()。
2、在前后两次执行后,地址栏不变,仍是当前文件的地址。
3、不能转向到本web应用之外的页面和网站,所以转向的速度要快。
4、URL中所包含的“/”表示应用程序(项目)的路径。
2. 重定向 response.sendRedirect():
1、属于重定向,也是客户端跳转,相当于客户端向服务端发送请求之后,服务器返回一个响应,客户端接收到响应之后又向服务端发送一次请求,一共是2次请求,前后页不共用一个request,不能读取转向前通过request.setAttribute()设置的属性值。
2、在前后两次执行后,地址栏发生改变,是目标文件的地址。
3、可以转向到本web应用之外的页面和网站,所以转向的速度相对要慢。
4、URL种所包含的"/"表示根目录的路径。
特殊的应用:对数据进行修改、删除、添加操作的时候,应该用response.sendRedirect()。如果是采用了 request.getRequestDispatcher().forward(request,response),那么操作前后的地址栏都不会发生 改变,仍然是修改的控制器,如果此时再对当前页面刷新的话,就会重新发送一次请求对数据进行修改,这也就是有的人在刷新一次页面就增加一条数据的原因。
4. 测试
代码如下:
package chat; import java.io.IOException; import java.util.Enumeration; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet implementation class FirstServlet */ @WebServlet("/FirstServlet") public class FirstServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public FirstServlet() { super(); } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse * response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("=====FirstServlet=====S "); System.out.println("request: " + request + " response: " + response); Enumeration<String> parameterNames = request.getParameterNames(); while (parameterNames.hasMoreElements()) { String nextElement = parameterNames.nextElement(); System.out.println("key: " + nextElement + ", value: " + request.getParameter(nextElement)); } String beforeDispatch = "FirstServlet BeforeDispatch"; response.getWriter().write(beforeDispatch); System.out.println(beforeDispatch); request.getRequestDispatcher("/SecondServlet?addParam=newParam").forward(request, response); // response.sendRedirect("/WebSocket/SecondServlet?addParam=newParam"); String afterDispatch = "FirstServlet AfterDispatch"; response.getWriter().write(afterDispatch); System.out.println(afterDispatch); System.out.println("=====FirstServlet=====E "); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse * response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
package chat; import java.io.IOException; import java.util.Enumeration; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet implementation class FirstServlet */ @WebServlet("/SecondServlet") public class SecondServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public SecondServlet() { super(); } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse * response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("=====SecondServlet=====S "); System.out.println("request: " + request + " response: " + response); Enumeration<String> parameterNames = request.getParameterNames(); while (parameterNames.hasMoreElements()) { String nextElement = parameterNames.nextElement(); System.out.println("key: " + nextElement + ", value: " + request.getParameter(nextElement)); } String dispose = "SecondServlet dispose"; response.getWriter().write(dispose); System.out.println("=====SecondServlet=====E "); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse * response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
1. 测试转发:
注释掉上面重定向代码,访问:http://localhost:86/WebSocket/FirstServlet?addParam=newParam
java控制台结果:
=====FirstServlet=====S
request: org.apache.catalina.connector.RequestFacade@123810d1 response: org.apache.catalina.connector.ResponseFacade@1ed812af
key: name, value: zs
FirstServlet BeforeDispatch
=====SecondServlet=====S
request: org.apache.catalina.core.ApplicationHttpRequest@175ea12f response: org.apache.catalina.connector.ResponseFacade@1ed812af
key: name, value: zs
key: addParam, value: newParam
=====SecondServlet=====E
FirstServlet AfterDispatch
=====FirstServlet=====E
2. 测试重定向
注释掉转发代码,访问http://localhost:86/WebSocket/FirstServlet?addParam=newParam
java控制台代码:
=====FirstServlet=====S
request: org.apache.catalina.connector.RequestFacade@123810d1 response: org.apache.catalina.connector.ResponseFacade@1ed812af
key: name, value: zs
FirstServlet BeforeDispatch
FirstServlet AfterDispatch
=====FirstServlet=====E
=====SecondServlet=====S
request: org.apache.catalina.connector.RequestFacade@123810d1 response: org.apache.catalina.connector.ResponseFacade@1ed812af
key: addParam, value: newParam
=====SecondServlet=====E