服務端跳轉和客戶端跳轉


先描述一個場景:

你到一個機關辦事,一個是辦事窗口的那個人很不客氣地說,這個事你別找我,你找xxx窗口,然后你自己跑到xxx窗口,那個窗口的人直接給你辦了;還有一個是窗口的人和你說,你等下,他自己跑去找另一個人溝通一番,然后跑回來給你辦了。

前者是redirect重定向,后者便是forward轉發。

重定向redirect和轉發forward的流程圖如下:

(1)客戶端跳轉--重定向redirect

客戶端向服務器發送請求時,服務器返回一個“去訪問其他鏈接”的響應,客戶端根據此響應,第二次去訪問服務器,服務器給出最終的響應,所以總共有兩次請求。客戶端跳轉時,地址欄會發生改變。

使用response的rsendRedirect方法:

  重定向格式:response.sendRedirect("path");

(2)服務端跳轉--轉發forward

客戶端向服務器發送請求時,服務器發現當前資源給不出回應,服務器需要在內部請求另一個資源的跳轉,然后給出響應,這屬於1次請求,由於服務器跳轉與否客戶端並不知道,所以地址欄的url並不會改變。

使用requestDispatcher對象:

  轉發格式:request.getRequestDispatcher("path").forward(response,request)

使用jsp動作元素:

  <jsp:forward page=""/>

(3)轉發與重定向的區別

1.地址欄 
轉發:不變,不會顯示出轉向的地址 
重定向:會顯示轉向之后的地址

2.請求 

轉發:一次請求
重定向:至少提交了兩次請求

3.數據 
轉發:對request對象的信息不會丟失,因此可以在多個頁面交互過程中實現請求數據的共享 
重定向:request信息將丟失

4.原理 

請求轉發為服務器內部跳轉,跳轉一次,客戶端接收結果,而不改變url地址,而請求重定向則跳轉兩次,既將結果返回給客戶端,又使客戶端的url地址改變。 

請求轉發為為內部跳轉,頁面請求的對象一直存在,請求重定向則會結束上個頁面的請求。

請求轉發的傳參使用request對象方法setAttribute(“name”,value),請求重定向只需使用url傳參即可。

(4)實例:

例子1:

轉發:在返回值前面加"forward:"

從第一個轉發到其他的處理器,是不需要寫傳遞的數據的,因為數據共享

重定向:在返回值前面加"redirect:

 

實例2:

1、常規用法,返回一個View

 1 @RequestMapping(value="/testa", method=RequestMethod.GET)
 2 public String inputData(){
 3     return "testa"; //Spring框架找到對應的View並渲染
 4 }
 5 
 6 @RequestMapping(value="/testa", method=RequestMethod.POST)
 7 public String outputData(HttpServletRequest request){
 8     String userName = request.getParameter("name");
 9     String password = request.getParameter("pwd");
10     request.setAttribute("name", userName);
11     request.setAttribute("pwd", password);
12     return "testb"; //Spring框架找到對應的View並渲染
13 }

 

打開testa網頁:

 

 

 

 

輸入用戶名:spring,密碼:spring:

 

 

 

 

點擊登陸按鈕,頁面變為如下:

 

再次刷新,谷歌瀏覽器提示重新提交表單。

 

對比圖片,發現瀏覽器的輸入框中URL不變,但是不同情況下顯示不同的View。跳轉時Model共享(表單會被重復提交)。

2、轉發(forward)

 1 @RequestMapping(value="/testa", method=RequestMethod.GET)
 2 public String inputData(){
 3     return "testa"; //Spring框架找到對應的View並渲染
 4 }
 5 
 6 @RequestMapping(value="/testa", method=RequestMethod.POST)
 7 public String outputData(HttpServletRequest request){
 8     String userName = request.getParameter("name");
 9     String password = request.getParameter("pwd");
10     request.setAttribute("name", userName);
11     request.setAttribute("pwd", password);
12     //轉發到 /testb 的Controller方法(即outputDataX)上
13     return "forward:/testb"; 
14 }
15 
16 @RequestMapping(value="/testb", method=RequestMethod.POST)
17 public String outputDataX(HttpServletRequest request){
18     return "testb";
19 }


打開testa網頁:

 

 

 

輸入用戶名:spring,密碼:spring:

 

 

 

點擊登陸按鈕,頁面變為如下:

 

 

 

調試分析:forward后面跟一個資源。當程序運行到return “forward:/testb”時,會執行會執行該資源對應的方法outputDataX。
另外轉發時,瀏覽器的URL不變。

再次刷新,谷歌瀏覽器提示重新提交表單。

 

 

 

3、重定向(redirect)

 1 @RequestMapping(value="/testa", method=RequestMethod.GET)
 2 public String inputData(){
 3     return "testa"; //Spring框架找到對應的View並渲染
 4 }
 5 
 6 @RequestMapping(value="/testa", method=RequestMethod.POST)
 7 public String outputData(HttpServletRequest request){
 8     String userName = request.getParameter("name");
 9     String password = request.getParameter("pwd");
10     request.setAttribute("name", userName);
11     request.setAttribute("pwd", password);
12     //重定向到 /testb 的Controller方法(即outputDataY)上
13     return "redirect:/testb"; 
14 }
15 
16 @RequestMapping(value="/testb", method=RequestMethod.POST)
17 public String outputDataX(HttpServletRequest request){
18     return "testb";
19 }
20 
21 @RequestMapping(value="/testb", method=RequestMethod.GET)
22 public String outputDataY(HttpServletRequest request){
23     return "testb";
24 }


打開testa網頁:

 

 

 

輸入用戶名:spring,密碼:spring:

 

 

 

點擊登陸按鈕,頁面變為如下:

 

 

 

調試分析:redirect后面跟一個資源。當執行到return “redirect:/testb”時,會執行該資源對應個方法outputDataY。由於重定向Model不共享,所以頁面無數據顯示。
另外重定向后瀏覽器的輸入框中URL也發生變化。

刷新后,谷歌瀏覽器沒有提示重新提交表單

 

 

 

總結:
常說的可以通過redirect: URL防止重復提交表單,就是上面過程的意思。
原理是對於redirect而言,Request的attribute不會被傳遞,放到session中,session在跳到頁面后馬上移除對象。所以你刷新一下后這個值就會丟掉。

如果你希望Request的attribute被傳遞,可以使用RedirectAttributes類。

 1 @RequestMapping(value="/testa", method=RequestMethod.GET)
 2 public String inputData(){
 3     return "testa"; //Spring框架找到對應的View並渲染
 4 }
 5 
 6 @RequestMapping(value="/testa", method=RequestMethod.POST)
 7 public String outputData(HttpServletRequest request, RedirectAttributes     redirectAttributes){
 8     String userName = request.getParameter("name");
 9     String password = request.getParameter("pwd");
10     request.setAttribute("name", userName);
11     request.setAttribute("pwd", password);
12     //重定向到 /testb 的Controller方法(即outputDataY)上
13     //重定向傳遞參數的兩種方法
14     redirectAttributes.addAttribute("name", userName);
15     redirectAttributes.addFlashAttribute("pwd", password);
16 
17     return "redirect:/testb"; 
18 }
19 
20 @RequestMapping(value="/testb", method=RequestMethod.POST)
21 public String outputDataX(HttpServletRequest request){
22     return "testb";
23 }
24 
25 @RequestMapping(value="/testb", method=RequestMethod.GET)
26 public String outputDataY(HttpServletRequest request){
27     String userName = request.getParameter("name");
28     request.setAttribute("name", userName);
29     return "testb";
30 }

 

運行如下:

 

 

 

上面示例了使用RedirectAttributes傳遞參數的兩種方法:
1. 使用RedirectAttributes類的addAttribute方法傳遞參數會跟隨在URL后面,如上圖谷歌瀏覽器所示,URL為http://localhost:8080/testb?name=spring
2. 使用RedirectAttributes類的addFlashAttribute方法傳遞參數不會跟隨在URL后面,會把該參數值暫時保存於session,待重定向URL獲取該參數后從session中移除,這里的redirect必須是方法映射路徑,jsp無效。你會發現redirect后的jsp頁面中pwd只會出現一次,刷新后pwd再也不會出現了。下圖為刷新后的結果,密碼pwd顯示為空。這驗證了上面說的,pwd在被訪問后就會從session中移除。對於防止重復提交可以使用此方法。

 

參考鏈接:

https://ask.csdn.net/questions/376121

https://blog.csdn.net/jiangshangchunjiezi/article/details/88998809

https://blog.csdn.net/webzhuce/article/details/54564608


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM