Servlet 3.0 之 Response

response对象包含了所有从服务端返回给客户端的信息。在HTTP协议下,这些信息通过HTTP头部或者response的消息体从服务器被传输到客户端。

Buffering

为了提高效率,一个servlet容器可以缓存输出到客户端的内容。典型的缓存服务器会把缓存服务默认打开,但是允许servlet指定缓存参数。

ServletResponse接口里的下列方法允许一个servlet访问和设置缓存参数:

  • getBufferSize
  • setBufferSize
  • isCommitted
  • reset
  • resetBuffer
  • flushBufer

无论servlet是否正在使用ServletOutPutStream或者Write,上述在ServletResponse接口之上提供的方法让缓存操作都能被执行。

方法getBufferSize返回正在使用的Buffer的大小。如果没有缓存被使用,这个方法返回int类型的0。

servlet能够请求通过setBufferSize方法设置的指定大小的buffer。分配的buffer大小不必与servlet请求的大小一样,但是必须不能小于请求的大小。这允许容器重用固定大小的buffer集合,在合适的时机可以提供一个比请求更大的buffer。在用ServletOutputStream 写回任何内容之前,方法setBufferSize必须被调用。如果任何内容被写回,或者response对象被提交,方法setBufferSize抛出IllegalStateException

方法IsCommitted 返回一个boolean值来标识是否有任何response字节被返回到客户端。方法flushBuffer 强制buffer中的内容被写回到客户端。

方法reset 在response对象没有被提交之前,清除缓存中的数据。Servlet在reset调用之前设置的header和状态码也必须被清除。如果response没有被提交,而且没有清除headers和状态码,resetBuffer 方法可以清除buffer中的内容。

如果response被提交,并且resetresetBuffer方法被调用,一个IllegalStateException必须被抛出。response及其相关的buffer将不会被改变。

当使用一个buffer,容器必须立即把已满buffer的内容刷新到客户端。如果这是发送给客户端的第一份数据,那么response就被认为被提交了。

Headers

一个servlet能通过HttpServletResponse 接口的下列方法设置HTTP response的headers:

  • setHeader
  • addHeader

方法setHeader 用指定的名字和值来设置一个header。之前的header会被新的header替代。如果一个名字对应一个头部值的集合,它的值会被清除并且被新值替代。

方法addHeader 添加一个header值到指定名字的集合中。如果没有关联此名字的header存在,新的将会被创建。

Headers可以包含表示一个int或者Date对象数据。下列HttpServletResponse接口的便捷方法允许一个servlet使用正确的格式化类型来设置一个header。

  • setIntHeader
  • setDateHeader
  • addIntHeader
  • addDateHeader

为了成功地传输回客户端,headers必须在response被提交之前设置好。在response被提交后设置的header将会被servlet容器忽略。

Servlet程序员负责在response对象中,为servlet生成的内容设置合适的Content-Type头部。HTTP1.1规范不要求在一个HTTP response中设置这个header。当servlet程序员没有设置Content-Type,servlet容器一定不能设置默认的content类型。

推荐容器使用X-Powered-By HTTP头部来发布它的实现信息。域值应该由一个或者多个实现类型组成,比如Servlet/3.0。容器的补充以及底层的Java平台信息可以被添加到括号里实现类型的后面。容器应该是可配置来覆盖这个header。

这是X-Powered-By头部的例子。

  • X-Powered-By: Servlet/3.0
  • X-Powered-By: Servlet/3.0 JSP/2.2 (GlassFish v3 JRE/1.6.0)

便捷方法

下列便捷方法存在于HttpServletResponse 接口中:

  • sendRedirect
  • sendError

sendRedirect 方法将设置合适的headers和消息体来把客户端重定向到不同的URL。用一个相对URL路径调用这个方法是合法的,但是当前容器必须把相对路径转换成具体的URL传回客户端。如果一个不完整的URI因为任何一个原因不能被转换为一个合法URL,那么这个方法必须抛出IllegalArgumentException

sendError方法将为返回给客户端的错误消息设置合适的headers和消息体。有一个可选的字符串参数能够传递给这个函数,这个参数能够被应用在消息体中。

如果response还没有被提交,或者结束,这些方法在提交response时将会有副作用。在这些方法调用之后,不应该再有更多内容输出到客户端了。如果在这些方法调用后,还有数据写到response,这些数据会被忽略。

如果这些数据被写到response buffer,但是没有返回给客户端(i.e response还没有被提交),response buffer中的数据必须被清除并且被通过这些方法设置的数据替代。如果response已经被提交,这些方法必须抛出IllegalStateException

国际化

Servlets应该设置response的区域和字符编码。区域用ServletResponse.setLocale方法来设置。这个方法能被重复地调用,且在response提交之后调用此方法不会有副作用。如果servlet在页面提交之前没有设置区域,容器会使用默认值来决定response的区域,但是并没为与客户端通信制定规范,比如HTTP中的Content-Language 头部。

<locale-encoding-mapping-list>
  <locale-encoding-mapping>
    <locale>ja</locale>
    <encoding>Shift_JIS</encoding>
  </locale-encoding-mapping>
</locale-encoding-mapping-list>

如果这个元素不存在,或者没有提供一个映射,setLocale 使用一个依赖容器的映射。setCharacterEncoding,setContentTypesetLocale能重复调用来改变字符编码。在servlet response的getWriter方法已经被调用之后,或者在response提交之后调用此方法对字符编码不会有副作用。
仅当指定的content type字符串为charset 属性提供一个值时,调用setContentType方法来设置字符编码。
仅当setCharacterEncodingsetContentType 之前都没有设置字符编码,调用setLocale方法设置字符编码。

如果在ServletResponse接口的getWriter方法调用或者response被提交之前,servlet没有指定字符编码,会使用默认编码 ISO-8859-1

如果当前使用的协议提供一种编码方式,容器必须为servlet的writer与客户端交流应用于servlet响应对象的writer的区域和字符编码。使用HTTP时,对于文本媒体类型,字符编码作为Content-Type头部的一部分,那么区域通过Content-Language头部来交流。需要注意的是,如果没有指定content type,servlet字符编码不能通过HTTP头部来交流;然而它仍然用来编码servlet响应对象的writer写回的文本。

Response对象的闭包

当response对象被关闭,容器必须立即把response buffer中所有剩余内容刷新到客户端。下列事件标识servlet已经满足了请求并且response对象将会被关闭:

  • servlet的service方法结束了.
  • 由response对象中的setContentLength方法指定的内容的长度大于0并且已经被写到response.
  • 方法sendError被调用.
  • 方法sendRedirect被调用.
  • AsyncContext上的complete方法被调用.

Response对象的生命周期

每个response对象仅在一个servlet的service方法范围内,或者在filter的doFilter方法范围内才合法,除非相关的请求对象已经为组件启动了异步处理。如果相关请求上的异步处理开始,请求对象直到complete方法被调用前仍然合法。为了避免创建新response对象的性能消耗,容器通常会重复利用response对象。
开发者必须意识到,维护一个指向response对象的引用,且与此对应的request对象上的startAsync还没有被调用,那么要是这引用指向上述范围之外会导致无法预测的行为。

翻译自 Java Servlet Specification
Version 3.0 Rev a
Author:Rajiv Mordani
Date: December 2010

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,546评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,224评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,911评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,737评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,753评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,598评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,338评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,249评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,696评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,888评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,013评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,731评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,348评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,929评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,048评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,203评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,960评论 2 355

推荐阅读更多精彩内容

  • Servlet Interface 是Java Servlet API的核心抽象。所有的servlets都直接或者...
    Lucky_Micky阅读 1,697评论 2 2
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,657评论 18 139
  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,251评论 11 349
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,638评论 18 399
  • 复习复习!!!搞起来!!Servlet和JSP是Java EE规范最基本成员,他们是Java Web开发的重点知识...
    JackFrost_fuzhu阅读 2,846评论 1 71