我有一个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()
无效。
答案 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并不完全满意,但我没有找到任何其他更简单的方法。
干杯!!