chapter07_SpringMVC的高级技术_4_跨重定向请求传递数据

  • 处理完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中的所有不安全字符都会进行转义,然后附加到路径上;

    扫描二维码关注公众号,回复: 5296433 查看本文章

    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视图渲染

猜你喜欢

转载自blog.csdn.net/captxb/article/details/87880168