response对象封装了用来从server返回client的所有信息。根据HTTP协议,这些信息通过HTTP header和request的message body两者中的任意一个从server传送至client。
Servlet container允许为了提高效率而缓冲发送至client的output,但不是必须的。一般情况下,server默认启用buffering,但允许servlet制定buffering参数。
以下来自ServletResponse接口的方法允许servlet存取buffering信息:
这些方法由ServletResponse接口提供,用来执行buffering操作,不管servlet使用的是ServletOutputStream还是Writer。
getBufferSize方法返回当前缓冲使用的大小。如果没有使用buffering,该方法返回0(int型)。
Servlet可以通过setBufferSize方法设置一个首选的缓冲大小。分配的缓冲不一定要和servlet默认的大小一样,但至少要等于默认大小。这样才可以使container可以重用整套的固定大小的缓冲,提供比要求的更大的缓存,如果需要的话。setBufferSize方法必须在使用ServletOutputStream或者Writer写任何内容之前被调用。如果由任何内容已经被写入或者response对象已经被提交,这个方法就会抛出IllegalStateException。
isCommitted方法通过返回一个boolean值来表明是否有response字节已经被返回给客户端。flushBuffer方法将缓冲中的内容强制发送给客户端。
如果response没有被commit,reSet方法可以清除buffer中的数据。servlet在reSet方法被调用前set的headers和status codes也一定会被清除。resetBuffer方法也会清除buffer中的内容,如果response没有被提交的话,resetBuffer不会清除headers和status code。
如果response被commit后reset方法或者resetBuffer方法被调用,IllegalStateException会被抛出。Response和与它关联的buffer将不会产生变化。
当使用了缓冲时,container一定会立即把已经装满的缓存的内容flush到client。If this is the first data is sent to the client, the response is considered to be committed 。
Servlet可以通过以下的HttpServletResponse接口的方法设置HTTP response的headers:
setHeader方法使用给定的name和value来set header。之前的header会被新的header替换,当header集合中出现了相同的name时,新value会替代原value。
addHeader方法使用给定的name和value来add header。如果没有header与指定的name相关联,就创建一个新的集合。
Headers可以以int或者Date行对象存储数据。下面的HttpServletResponse接口的便利的方法允许servlet通过正确的格式来set a header:
为了成功地回传给client,headers必须在response被commit之前set。在response提交后被set的headers会被servlet container忽略。
Servlet程序员有责任确保response对象中的Content-Type header被正确地设置,为了由servlet生成的内容。HTTP 1.1规范中并没有要求这个header必须被set到HTTP response中。如果servlet程序员没有set这个type,Servlet container一定也不会设置一个默认的content type。
一般来说,containers被推荐使用X-Powered-By HTTP header来发布它的实现信息。这个字段的值应当由一个或多个implementation type组成,比如“Servlet/2.4”。还有一些可选的补充信息可以通过小括号被追加到implementation type。The container should be configurable to suppress this header.
这里有一些header的例子:
以下是HttpServletResponse提供的接口:
sendRedirect方法会恰当地设置headers和content body,来redirect client到一个不同的URL,必须以相对URL路径调用此方法,然而,底层的container必须将相对路径翻译成完整的合法的URL,以便回传至client。如果传入了不完整的URL,不管什么原因,不能被转换成合法的URL的话,方法就会抛出IllegalArgumentException。
sendError方法会恰当地设置headers和content body,以便返回给client一个错误信息。sendError方法有一个可选的String类型的参数,可以用在error的content body里面。
如果response还没有被commit的话,这些方法会使response commit掉,并且终止response。在这些方法被调用以后,servlet不会再输出任何东西到client。如果数据数据在这些方法被调用后写入response,它们会被忽略。
如果数据已经被写入response缓冲,但没有return、到client(response没有被commit),response 缓冲里的数据一定会被清除并且被这些方法set的数据替换。如果response被commit了,这些方法会抛出IllegalStateException。
servlet应该被设置locale和response字符编码。Locale使用ServletResponse.setLocale方法设置。此方法可以重复调用;但是response提交后调用无效。如果servlet没有在页面被提交前set locale,container会启用自身的默认locale以决定response的locale,但不生成任何关于与client交互的说明 ,比如Content-Language header,如果是HTTP的话。
见图SRV.5.4-1.png
如果元素没有出现或者没有提供一个映射,setLocale方法会使用container依赖的映射。setCharacterEncoding,setContentType和setLocale方法可以被重复调用来改变字符编码。在servlet response的getWriter方法已经被调用或者在response被commit后调用这些方法不会对字符编码产生任何作用。调用setContentType方法设置字符编码,只有在给定的content type string 为字符集属性提供了一个值的情况下才有效。调用setLocale方法设置字符编码,只有在setCharacterEncoding方法或者setContentType都没有被使用来设置了字符编码的情况下才有效。
如果servlet没有在ServletResponse接口的getWriter方法被调用之前或者response被提交之前指定一个字符编码,那么会使用默认的ISO-8859-1。
Container必须通过发送给client的servlet response的writer来与locale和字符编码通讯,如果启用的协议提供了这么做的方式。在HTTP的情况下,locale通过Content-Language header传达,字符编码则作为文本媒体类型的Content-Type header的一部分。需要注意的是,在servlet没有设定content-type的情况下,字符编码不能通过HTTP header被传达;然而,它仍被用于通过servlet response的writer来编码输入的文本。
当response关闭时,container必须立即flush发往client的response的buffer中所有剩余的content。以下事件表明servlet已经满足了request的要求并且response对象即将关闭:
每个response对象都只在servlet的service方法范围内有效,或者在filter的doFilter方法范围内。一般来说,container为了避免创建response对象对性能的额外开销影响而回收response对象。开发者必须注意的是,在上述范围之外维持response对象的引用可能导致不可预测的行为。