在重复使用
response.sendRedirect()
时候,报了“Cannot call sendRedirect() after the response has been committed”这个错误。于是查找原因分析,servlet response机制所致。
总结一下,现阶段对于servlet response的理解。
response是服务端对客户端请求做出响应的一个封装,里面包含了响应头,状态码以及响应体内容等。服务端在将响应response返回至客户端(浏览器)前,是将内容(header响应头,状态码等)写到缓存区中的。
如上图所示,平常在调用response.getWriter()
print或write写响应体内容的时候,可以看到底层是会调用OutputBuffer,将内容写入缓存区。
当然写入缓存区,这是在响应response不超过缓存区大小的前提下,如果超过缓存区大小,就会直接flush至客户端(浏览器)。缓存区的机制就是为了较少网络传输的次数,提高网络传输速度。
当response内容写到缓存中后,也是将所有内容flush,将缓存区内容传输客户端,同时缓存区清空。如下图,response.sendRedirect()
中的一段代码,就是这样。(我们平常通过流对响应写入后,close()关闭流时,其内部也是如此)
最后再将该response标记为committed、完成等(response中定义了多个标志位字段)。可以看到在sendRedirect最终处理前,其中已经将状态位标记,来表示此次请求已经响应完成。
如果再次对该response设置重定向的话,会先判断标志位
显然在上一次调用完sendRedirect()
的时候,已经commit了,再次调用的时候(或者调用其他方法对response进行改写),就会报开头所说的错误。所以一般调用完sendRedirect()
后就直接return
了。
response支持在commit响应完成前,重置缓存区reset()
。
发表评论