请求转发与请求重定向的区别
请求重定向和转发
1、请求重定向:浏览器的行为(通过响应对象HttpServletResponse来执行)
特点:可以重新定向访问其他Web应用下的资源
浏览器发出了2次请求,得到了2次响应
地址栏地址会变,跳转到要求指定的Servlet
代码演示:
//请求重定向方式一:
public void sent1(HttpServletResponse response) { response.setStatus(302); response.setHeader("Location", "/ServletStudy/servlet/ServletDemo2"); //这个地址是要求浏览器重新访问的。 }
//请求重定向方式二:
public void send2(HttpServletRequest request,HttpServletResponse response) throws IOException { //服务器向访问的浏览器的请求中添加属性,当被请求重定向后,在新的Servlet中不能得到添加的属性。 //因为请求重定向后的请求request对象不懂,这就是request的生命周期。 request.setAttribute("name", "zhangsan"); //与方式一实现的原理相同,较为常用 response.sendRedirect("/ServletStudy/servlet/ServletDemo2"); }
2、请求转发:服务器的行为(转发的瞬间是一个ServletRequest的生命周期)
特点:转发只能发生在当前Web应用下
浏览器发出了1次请求,得到了1次响应
(源组件和目标组件共享request和response中的数据)
地址栏地址不会发生变化。
应用:
(1)可以利用request的域对象的特点,由源组件向其中存放写数据。
(2)可以让用户访问到存放在WEB-INF目录中的目标资源
代码演示:
//请求转发 public void send3(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException{ //在请求转发之前进行属性添加,在新的Servlet资源中能获取这个属性 request.setAttribute("name", "zhangsan"); //获取当前Servlet资源的转发器对象RequestDispatcher,传入当前应用的下要访问的那个Servlet资源 RequestDispatcher rd = getServletContext() .getRequestDispatcher("/servlet/ServletDemo2"); //注意:传入的要访问的Servlet资源的地址中/代表的就是当前应用,所以就可以访问当前应用中WEB-INF中的信息 rd = getServletContext() .getRequestDispatcher("/WEB-INF/form.html"); //也可以通过request得到转发器对象,用request得到的转发器在传入路径时,可以传入相对路径,不用加/ rd = request.getRequestDispatcher("/servlet/ServletDemo2"); //这里传入的路径地址:相对去被转发地址不同地方 //被转发地址: http://localhost:8080/ServletStudy/servlet/ServletDemo1 //转发地址: http://localhost:8080/ServletStudy/servlet/ServletDemo2 //所以填写相对资源地址:ServletDemo2 rd = request.getRequestDispatcher("ServletDemo2"); //调用转发器的forward()方法,进行请求转发 rd.forward(request, response); }
3.RequestDispatcher中forward()转发和include()包含的区别
forword()转发:源组件<--->头+体
源组件转向目标组件,由目标组件显示响应正文结果(只有目标的响应)
转发前,容器会清空response对象的缓存,源组件的任何页面输出都无效,也就是会清空源组件的体
转发前不要刷新或关闭response的流
include()包含:
源组件包含目标组件,由源组件显示响应正文结果(还会把目标的响应结果包含进来)
包含前,容器会清空目标组件设置的响应头信息,目标组件所有设置的所有头都无效。
代码演示:
//RequestDispatch转发器中的:forward()和include()方法的区别
/*forword()转发:
源组件转向目标组件,由目标组件显示响应结果(只有目标的响应)
转发前,容器会清空response对象的缓存,源组件的任何页面输出都无效。
转发前不要刷新或关闭response的流
include()包含:
源组件包含目标组件,由源组件显示响应结果(还会把目标的响应结果包含进来)
包含前,容器会清空目标组件设置的响应头信息,目标组件所有设置的所有头都无效*/
public class ServletDemo3 extends HttpServlet { //当做源组件 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { forwardTest(request, response); } public void forwardTest(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { //response.setHeader("Refresh", "2"); OutputStream out = response.getOutputStream(); System.out.println("转发前向控制台输出"); out.write("转发前向页面输出".getBytes()); RequestDispatcher rd = request.getRequestDispatcher("ServletDemo4"); rd.forward(request, response); System.out.println("转发后向控制台输出"); out.write("转发后向页面输出".getBytes()); } public class ServletDemo4 extends HttpServlet { //当做目标组件 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setHeader("Refresh", "2"); response.getOutputStream().write("目标组件".getBytes()); }
4.ServletContext和ServletRequest都能得到RequestDispatcher区别
(1)ServletContext
RequestDispatcher getRequestDispatcher(String path):path必须以"/"开头,代表当前的应用。这种写法,叫做绝对路径写法。
(2)ServletRequest
RequestDispatcher getRequestDispatcher(String path):
path可以以"/"开头:代表当前的应用。这种写法,叫做绝对路径写法。
也可以不以"/"开头:代表相对路径。
5.各种URL的写法:绝对路径和相对路径,建议大家使用绝对路径
绝对路径:如:/day05 地址前加了/就是一个绝对路径
原则:要不要加应用名称,看地址为谁服务的?
如果是给服务器用的,就不用加/MyApp,"/"代表的是当前应用。
如果是给客户端用的,要加上"/MyApp","/"代表的是要访问的服务器的URL地址(域名+端口),
getRequestDispatcher(String path):
path是一个路径。 不要加"/MyApp",只需要"/"即可
form action="url":要加"/MyApp"
a href="url":要加"/MyApp"
img src="url":要加"/MyApp"
link href="url":要加"/MyApp"
script src="url":要加"/MyApp"
302+Location="url":要加"/MyApp"