Spring Controller:如何正确地重定向到动作并包含模型参数?

rob*_*trv 2 java spring spring-mvc

我有一个弹簧控制器UserController,我有以下方法(业务逻辑不包括在内):

    @RequestMapping(value = "new", method = RequestMethod.GET)
public String getNewUserForm(Model model) {
    model.addAttribute("action", "Create");
    model.addAttribute(new User());
    return "users/edit";
}

@RequestMapping(value = "create", method = RequestMethod.POST)
public String getCreateUser(@ModelAttribute("user") User user, BindingResult result, RedirectAttributes attr) {
    attr.addFlashAttribute("user", user);
    return "redirect:view";
}

@RequestMapping(value = "view", method = RequestMethod.GET)
public String getViewUser(Model model) {
    return "users/view";
}
Run Code Online (Sandbox Code Playgroud)

我最终得到了三个"动作"(新的,创造和视图).我想要实现的是:app.com/users/new在浏览器中输入.将users/edit显示"创建用户"表单.提交表单时,它会调用users/create (POST).成功创建用户后,我想将用户转发到users/view,并在不可编辑的页面中显示输入数据.我不能只返回view因为那时网址仍然存在app.com/users/create.我想读它app.com/users/view.

现在,我正在使用一个RedirectAttributes对象,结合返回redirect:view,它的工作原理.但感觉应该有更好的方法来实现这一目标.我尝试使用redirect:view没有RedirectAttributes,模型不可用.

另一种方法是在url中传递用户id(例如:),app.com/users/view/1并从数据库中加载数据.但考虑到我已经拥有该对象的最新版本,这似乎是对数据库的不必要的往返.我将为"漂亮的网址"实现此功能,但我不想选择不加载用户对象(如果可用).

像这样的东西:

    @RequestMapping(value = "view", method = RequestMethod.GET)
public String getViewUser(Model model, @RequestParam(required = false) String id) {

    if(!model.containsAttribute("user")){
        //get it from the db with the optional request parameter
    }

    return "users/view";
}
Run Code Online (Sandbox Code Playgroud)

我的方法是推荐的吗?还是我看这完全错了?

JB *_*zet 5

更好的方法是重定向到app.com/users/view/1.

首先,因为你有最新的变化,你做的模型,而不是那些其他并发用户可能会同时进行.

其次,因为它使您的应用程序无状态,因此同时更具可扩展性和简单性.

第三,因为视图页面可能需要比编辑页面更多的关于用户的信息.有一个大的详细信息页面显示用户的许多关联,但在编辑页面中只有一些可修改的信息.因此,保存编辑页面的模型以使其可用于视图页面是不够的.

第四,因为这样,显示用户细节的逻辑在一个地方,并且只有一个可能的URL来做到这一点.

第五,因为这样,用户可以将URL加入书签,或通过电子邮件将其发送给某人,如果他稍后返回此URL,它将起作用.在您当前的解决方案中,只有在您之前编辑过用户时,该URL才有效.