本文介紹Spring MVC中轉發和重定向的區別。
轉發和重定向
開始Java EE時,可能會對轉發(forward)和重定向(redirect)這個兩個概念不清楚。本文先通過代碼實例和運行結果圖片感性 認識二者的區別,然后給出二者的定義。
1、常規用法,返回一個View
@RequestMapping(value="/testa", method=RequestMethod.GET)
public String inputData(){
return "testa"; //Spring框架找到對應的View並渲染
}
@RequestMapping(value="/testa", method=RequestMethod.POST)
public String outputData(HttpServletRequest request){
String userName = request.getParameter("name");
String password = request.getParameter("pwd");
request.setAttribute("name", userName);
request.setAttribute("pwd", password);
return "testb"; //Spring框架找到對應的View並渲染
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
打開testa網頁:

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

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

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

對比圖片,發現瀏覽器的輸入框中URL不變,但是不同情況下顯示不同的View。跳轉時Model共享(表單會被重復提交)。
2、轉發(forward)
@RequestMapping(value="/testa", method=RequestMethod.GET)
public String inputData(){
return "testa"; //Spring框架找到對應的View並渲染
}
@RequestMapping(value="/testa", method=RequestMethod.POST)
public String outputData(HttpServletRequest request){
String userName = request.getParameter("name");
String password = request.getParameter("pwd");
request.setAttribute("name", userName);
request.setAttribute("pwd", password);
//轉發到 /testb 的Controller方法(即outputDataX)上
return "forward:/testb";
}
@RequestMapping(value="/testb", method=RequestMethod.POST)
public String outputDataX(HttpServletRequest request){
return "testb";
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
打開testa網頁:

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

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

調試分析:forward后面跟一個資源。當程序運行到return “forward:/testb”時,會執行會執行該資源對應的方法outputDataX。
另外轉發時,瀏覽器的URL不變。
再次刷新,谷歌瀏覽器提示重新提交表單。

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

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

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

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

總結:
常說的可以通過redirect: URL防止重復提交表單,就是上面過程的意思。
原理是對於redirect而言,Request的attribute不會被傳遞,放到session中,session在跳到頁面后馬上移除對象。所以你刷新一下后這個值就會丟掉。
如果你希望Request的attribute被傳遞,可以使用RedirectAttributes類。
@RequestMapping(value="/testa", method=RequestMethod.GET)
public String inputData(){
return "testa"; //Spring框架找到對應的View並渲染
}
@RequestMapping(value="/testa", method=RequestMethod.POST)
public String outputData(HttpServletRequest request, RedirectAttributes redirectAttributes){
String userName = request.getParameter("name");
String password = request.getParameter("pwd");
request.setAttribute("name", userName);
request.setAttribute("pwd", password);
//重定向到 /testb 的Controller方法(即outputDataY)上
//重定向傳遞參數的兩種方法
redirectAttributes.addAttribute("name", userName);
redirectAttributes.addFlashAttribute("pwd", password);
return "redirect:/testb";
}
@RequestMapping(value="/testb", method=RequestMethod.POST)
public String outputDataX(HttpServletRequest request){
return "testb";
}
@RequestMapping(value="/testb", method=RequestMethod.GET)
public String outputDataY(HttpServletRequest request){
String userName = request.getParameter("name");
request.setAttribute("name", userName);
return "testb";
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
運行如下:

上面示例了使用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中移除。對於防止重復提交可以使用此方法。
定義
作為一個經驗豐富的servlet/JSP程序員,必須知道轉發和重定向的區別。 轉發比重定向快,因為重定向經過客服端,而轉發沒有。但是,又是采用重定向更好,若需要重定向到一個外部網站,則無法使用轉發。
個人理解:好比服務器窗口A點餐,窗口B取餐。轉發就是瀏覽器到服務器窗口A點餐,點完餐后,服務器內部從窗口B取餐,把飯菜直接給瀏覽器。重定向就是瀏覽器到服務器窗口A點餐,服務器不幫助瀏覽器從窗口B取餐,而是告知瀏覽器到B取餐。瀏覽器得到信息后再向窗口B發出取餐要求。
