在处理完 POST 请求后,通常来讲一个最佳实践就是执行一下重定向。除了其他的一些因素外,这样做能够防止用户点击浏览器的刷新按钮或后退箭头时,客户端重新执行危险的 POST 请求。

从发起重定向的方法传递数据给处理重定向方法中:

  • 使用 URL 模板以路径变量和/或查询参数的形式传递数据;
  • 通过 flash 属性发送数据。

通过 URL 模板进行重定向

@RequestMapping(value="/register", method=POST);  
public String processRegistration(  
        Spitter spitter, Model model) {  
    spitterRepository.save(spitter);  
  
    model.addAttribute("username", spitter.getUsername());  
    return "redirect:/spitter/{username}";  
}

现在,username 作为占位符填充到了 URL 模板中,而不是直接连接到重定向 String 中,所以 username 中所有的不安全字符都会进行转义。这样会更加安全,这里允许用户输入任何想要的内容作为 username,并会将其附加到路径上。

除此之外,模型中所有其他的原始类型值(String 和数字的值)都可以添加到 URL 中作为查询参数,例如:

@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}";  
}

因为模型中的 spitterId 属性没有匹配重定向 URL 中的任何占位符,所以它会自动以查询参数的形式附加到重定向 URL 上。

如果 username 属性的值是 habuma 并且 spitterId 属性的值是 42,那么结果得到的重定向 URL 路径将会是 /spitter/habuma?spitterId=42

使用 flash 属性

使用flash 属性,在重定向中发送实际的对象。

@RequestMapping(value="/register", method=POST)  
public String processRegistration(  
        Spitter spitter, RedirectAttribute model) {  
    spitterRespository.save(spitter);  
    model.addAttribute("username", spitter.getUsername());  
    model.addFlashAttribute("spitter", spitter);
    return "redirect:/spitter/{username}";  
}

处理重定向的方法就能从模型中访问 Spitter 对象了,就像获取其他的模型对象一样,例如:在从数据库中查找之前,它会首先从模型中检查 Spitter 对象:

@RequestMapping(value="/{username}", method=GET)  
public String showSpitterProfile(  
        @PathVariable String username, Model model) {  
    if (!model.containsAttribute("spitter")) {  
        model.addAttribute(spitterRepository.findByUsername(username));  
    }  
    return "profile";  
}

WinRT
21 声望4 粉丝

临渊羡鱼,不如退而结网