如何在Spring MVC中在两个控制器之间传递对象?

5

实际上,我已经通过谷歌搜索了解如何在Spring MVC中从一个controller传递数据到另一个controller,并发现使用flash attributes可以完成此任务。它包括声明一个带有RequestMapping=GET的控制器和另一个带有RequestMapping=POST的控制器。我已在我的控制器中测试了这段代码,并且它有效。

 @RequestMapping(value ="/ajouter", method = RequestMethod.POST)  
     public String add(@ModelAttribute User user,final RedirectAttributes redirectAttributes) {  
         redirectAttributes.addFlashAttribute("user", user);
      return "redirect:/account";  
     }  

还有另一个:

 @RequestMapping(value ="/account", method = RequestMethod.GET)  
     public String addAccount(@ModelAttribute("user") User user,@ModelAttribute Account account) { 
                System.out.println(user.getId());

      return "account";  
     }  

但我还有另一个案例:我有两个JSP页面:

第一个页面将用户添加到数据库。我想要恢复刚插入的用户的ID,将其设置为帐户的外键(在提交添加用户页面后,会出现第二个添加帐户的页面)。

我已经测试过以下代码:

这个控制器将把一个用户插入到数据库中,并恢复刚插入的用户。

 @RequestMapping(value ="/addUser", method = RequestMethod.POST)  
     public String add(@ModelAttribute User user,final RedirectAttributes redirectAttributes) {  
        this.userService.insertData(user);
         redirectAttributes.addFlashAttribute("user", user);
      return "redirect:/account";  
     }      

这个控制器将在数据库中插入一个账户,但无法恢复刚刚插入的用户ID。

     @RequestMapping(value= "/ajouterCompte", method = RequestMethod.POST)
public String addCompte(@ModelAttribute("account") Account compte,@ModelAttribute("user") User user){
    System.out.println(user.getId());  //this code shows 0

    System.out.println(compte.getPwd());

     String hashPassword = passwordEncoder.encode(compte.getPwd());
     System.out.println(hashPassword);
     compte.setPwd(hashPassword);
    compte.setId(user.getId()); 
       this.compteService.insertCompte(compte);

    return "redirect:/users";

}

我猜问题在于这两个控制器都使用了method = RequestMethod.POST方法声明,而应该有一个是GET方法,另一个是POST方法。但是这种情况下,我该如何获取用户的ID并将其插入到数据库中呢? 当我使用GET方法声明第二个控制器时,数据库插入失败! 请帮忙解决这个问题 :(

1
问题在于Flash属性已经被清除。它仅适用于第一个请求,而POST是第二个请求,因此没有更多的Flash范围。只需将用户ID作为隐藏字段添加到您的表单中,并按此方式检索它。或者在显示帐户页面的GET方法中(在GET之后执行的方法)重新添加用户作为Flash属性(我认为有点不干净)。我可能会在get方法中创建一个“账户”,并根据用户填充所需的字段,然后将这些属性放入表单中的隐藏字段中(或将“账户”作为会话属性)。 - M. Deinum
非常感谢您,您救了我的一天! - pietà
你能否请在回复中发布翻译内容,以便我可以将你的答案标记为正确答案? - pietà
1个回答

5

设置为闪存属性的对象仅在设置后的第一次请求中可用。这也如参考指南中所解释的那样。

假设在您的帐户控制器中有一个基于GET的方法用于/account,则应在该点使用信息预填充Account

public String account(@ModelAttribute("user") User user, Model model) {
    Account account = new Account();
    account.setId(user.getId());
    model.addAttribute("account", account);
    return "account";
}

现在,您可以使用@SessionAttribute("account")注释您的控制器,以便在请求之间将Account存储在会话中。如果是这样,则必须修改POST处理方法以包括SessionStatus对象,并在存储后调用setComplete()
public String addCompte(@ModelAttribute("account") Account compete, SessionStatus sessionStatus){
    ...
    sessionStatus.setComplete();
    return "redirect:/users";
}

或者将预填信息存储在隐藏的表单字段中,以便随后的请求一同传递,并且可以重构账户(Account)

<form:hidden path="id" />

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接