服務端跳轉和客戶端跳轉

先描述一個場景:web

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

前者是redirect重定向,後者即是forward轉發。瀏覽器

重定向redirect和轉發forward的流程圖以下:服務器

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

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

使用response的rsendRedirect方法:框架

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

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

客戶端向服務器發送請求時,服務器發現當前資源給不出迴應,服務器須要在內部請求另外一個資源的跳轉,而後給出響應,這屬於1次請求,因爲服務器跳轉與否客戶端並不知道,因此地址欄的url並不會改變。spa

使用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:

一、常規用法,返回一個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共享(表單會被重複提交)。

二、轉發(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不變。

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

 

 

 

三、重定向(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

相關文章
相關標籤/搜索