1. 程式人生 > >Spring MVC 轉發和重定向

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發出取餐要求。