简体   繁体   English

Spring MVC-@SessionAttributes和status.setComplete()

[英]Spring MVC - The @SessionAttributes and status.setComplete()

I'm facing a problem I don't really know how to solve. 我面临着一个我真的不知道该如何解决的问题。 I am developing a Bug Tracker (learning purposes only). 我正在开发一个Bug跟踪器(仅供学习)。 I have a page to create a new issue and one page to edit an issue. 我有一个页面可以创建一个新问题,一个页面可以编辑一个问题。 Both, for now, have their own controllers. 两者目前都有自己的控制器。

EditIssueController.java EditIssueController.java

@Controller
@RequestMapping(value = "/issues/{issueId}")
@SessionAttributes("issuePackage")
public class EditIssueController {

    @Autowired
    private IssueService issueService;

    [...]

    @ModelAttribute("issuePackage")
    public IssueTagEnvironment populateIssue (@PathVariable("issueId") Integer issueId) {

        IssueTagEnvironment issueTagEnv = new IssueTagEnvironment();
        issueTagEnv.setIssue(issueService.getIssueById(issueId));

        return issueTagEnv;
    }

    @InitBinder
    public void initBinder (WebDataBinder binder) {

        [...]
    }

    @RequestMapping(value = "/edit", method = RequestMethod.GET)
    public ModelAndView editIssue (@PathVariable("issueId") Integer issueId,
                                   @ModelAttribute("issuePackage") IssueTagEnvironment issuePackage) {

        ModelAndView mav = new ModelAndView("/issues/EditIssue");

        [...]

        IssueTagEnvironment issueTagEnv = new IssueTagEnvironment();
        issueTagEnv.setIssue(issueService.getIssueById(issueId));

        [...]
        mav.addObject("issuePackage", issueTagEnv);

        return mav;
    }

    @RequestMapping(value = "/edit", method = RequestMethod.POST)
    public String updateIssue (@ModelAttribute("issuePackage") IssueTagEnvironment issuePackage,
                               BindingResult result) {

        if (result.hasErrors() == true) {
            return "redirect:/issues/{issueId}/edit";
        }

        issueService.updateIssue(issuePackage.getIssue());

        return "redirect:/issues/{issueId}";
    }
}

CreateIssueController.java CreateIssueController.java

@Controller
@SessionAttributes("issuePackage")
public class CreateIssueController {

    @Autowired
    private IssueService issueService;

    [...]

    @ModelAttribute("issuePackage")
    public IssueTagEnvironment populateNewIssue () {

        return new IssueTagEnvironment();
    }

    @InitBinder
    public void initBinder (WebDataBinder binder) {

        [...]
    }

    @RequestMapping(value = "/issues/CreateIssue", method = RequestMethod.GET)
    public ModelAndView createIssueGet (@ModelAttribute("issuePackage") IssueTagEnvironment issuePackage) {

        ModelAndView mav = new ModelAndView("/issues/CreateIssue");

        [...]

        issuePackage.getIssue().setReporter(SecurityUtils.getCurrentUser());

        return mav;
    }

    @RequestMapping(value = "/issues/CreateIssue", method = RequestMethod.POST)
    public String createIssuePost (@ModelAttribute("issuePackage") IssueTagEnvironment issuePackage,
                                   BindingResult result,
                                   SessionStatus status) {

        if (result.hasErrors() == true) {
            return "redirect:/issues/CreateIssue";
        }

        [...]

        issueService.createIssue(issuePackage.getIssue());

        status.setComplete();
        return "redirect:/issues/" + issuePackage.getIssue().getId();
    }

}

So far everything seems correct (and in indeed works). 到目前为止,一切似乎都是正确的(并且确实可行)。 But here are the dragons: 但是这是龙:

  • I am within an "edit" page changing data from an existing issue. 我在“编辑”页面中,可更改现有问题的数据。
  • Instead of submitting the changes I decide to press the "Go Back" button from the navigator. 我决定不提交更改,而是决定从导航器中按“返回”按钮。
  • Right after that action (Go Back), I decide to create a new issue and... Here it is! 在该操作(返回)之后,我决定创建一个新的问题,然后...就在这里! The form to create a new issue isn't empty but filled with the information of the previous "edited-but-not-submitted" issue. 创建新问题的表单并非空白,而是充满了先前“已编辑但未提交”问题的信息。

I understand what the problem is: The controller is not completing the session/status by executing status.setComplete() . 我了解问题所在: controller未通过执行status.setComplete()来完成会话/状态。

My question here is, how to solve this problem? 我的问题是,如何解决这个问题?

Thanks in advance to the community! 在此先感谢社区!

For your current example, it is easy to fix , just change createIssueGet method to : 对于您当前的示例,很容易修复,只需将createIssueGet方法更改为:

public ModelAndView createIssueGet () {

    ModelAndView mav = new ModelAndView("/issues/CreateIssue");
    IssueTagEnvironment issuePackage = new IssueTagEnvironment();

    ModelAndView mav = new ModelAndView("/issues/CreateIssue");
    mav.addAttribute("issuePackage", issuePackage);

    [...]

    [...]
}

That way you are sure that you always use a fresh IssueTagEnvironment object in that controller. 这样,您可以确保始终在该控制器中使用新的IssueTagEnvironment对象。 And Spring will put it in session as you put it in model. Spring将其放入会话中,就像您将其放入模型中一样。

But the problem still remains : if you do not properly call status.setComplete() , you leave in session an object that should not be there, and like you said dragons may be there 但问题依然存在:如果不正确地调用status.setComplete()你在会议的对象, 应该存在离开,像你说的龙可能有

I stopped using @SessionAttributes for that reason, and only use a hidden field (for the id) and a Converter from the id to a full object using the service layer, hoping it should be in cache and does not hit the database. 出于这个原因,我停止使用@SessionAttributes ,而仅使用一个隐藏字段(用于id)和一个使用服务层从id到完整对象的Converter ,希望它应该在缓存中并且不会访问数据库。 Not really nice, but not really worse than that. 不太好,但也不比这差。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM