-
处理完Post请求后,一般要进行重定向。防止因为浏览器刷新或回退时重新执行Post请求
-
使用转发forward时,由于控制器方法和视图处理的是同一个request,所以转发的过程中,request的属性得以保存
-
控制器方法中的Model对象最终是以请求参数的形式复制到请求中的,因此发生重定向时,不能用Model传递数据
-
常用的跨重定向传递数据的方式有2种
(1) 通过URL模板以路径变量和/或查询参数的形式传递数据(简单,数据少的情况)
(2) 通过Spring的flash属性传递数据
-
通过URL模板进行重定向数据传输
(1) 之前采取的方法是 return ("redirect:/spitter/" + spitter.getUserName());
这样做的危险支出在于userName中的不安全字符不会进行转义,造成不安全的情况
(2) 示例
@Controller @RequestMapping("/spitter") public class SpitterController { ... @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}"; } ... }
首先在模型Model中添加两个属性 username和spitterId。其中,username作为占位符填充到了URL模板中,而不是直接进行字符串连接,这样username中的所有不安全字符都会进行转义,然后附加到路径上;
spitterId属性没有匹配重定向URL中的任何占位符,它会自动以查询参数的形式附加到重定向URL上;
所以,如果 username="bochen", spitterId="1",那么重定向的URL地址为 "/spitter/bochen?spitterId=1"
-
通过flash属性进行重定向数据传输
(1) URL模板的方式只能传递简单的字符串,不能传递对象
(2) 能够长期存在的是 session,并且可以跨多个请求。所以我们应该在重定向前把对象放入session,重定向后从session取出对象,然后将session清理掉
(3) spring的flash属性的底层原理同(2),但是它帮我们做好了这些工作,flash属性会自动一直携带数据一直到下一次请求然后消失。具体地,重定向前,所有的flash属性都会复制到session中;重定向后,flash属性被取出,并从会话转移到模型Model中,这就和获取其他的Model对象一样了
(4) 示例
@Controller @RequestMapping("/spitter") public class SpitterController { ... @RequestMapping(value = "/register", method = POST) public String processRegistration( @RequestPart(value = "profilePicture") MultipartFile profilePicture, @Valid Spitter spitter, Errors errors, RedirectAttributes redirectAttributes) throws IllegalStateException, IOException { if (errors.hasErrors()) { return "registerForm"; } spitterRepository.save(spitter); profilePicture.transferTo(new File("/" + spitter.getUsername() + ".png")); redirectAttributes.addAttribute("username", spitter.getUsername()); redirectAttributes.addFlashAttribute("spitter", spitter); return "redirect:/spitter/{username}"; } @RequestMapping(value = "/{username}", method = GET) public String showSpitterProfile(@PathVariable String username, Model model) { if (!model.containsAttribute("spitter")) { model.addAttribute(spitterRepository.findByUsername(username)); } return "profile"; } ... }
RedirectAttribute接口扩展了Model接口,增加了几个关于flash的方法。它可以像Model一样addAttribute(),这和URL模板传递数据方式一样;addFlashAttribute()方法可以传递数据到session中,实现跨重定向数据传输;
当重定向到 /spitter/{username} 时,会被控制器的showSpitterProfile()处理。此时这个方法会读到路径变量username;同时重定向后,由于flash属性已经被取出,并且从会话转移到了Model,所以model对象也可以读到key为"spitter"的对象,这样就无需重新从数据库中再次查找了,直接交给profile视图渲染
网友评论