Spring MVC 轉發和重定向
本文介紹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並渲染
}
開啟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";
}
開啟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";
}
開啟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";
}
執行如下:
上面示例了使用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發出取餐要求。