請求重定向和轉發
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"
