我创建了一个非常简单的"测试"控制器,它在会话中保持一个计数器,以打印调用请求处理程序的次数。
@Controller
@SessionAttributes("counter")
public class MyController {
@ModelAttribute("counter")
public Counter addCounter(){
System.out.println("Counter added to model");
return new Counter();
}
@RequestMapping("printCounter")
@ResponseBody
public String printCounter(Model model){
Counter counter = (Counter)model.asMap().get("counter");
int currVal = counter.getValue();
System.out.println("Current value: " + currVal);
counter.increment();
return "hello-view";
}
}
每件事都很好,但当我尝试在响应上使用@ResponseBody时,它失败了,并出现以下错误:
java.lang.IllegalStateException: Cannot create a session after the response has been committed
我找到了几件工作。我知道发生错误是因为spring在尝试将计数器添加到会话时已经刷新了响应。我不知道的是春天为什么会这样
既然这个问题已经存在了这么长时间,我想它是根据提议完成的。
有人知道以这种方式实施它的动机是什么吗?
如果方法返回正文内容,为什么我们可以在会话中存储数据,而如果它返回视图名称,我们可以存储数据?
提前谢谢。
@SessionAttribute
不是SpringFramework中设计最好的概念(请参阅另一篇文章了解另一个警告)。
当您转发到一个视图时,Spring在调用视图之前有所有的时间来处理会话属性:在控制器方法返回时,没有向请求写入任何内容。但是,当您使用@ResponseBody
时,方法的返回值会直接写入响应,并立即提交响应。因此,Spring创建一个会话来保存模型属性可能为时已晚。好吧,它本来可以被设计成一种没有必要的方式。但是因为您总是可以要求通过向控制器方法提供HttpSession
参数来急切地创建会话,我想Spring fellows认为这已经足够了。