【问题标题】:How do I omit ModelAttribute parameters from the ModelAndView returned by a Spring 3 MVC action?如何从 Spring 3 MVC 操作返回的 ModelAndView 中省略 ModelAttribute 参数?
【发布时间】:2011-12-01 18:00:18
【问题描述】:

我有一个 Spring MVC 控制器,其中包含一个使用 AJAX 调用的操作。

@SessionAttributes({"userContext"})
public class Controller
{
    ...
    @RequestMapping(value = "/my-url", method= { RequestMethods.POST })
    public ModelAndView doSomething(@ModelAttribute("userContext") UserContext context,
            SessionStatus sessionStatus)
    {
        BusinessObject obj = doSomeBusinessLogic(context.getUserName());
        sessionStatus.setComplete();
        ModelAndView mav = new ModelAndView("jsonView");
        mav.addObject("someInt", obj.getId());
        return mav;
    }
}

当我运行此操作时,我收到以下异常:

net.sf.json.JSONException: There is a cycle in the hierarchy!
at t.sf.json.util.CycleDetectionStrategy$StrictCycleDetectionStrategy.handleRepeatedReferenceAsObject(CycleDetectionStrategy.java:97)
at net.sf.json.JSONObject._fromBean(JSONObject.java:833)
at net.sf.json.JSONObject.fromObject(JSONObject.java:168)
at org.springframework.web.servlet.view.json.writer.jsonlib.PropertyEditorRegistryValueProcessor.processObjectValue(PropertyEditorRegistryValueProcessor.java:127)
at net.sf.json.JSONObject._fromMap(JSONObject.java:1334)
Truncated. see log file for complete stacktrace

在做了一些调试之后,我发现 Spring 将 UserContext 对象放到了我返回的 ModelAndView 上。如果我硬编码我的用户名并从方法的参数中删除上下文对象,则操作会成功运行。有没有办法配置 Spring 从返回的 ModelAndView 中省略带有 ModelAttribute 注释的参数?如您所见,sessionStatus.setComplete() 无效。

【问题讨论】:

    标签: spring-mvc


    【解决方案1】:

    我过去在使用@SessionAttributes 时也遇到过类似的问题。通过声明@SessionAttributes({"userContext"}),您是在告诉Spring您希望"userContext"在模型中始终可用,因此Spring别无选择,只能将您的UserContext对象发送给模型,以防万一您要去正在重定向或做其他可能最终在另一个 Controller 结束的事情。

    “解决方案”(我不太喜欢它,但它有效)是在控制器上省略 @SessionAttributes 注释,在必要的方法中添加 HttpSession 参数并“手动”管理其中的内容它。

    我很想看看是否有更好的方法,因为@SessionAttributes 似乎具有整理控制器级代码的巨大潜力。

    【讨论】:

      【解决方案2】:

      我注册了一个WebArgumentResolver 来访问我的会话变量。这使我可以将这个会话变量排除在响应之外,同时保持我的操作单元可测试。

      【讨论】:

        【解决方案3】:

        与@ModelAttribute 一起,将@ModelMap 作为方法参数传递。 根据业务逻辑、错误情况——如果您在某些场景中不需要该属性,则将其从地图中移除。

            public ModelAndView foo(@ModelAttribute("userContext") UserContext, @ModelMap map){
              if(success){
               return success.jsp
              }
              else{
               map.remove("userContext");
              return "error.jsp" 
              }
            }
        

        对也必须通过 ModelMap 并不完全满意,但我没有找到任何其他更简单的方法。

        干杯!!

        【讨论】:

          猜你喜欢
          • 2021-08-20
          • 2013-12-31
          • 1970-01-01
          • 2011-06-20
          • 1970-01-01
          • 2012-08-20
          • 1970-01-01
          • 1970-01-01
          • 2021-04-12
          相关资源
          最近更新 更多