2

我有一个弹簧控制器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";
}

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

现在,我正在使用一个RedirectAttributes对象,结合返回redirect:view,它可以工作。但感觉应该有更好的方法来实现这一点。我尝试使用redirect:viewwithoutRedirectAttributes并且该模型不可用。

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

像这样的东西:

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

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

4

1 回答 1

5

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

首先,因为您拥有对模型所做的最新更改,但没有其他并发用户可能同时进行的更改。

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

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

第四,因为这种方式,显示用户详细信息的逻辑在一个地方,并且只有一个可能的 URL 可以做到这一点。

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

于 2012-05-31T06:10:38.160 回答