【问题标题】:Deal with overlapping @SessionAttributes names?处理重叠的@SessionAttributes 名称?
【发布时间】:2019-03-05 09:28:51
【问题描述】:

我怎样才能使@SessionAttributes 被限定到它们各自的控制器,或者在控制器之间过早切换工作流时清理@SessionAttributes

例子:

用户进入网页编辑字典并进入DictionaryController.java,它创建一个DictionaryForm.java对象并将其存储在“表单”下的@SessionAttributes

通常,字典条目在 GET 请求中获取,然后在 POST 上更新,成功时调用 status.setComplete()

但是,如果用户发出 GET 请求,然后点击离开到另一个页面,例如 OrganizationController.java,第二个控制器似乎试图重用来自另一个控制器的“表单”@SessionAttribute 对象,并且在它到达之前就会失败getOrganization() 方法。 (由于我的 Eclipse 控制台没有输出任何异常,因此无法确定它失败的具体原因,但我怀疑这是因为表单类型不匹配)

@SessionAttributes("form")
public class DictionaryController {

    @ModelAttribute("form")
    public DictionaryForm initForm() {
        return new DictionaryForm();
    }

    @RequestMapping(value="/Dictionary" method=RequestMethod.GET)
    public String getDictionary(
        @ModelAttribute("form") DictionaryForm form) {
        ...
        return "dictionaryView";
    }    

    @RequestMapping(value="/Dictionary" method=RequestMethod.POST)
    public String updateDictionary(
        @ModelAttribute("form") DictionaryForm form, 
        SessionStatus status) { 
        ...
        status.setComplete();
        return "successView";
    }

}
@Controller
@SessionAttributes("form")
public class OrganizationController{

    @ModelAttribute("form")
    public OrganizationForm initForm() {
        return new OrganizationForm();
    }

    @RequestMapping(value="/Organization" method=RequestMethod.GET)
    public String getOrganization(
        @ModelAttribute("form") OrganizationForm form) {
        ...
        return "orgView";
    }    

    @RequestMapping(value="/Organization" method=RequestMethod.POST)
    public String updateOrganization(
        @ModelAttribute("form") OrganizationForm form, 
        SessionStatus status) { 
        ...
        status.setComplete();
        return "successView";
    }
}

【问题讨论】:

  • 我想到的解决方法是:通过隐藏输入将整个表单包含在html页面中(可能的数据泄漏),在每一步从数据库中加载对象(不幸的是,对象加载通常很复杂),使用不同的名称用于存储每个表单(大量会话混乱),手动管理会话并显式处理控制器方法中的冲突,使每个表单具有相同的类型(重要的代码重写)

标签: java spring spring-mvc session


【解决方案1】:

我最终使用的解决方案是拥有一个所有表单类型都继承自的 BaseForm 对象类型。然后在 GET 请求的请求映射方法中,我将使用 @ModelAttribute("form") BaseForm form 并手动检查方法主体中的表单类型,如果不匹配则将其转换并在会话中恢复。 (如果您将其附加到请求的模型对象中,则可能不需要在会话中替换它)

即。

@RequestMapping(value="/Organization" method=RequestMethod.GET)
    public String getOrganization(HttpServletRequest request,
        @ModelAttribute("form") BaseForm form) {
        if (form.getClass() != OrganizationForm.class) {
            form = new OrganizationForm();
            request.getSession().setAttribute("form", form);
        }
        ...
        return "orgView";
    }    

【讨论】:

    猜你喜欢
    • 2019-02-18
    • 1970-01-01
    • 2012-10-01
    • 2016-03-27
    • 1970-01-01
    • 2015-07-04
    • 2019-12-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多