如何从Spring 3 MVC操作返回的ModelAndView中省略ModelAttribute参数?

时间:2011-12-01 18:00:19

标签: spring-mvc

我有一个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-annotated参数?如您所见,sessionStatus.setComplete()无效。

3 个答案:

答案 0 :(得分:1)

过去我和@SessionAttributes有过类似的问题。通过声明@SessionAttributes({"userContext"})你告诉Spring你希望"userContext"始终在模型中可用,所以Spring别无选择,只能将你的UserContext对象发送给模型,如果您要重定向或做其他可能最终在另一个Controller的其他内容。

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

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

答案 1 :(得分:0)

我注册了WebArgumentResolver来获取我的会话变量。这使我可以将此会话变量保留在响应之外,同时保持我的操作单元可测试。

答案 2 :(得分:0)

与@ModelAttribute一起,将@ModelMap作为方法参数传递。 基于业务逻辑,错误条件 - 如果您不需要某些方案的属性,则将其从地图中删除。

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

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

干杯!!