@SessionAttributes和@ResponseBody不能一起工作

时间:2014-10-21 12:45:25

标签: spring-mvc

我创建了一个非常简单的“测试”控制器,它在会话中保持一个计数器来打印一个请求处理程序被调用的次数。

@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在尝试将计数器添加到会话时已经刷新了响应。我不知道的是为什么春天这样做。

由于这个问题已经存在了很长时间,我想它已经完成了提议。

有没有人知道以这种方式实施它的动机是什么?

如果方法返回正文内容,为什么我们可以在会话中存储数据但是如果它返回一个视图名称呢?

提前致谢。

1 个答案:

答案 0 :(得分:3)

@SessionAttribute不是SpringFramework中设计最好的概念(另请参阅另一个post)。

当您转发到视图时,Spring会在调用视图之前一直处理会话属性:在控制器方法返回时,没有任何内容写入请求。但是当您使用@ResponseBody时,方法的返回值将直接写入响应,并立即提交响应。因此,Spring可能为时已晚,无法创建会话来保存模型属性。好吧,它本来可以设计成没有必要的。但因为你总是可以通过向控制器方法提供一个HttpSession参数来急切地创建一个会话,我想Spring的人认为这已经足够了。