阿毛
It's me !
想你所想
浅谈servlet response

在重复使用response.sendRedirect()时候,报了“Cannot call sendRedirect() after the response has been committed”这个错误。于是查找原因分析,servlet response机制所致。

总结一下,现阶段对于servlet response的理解。


response是服务端对客户端请求做出响应的一个封装,里面包含了响应头,状态码以及响应体内容等。服务端在将响应response返回至客户端(浏览器)前,是将内容(header响应头,状态码等)写到缓存区中的。

https://file.blog.humh.cn/2020/04/图片-1024x374.png

如上图所示,平常在调用response.getWriter()print或write写响应体内容的时候,可以看到底层是会调用OutputBuffer,将内容写入缓存区。
当然写入缓存区,这是在响应response不超过缓存区大小的前提下,如果超过缓存区大小,就会直接flush至客户端(浏览器)。缓存区的机制就是为了较少网络传输的次数,提高网络传输速度。
当response内容写到缓存中后,也是将所有内容flush,将缓存区内容传输客户端,同时缓存区清空。如下图,response.sendRedirect() 中的一段代码,就是这样。(我们平常通过流对响应写入后,close()关闭流时,其内部也是如此)

https://file.blog.humh.cn/2020/04/图片-2.png

最后再将该response标记为committed、完成等(response中定义了多个标志位字段)。可以看到在sendRedirect最终处理前,其中已经将状态位标记,来表示此次请求已经响应完成。

https://file.blog.humh.cn/2020/04/图片-3.png

如果再次对该response设置重定向的话,会先判断标志位

https://file.blog.humh.cn/2020/04/图片-4.png
https://file.blog.humh.cn/2020/04/图片-5.png

显然在上一次调用完sendRedirect()的时候,已经commit了,再次调用的时候(或者调用其他方法对response进行改写),就会报开头所说的错误。所以一般调用完sendRedirect()后就直接return了。

response支持在commit响应完成前,重置缓存区reset()

发表评论

textsms
account_circle
email

想你所想

浅谈servlet response
在重复使用response.sendRedirect()时候,报了“Cannot call sendRedirect() after the response has been committed”这个错误。于是查找原因分析,servlet response机制所致。 总结一…
扫描二维码继续阅读
2020-04-14