- redirect
- 處理完POST後,通常都會執redirect。這樣能夠防止點擊refresh或back時,client重新執行危險的POST
- 通常使用redirect: prefix能夠重新定位
- 問: 如何發送data給redirect的目標method?
- 答: 當一個controller method完成之後,這個method所指定的model data將會複製到request中,並作為request的property,request會forward到view上。因為controller method和view處理的是同一個request,所以在forward過程中,request property也能夠保存。但當controller是redirect時,原始的request就消失了,並且會發起一個新的GET request。原始request中所帶有的model data也跟著request消失了,在新的request上,沒有任何的model data,這個request必須要自己計算data
- 有一些方法能夠使用redirect但又能夠將data傳遞給redirect的method中
- 使用URL template 以path variable或或query parameter的形式
- 透過flash attribute發送data
return "redirect:/spitter/" + spitter.getUsername();
- 透過URL template進行redirect
- 使用String做連結,但有點危險
- Spring還提供model的方式來定義redirect URL
- 除此之外,model中任何primitive values都可以加到URL中作為query parameters
- 下例表示,假設還需要使用到id
- return的String沒有太大變化,但是因為model中的spitterId attribute沒有redirect URL中的任何placeholder,所以會自動以query parameter的形式附加到redirect URL
- 例如username如果是habuma,且spitterId是42,則redirect URL path: /spitter/habuma?spitterId=42
- 使用path variable及query parameter的形式只能拿來發送簡單的值,像是String或數字,並沒有辦法發送更複雜的值,但這是flash能夠提供幫助的領域
- Flash attribute
- 假設這次不發送ID及username,而是要發送Spitter object。
- 如果只發送ID,則需要到db找Spitter object,但是在redirect之前其實已經得到Spitter object
- Spitter object只能設定為model中的attribute,但model會因為redirect而lost,因此必須將Spitter object放在一個位置,能夠在redirect的過程中存活
- 有個方法是,將Spitter放到session中,session能夠長期存在,且可以跨多個session,所以在redirect之後可以從session取出attribute
- 但Spring認為並不需要管理這些data,相反的,Spring提供了將data發送到flash attribute的功能,按照定義,flash attribute會一直攜帶這些data直到下一次的request,然後才會消失
- Spring提供一種透過RedirectAttributes設定flash attribute的method,這是Spring3.1引入的sub-interface of Model。RedirectAttributes提供了model的所有功能,還有幾個method可以設定flash attribute
- 可以使用addFlashAttribute()將Spitter加到model
- 也可以直接寫成,讓key自行從type決定
- 在redirect之前,所有的flash attribute都會複製到session中。而redirect之後,存在session中的flash attribute就會被取出,並從session轉移到model中,這樣一來redirect method就能從model中取得Spitter object,就像取得其他的model object依樣
- 下面黃色部份,在從資料庫找user之前,會先確認model裡面是否有spitter attribute,如果有的話,則什麼都不用做,直接會將spitter object傳遞到view
return "redirect:/spitter/{username}";
@RequestMapping(value = "/register", method = POST) public String processRegistration( Spitter spitter, Model model) { spitterRepository.save(spitter); model.addAttribute("username", spitter.getUsername()); return "redirect:/spitter/{username}"; }
@RequestMapping(value = "/register", method = POST) public String processRegistration(Spitter spitter, Model model) { spitterRepository.save(spitter); model.addAttribute("username", spitter.getUsername()); model.addAttribute("spitterId", spitter.getId()); return "redirect:/spitter/{username}"; }
@RequestMapping(value="/register", method=POST) public String processRegistration(Spitter spitter, RedirectAttributes model) { spitterRepository.save(spitter); model.addAttribute("username", spitter.getUsername()); model.addFlashAttribute("spitter", spitter); // spitter object加到model中 ,將spitter當作key return "redirect:/spitter/{username}"; }
model.addFlashAttribute(spitter);
from Spring in action 4
@RequestMapping(value = "/{username}", method = GET) public String showSpitterProfile( @PathVariable String username, Model model) { if (!model.containsAttribute("spitter")) { model.addAttribute( spitterRepository.findByUsername(username)); } return "profile"; }
沒有留言:
張貼留言