本文轉載自“獨釣漁”的部落格
(一) java web程式設計中的forward和redirect
在java web程式設計中跳轉有兩種:” 1:forward ,2:redirect。
我的了解是:forward是請求轉發,redirect是重定向。
forward(請求轉發):
可以看出是統一次請求,當request到達這個servlet後又看到又forward又将目前的request繼續轉發到forward的位址去,在這個過程中,可以利用request.setAttribute設定一些轉發的屬性,都會被帶到目标servlet中去,目标servlet可以通過request.getparam來擷取原始的request請求,也可通過request.getAttribute來擷取轉發過程中的設定的屬性。
redirect(重定向):
redirect重定向,基本可以了解為響應了301,302等之類的,你重新安裝redirect新位址去重新請求。所有一般來說redirect不能帶model資訊,無法像forward利用request.setAttribute來設定一些轉發屬性,如果重定向到外部應用隻有通過GET送出方式傳遞資料,如果是重定向到應用自己内部的其它位址,則還可以利用session實作資料傳遞。
自己總結:
可以了解為forward過程發生在request過程中,redirect發生在response過程中。從浏覽器來看,forward是一次請求,轉發過程在Servlet容器中完成,所有目标Servlet傳回資訊就會在目前的請求response中,浏覽器位址不變;而redirect是重定向,這次請求的servlet響應,響應的response内容為一個redirect, 浏覽器收到這個redirect後重新發起一個新的request請求到redirect這個目标位址,在由這個目标位址的Servlet來響應傳回的内容。也正是應為如此,forward(請求轉發)隻能用在同一個應用中。而redirect可以重定向到其他外部應用中去。
在redirect過程中是一次完全重新的GET請求,如果要在redircet中帶資料轉發隻有這一種方式(利用GET請求時把參數帶上)。
eg1 redirect:/path/list?prama1=values1&prama2=values2
eg2 redirect:http://api.xxx.com/path/list?prama1=values1&prama2=values2
如果redirect是以/開始這會認為是同一應用中(如eg1),那麼他們直接的資料傳遞還可以利用session實作。
(二) 說說springmvc中的forward和redirect
springmvc完成forward和redirect時本質也是一樣。
Spring MVC 中,我們在傳回邏輯視圖時,架構會通過 viewResolver 來解析得到具體的 View,然後向浏覽器渲染。假設邏輯視圖名為 hello,通過配置,我們配置某個 ViewResolver 如下:
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<description>
假如邏輯試圖名為 "hello",是以 viewResolver 将解析成 /WEB-INF/jsp/hello.jsp
</description>
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
實際上,架構還是通過 forward 的方式轉發到了 /WEB-INF/jsp/hello.jsp。如果邏輯視圖名是 /hello,實際還是轉發到了 /WEB-INF/jsp/hello.jsp,即 /WEB-INF/jsp//hello.jsp 等同于 /WEB-INF/jsp/hello.jsp。
現在有個問題,如果 /hello 就是某個 controller 的映射,我想轉發到這個 controller,怎麼辦?我們可以通過forward 字首來達到轉發到其它資源的目的:
public String handle() {
// return "forward:/hello" => 轉發到能夠比對 /hello 的 controller 上
// return "hello" => 實際上還是轉發,隻不過是架構會找到該邏輯視圖名對應的 View 并渲染
// return "/hello" => 同 return "hello"
return "forward:/hello";
}
同理,如果我們想重定向到某個資源,我們可以通過 redirect 字首來達到重定向到其它資源的目的:
public String handle() {
// 重定向到 /hello 資源
return "redirect:/hello";
}
forward(請求轉發)因為有request.setAttribute方法是以請求轉發過程中增加一些請求屬性都是非常容易的事情。
redirect(重定向)要想在重定向過程中傳遞資料相對麻煩得多。
1,redirect到外部應用時,隻有通過get送出方式傳遞資料(如eg2)。
2,redircet到應用自己的其它位址時,可以通過get送出方式傳遞資料(如eg1),還可通過session方式傳遞資料。
Spring MVC中有RedirectAttributes類專門用于重定向之後還能帶參數跳轉的的工具類。
他有兩種帶參的方式:
第一種:
redirectAttributes.addAttributie(“prama”,value); 這種方法相當于在重定向連結位址追加傳遞的參數,例如:
redirectAttributes.addAttributie("prama1",value1);
redirectAttributes.addAttributie("prama2",value2);
return:"redirect:/path/list"
以上重定向的方法等同于 return:”redirect:/path/list?prama1=value1&prama2=value2”
第二種:
redirectAttributes.addFlashAttributie(“prama”,value); 這種方法是隐藏了參數,連結位址上不直接暴露,但是能且隻能在重定向的 “頁面” 擷取prama參數值。其原理就是放到session中,session在跳到頁面後馬上移除對象。如果是重定向一個controller中是擷取不到該prama屬性值的。除非在controller中用(@RequestPrama(value = “prama”)String prama)注解,采用傳參的方式。頁面獲值例如:
redirectAttributes.addFlashAttributie("prama1",value1);
redirectAttributes.addFlashAttributie("prama2",value2);
return:"redirect:/path/list.jsp"
在以上參數均可在list.jsp頁面使用EL表達式擷取到參數值${prama*}
controller獲得redirectAttributes重定向的值例如:
redirectAttributes.addFlashAttributie("prama1",value1);
redirectAttributes.addFlashAttributie("prama2",value2);
return:"redirect:/path/list"
@RequestMapping("list")
public List<Student> list(@RequestPrama(value = "prama1")String prama1,
@RequestPrama(value = "prama2")String prama2,...
){
//TODO
}
這可以在controller中擷取redirect傳過來的值。