forward和redirect的區別

概述:

如何從服務器端的某個資源訪問另一個資源?從服務器端的某個資源訪問另一個資源通常有兩種訪問方式:

一種叫做請求轉發;

一種叫做請求重定向;


1、forward(請求轉發)

如何理解請求轉發:

從Servlet1,請求轉發到Servlet2, Servlet1完成一部分的功能,再跳轉到Servlet2,繼續完成剩下的功能。

語法:

request.getRequestDispatcher(String path).forward(request,response);

參數:path,表示跳轉的目標的路徑(資源的名稱)。

打個比方:

老師交給班長一個工作任務,就是今晚幫忙關閉電腦;但是班長今晚有事情,不能做這個工作,他就把這個工作交給別人做了;改天老師來就看到電腦已經被關閉了在老師的眼裏這個工作還是班長做的。

在web程序中,就是一個servlet可以把一個請求再發送給另一個servlet(類似於工作轉移),但是對於客戶端來說,它還是認爲工作是第一個servlet完成的,第一個servlet把工作交給第二個servlet去完成的過程就叫做請求轉發。

請求轉發實現轉發只使用了一次http請求,一次轉發中request和response對象都是同一個;請求轉發是一次請求一旦把請求參數放入到request中,則只要是請求轉發,無論轉發過程中經歷多少個資源,則在這些資源中都可以獲取放入request中的參數值請求轉發是不會改變瀏覽器的請求路徑的;編寫請求轉發的路徑是不需要寫項目名稱的;請求轉發的響應體是最後一個處理請求的servlet返回的信息。

請求轉發流程圖:

(1)使用請求轉發轉到s2頁面

servlet1

@WebServlet("/forward/s1")
public class Servlet1 extends HttpServlet{
	private static final long serialVersionUID = 1L;
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.setContentType("text/html;charset=utf-8");
		PrintWriter out=resp.getWriter();
		//===========================================
		//System.out.println("servlet1.service()");
		System.out.println("servlet1……before");//控制檯輸出
		out.println("servlet1……before");//網頁輸出
		//---------------------------------------
		//請求轉發
		req.getRequestDispatcher("/forward/s2").forward(req, resp);
		//---------------------------------------
		System.out.println("Servlet1……after");
		out.println("Servlet1……after");
	}
}

servlet2:

@WebServlet("/forward/s2")
public class Servlet2 extends HttpServlet{
	private static final long serialVersionUID = 1L;
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		resp.setContentType("text/html;charset=utf-8");
		PrintWriter out=resp.getWriter();
		System.out.println("Servlet2……");
		out.println("Servlet2……");
	}
}

在瀏覽器輸入:http://localhost:9090/forward/s1 進行訪問發現輸出的是servlet2的數據,但是瀏覽器地址欄並沒有變成s2;

 控制檯最後輸出的數據證明頁面最後還是跳轉回了s1;

(2)分別在servlet1和servlet2中寫入獲取參數的代碼,在瀏覽器地址欄輸入參數:

System.out.println("servlet1……before"+req.getParameter("name"));//控制檯輸出
System.out.println("Servlet2……"+req.getParameter("name"));

可以看到servlet1和servlet2獲取到的參數是一樣的。

 (3)在servlet1和servlet2中打印請求看輸出的請求地址是否爲同一個;

System.out.println(req);

在控制檯看到輸出的地址不一樣但是獲得的參數是一樣的,這說明他們共享的是同一個請求中的數據。

 

(4)WEB-INFO中的資源是受保護的不能直接訪問,可以使用請求轉發進行訪問;

//使用請求轉發訪問WEB-INF中的資源
req.getRequestDispatcher("/WEB-INF/in.html").forward(req, resp);

 請求轉發的特點:

1:瀏覽器地址欄不發生改變,依然是/forward/s1,不是目標地址(/forward/s2)。

2:請求轉發只發送一個請求。

3:共享同一個請求中的數據。

4:最終響應給瀏覽器的由Servlet2來完成。

5:請求轉發不能跨域訪問,只能跳轉到當前web服務器中的資源。

6:請求轉發可以訪問WEB-INF目錄中的資源。


2、redirect(重定向)

如何理解重定向:

通過各種方法將各種網絡請求重新定個方向轉到其它位置,如其它網址;

語法:

response.sendRedirect(String url);

參數:url,表示目標資源地址。

打個比方:

老師交給班長一個工作任務,就是今晚幫忙關閉電腦;但是班長今晚有事情,不能做這個工作;班長就向老師反饋,我不能做這個工作,但是某個同學可以做;然後老師就又找這個同學去做這個事情;最終事情做完,老師知道是哪個同學完成的這個事情。

在web程序中,就是一個servlet1可以把請求再返回給客戶端,由客戶端再請求第二個servlet2去完成

但是對於客戶端來說它是知道工作是第二個servlet2完成的;

在以上的描述中,第一個servlet1把工作返回了客戶端,由客戶端再交給第二個servlet2去完成,這個過程就叫做請求重定向,請求重定向是兩次請求,兩次請求的結果就是對應兩個request,第一個request是客戶端把參數發送給servlet1,在Servlet1輸出了請求參數,在servlet1中使用重定向把一個請求路徑返回給客戶端瀏覽器;第二個request是瀏覽器再使用第一個servlet1返回的路徑去訪問servlet2。

URL重定向流程圖:

(1)使用重定向跳轉到servlet2,在瀏覽器地址欄輸入:localhost:9090/redirect/s1。

//使用URL重定向跳轉到servlet2
resp.sendRedirect("/redirect/s2");

回車之後地址欄變成了s2;

 (2)在servlet1和servlet2中加入接受請求參數的代碼,看他們能否獲得同一個參數。

//servlet1獲取請求參數
System.out.println("servlet1……before"+req.getParameter("name"));me"));
//servlet2獲取請求參數
System.out.println("Servlet2……"+req.getParameter("name"));

在瀏覽器地址欄輸入:localhost:9090/redirect/s1?name=wiil,發現servlet1獲得了請求參數,而servlet2獲得的值爲null;從中可以看出URL重定向是兩次獨立的請求,所以不共享請求中的數據。

 (3)使用URL進行跨域訪問

//使用URL重定向進行跨域訪問百度
resp.sendRedirect("https://baidu.com");

在瀏覽器地址欄輸入:localhost:9090/redirect/s1,回車之後跳轉到百度,如下圖:

重定向的特點:

1:瀏覽器地址欄發生改變,從/redirect/s1,變成目標地址(/redirect/s2)。

2:URL重定向發了兩次請求。

3:因爲URL重定向是兩次獨立的請求,所以不共享請求中的數據。

4:最終響應給瀏覽器的由Servlet2來決定(相當於把目標地址拷貝到瀏覽器地址欄,敲回車)。

5:URL重定向能跨域訪問,可以訪問其他應用中的資源。

6:URL重定向不能訪問WEB-INF目錄中的資源。


3、forward和redirect的區別

D1:請求轉發一個請求一個request對象;

請求重定向兩次請求兩個request對象。

D2:使用請求轉發瀏覽器的url是不會發生改變的;

使用請求重定向瀏覽器的url是會發生變化的。

D3:使用請求轉發只要是在這個轉發流程中,每一個servlet都可以獲取請求參數;

使用重定向, 只是第一次瀏覽器給某個servlet發送的請求參數可以被接收到,重定向的servlet是接收不到請求參數的(需要把請求參數再次傳遞)。

D4:請求轉發可以訪問應用WEB-INF下的資源;而請求重定向是不可以訪問應用WEB-INF下的資源;所以以上的問題就牽扯瞭如果考慮資源的安全性,可以把資源放到本應用的WEB-INF下,這樣使用重定向方式不能訪問(也就意味着使用瀏覽器不能訪問) 客戶從別的地方使用瀏覽器就不能訪問這個資源,只能使用請求轉發從後臺程序訪問。

D5:使用請求重定向可以從本系統的某個資源訪問別的系統的某個資源。

D6:傳遞的數據類型不同:

轉發的request對象可以傳遞各種類型的數據,包括對象。

重定向只能傳遞字符串。

D7:調轉的時間不同:

轉發時:執行跳轉語句時就會立刻跳轉;

重定向:整個頁面執行完之後才執行跳轉。

應用場景:

1、轉發:訪問servlet處理業務邏輯,然後forward到jsp顯示處理結果,瀏覽器裏URL不變。

2、重定向:提交表單,處理成功後redirect到另一個jsp,防止表單重複提交,瀏覽器裏URL變了。


請求轉發全部代碼:

servlet1:

@WebServlet("/forward/s1")
public class Servlet1 extends HttpServlet{
	private static final long serialVersionUID = 1L;

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println(req);
		resp.setContentType("text/html;charset=utf-8");
		PrintWriter out=resp.getWriter();
		//===========================================
		//System.out.println("servlet1.service()");
		System.out.println("servlet1……before"+req.getParameter("name"));//控制檯輸出
		out.println("servlet1……before");//網頁輸出
		//---------------------------------------
		//請求轉發
		//沒有加:/,使用當前資源的相對路徑
		//資源路徑:/forward/s1,相對路勁,找到最後一個/,之前的部分就是相對路徑:/forward
		//req.getRequestDispatcher("/forward/s2").forward(req, resp);
		//使用請求轉發訪問WEB-INF中的資源
		req.getRequestDispatcher("/WEB-INF/in.html").forward(req, resp);
		//---------------------------------------
		System.out.println("Servlet1……after");
		out.println("Servlet1……after");
	}
}

 servlet2

@WebServlet("/forward/s2")
public class Servlet2 extends HttpServlet{
	private static final long serialVersionUID = 1L;

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println(req);
		//System.out.println("servlet2.service()");
		resp.setContentType("text/html;charset=utf-8");
		PrintWriter out=resp.getWriter();
		//===========================================
		System.out.println("Servlet2……"+req.getParameter("name"));
		out.println("Servlet2……");
	}
}

in.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>in.html</title>
</head>
<body>
	WEB-INF中的資源
</body>
</html>

重定向全部代碼:

servlet1

@WebServlet("/redirect/s1")
public class Servlet1 extends HttpServlet{
	private static final long serialVersionUID = 1L;

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println(req);
		resp.setContentType("text/html;charset=utf-8");
		PrintWriter out=resp.getWriter();
		//===========================================
		System.out.println("servlet1……before"+req.getParameter("name"));
		out.println("servlet1……before");
		//---------------------------------------
		//使用URL重定向跳轉到servlet2
		//resp.sendRedirect("/redirect/s2");
		//使用URL重定向進行跨域訪問百度
		resp.sendRedirect("https://baidu.com");
		//---------------------------------------
		System.out.println("Servlet1……after");
		out.println("Servlet1……after");
	}
}

 servlet2

@WebServlet("/redirect/s2")
public class Servlet2 extends HttpServlet{
	private static final long serialVersionUID = 1L;

	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println(req);
		//System.out.println("servlet2.service()");
		resp.setContentType("text/html;charset=utf-8");
		PrintWriter out=resp.getWriter();
		//===========================================
		System.out.println("Servlet2……"+req.getParameter("name"));
		out.println("Servlet2……");
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章