环境:ajax+springMVC,
现象:
1、浏览器请求jsp页面,可以获取到拦截器postHandle设置的cookie
2、页面的ajax请求接口,拦截器同样设置了cookie,但前端获取不到,(抓包工具显示后端没传对应cookie)
3、把postHandle设置cookie的代码放到preHandle方法里面,ajax请求每次也可以获取到cookie
4、controller方法里面设置的cookie,ajax也能获取到
问题定位:
显然,response对象在controller方法返回之前是能设置cookie的,但在controller方法返回值后就不能了。
查找资料,得出结论:
Controller方法使用了@ResponseBody的注解,这个注解的实现方法里面对response进行了提交,导致提交后的response不能再设置cookie。
参考文章:
被@ResponseBoby注释的方法在拦截器的posthandle方法中设置cookie失效的问题
摘抄一段:
servlet文档里的说法:
isCommitted
public boolean isCommitted()
Returns a boolean indicating if the response has been committed. A committed response has already had its status code and headers written.
划重点:A committed response has already had its status and headers written.
所以flush操作是会导致response的commited状态被修改的,也就是说这时response的头信息已经被确定了!
解决方案:
1、只想对一个controller方法设置cookie的话,就在controller方法里面进行设置。
2、想对所有controller方法设置cookie的话,而且cookie和业务无关(与用户提交的数据无关),可以直接在postHandle设置cookie
3、想对所有controller方法设置cookie的话,而且cookie和业务有关(用户提交的数据立刻会影响cookie),可以使用AOP在controller方法返回值,且在返回值被@ResponseBody的注解封装前进行切入,在response里面设置cookie。
我采用的是第3种方法,使用了RequestBodyAdvice,在beforeBodyWrite方法里面设置了cookie,而且此处可以指定controller方法上有@ResponseBody的注解,没有此注解的就不设置cookie。
至于RequestBodyAdvice在springmvc里面的位置,可以参考我这篇文章:
https://blog.youkuaiyun.com/qq_30865917/article/details/97407174