20200311 5. Response

摘要:
ServletResponse接口的以下方法允许servlet访问和设置缓冲区信息:isCommitted方法返回一个布尔值,指示是否向客户端返回了任何响应字节。在调用reset之前,servlet调用getWriter或getOutputStream设置的状态代码和状态也必须清除。
5. Response

响应( response)对象封装了从服务器返回到客户端的所有信息。在 HTTP 协议中,从服务器传输到客户端
的信息通过 HTTP 头信息或响应的消息体。

5.1 缓冲

Servlet 容器允许但不必为了提高效率而缓冲到客户端的输出。典型的服务器默认都是缓冲的,但允许 servlet
指定缓冲参数。

ServletResponse 接口的如下方法允许 servlet 访问和设置缓冲信息:

  • getBufferSize
  • setBufferSize
  • isCommitted
  • reset
  • resetBuffer
  • flushBuffer

不管 Servlet 使用的是一个 ServletOutputStream 还是一个 Writer, ServletResponse 接口提供的这些方法允许执行缓冲操作。

getBufferSize 方法返回使用的底层缓冲区大小。如果没有使用缓冲,该方法必须返回一个 int 值 0

Servlet 可以请求 setBufferSize 方法设置一个最佳的缓冲大小。不一定分配 servlet 请求大小的缓冲区,但至
少与请求的大小一样大。这允许容器重用一组固定大小的缓冲区,如果合适,可以提供一个比请求时更大的缓冲区。该方法必须在使用 ServletOutputStream 或 Writer 写任何内容之前调用。如果已经写了内容或响应对象已经提交,则该方法必须抛出 IllegalStateException

isCommitted 方法返回一个表示是否有任何响应字节已经返回到客户端的 boolean 值。 flushBuffer 方法强制
刷出缓冲区的内容到客户端。

当响应没有提交时, reset 方法清空缓冲区的数据。头信息,状态码和在调用 reset 之前 servlet 调用 getWritergetOutputStream 设置的状态也必须被清空。如果响应没有被提交, resetBuffer 方法将清空缓冲区中的内容,但不清空请求头和状态码。

如果响应已经提交并且 resetresetBuffer 方法已被调用,则必须抛出 IllegalStateException,响应及它关联的缓冲区将保持不变。

当使用缓冲区时,容器必须立即刷出填满的缓冲区内容到客户端。如果这是最早发送到客户端的数据,且认为响应被提交了。

5.2 头信息

Servlet 可以使用如下 HttpServletResponse 接口中的方法设置 HTTP 响应头:

  • setHeader
  • addHeader

setHeader 方法设置一个给定名字和值的 header。之前的 header 将被新的 header 替换。如果已经存在同名的
header 值的 set, set 中的值会被清空并用新的值替换。

addHeader 方法使用给定的名字添加一个 header 值到 set。如果没有 header 与给定的名字关联,则创建一个
新的 set。

Header 可能包含表示 intDate 对象的数据。以下 HttpServletResponse 接口提供的便利方法允许 Servlet 对适当的数据类型用正确的格式设置一个 header:

  • setIntHeader
  • setDateHeader
  • addIntHeader
  • addDateHeader

为了成功的传回给客户端, header 必须在响应提交前设置。响应提交后的 Header 设置将被 servlet 容器忽略。
Servlet 程序员负责保证为 Servlet 生成的内容设置合适的 response 对象的 Content-Type header。 HTTP 1.1 规范中没有要求在 HTTP 响应中设置此 header。当 Servlet 程序员没有设置该类型时, Servlet 容器也不能设置
默认的内容类型。

建议容器使用 X-Powered-By HTTP header 公布它的实现信息。该字段值应考虑一个或多个实现类型,如
"Servlet/3.1"。容器应该可以配置来隐藏该 header。可选的容器补充的信息和底层 Java 平台可以被放在括号
内并添加到实现类型之后。

X-Powered-By: Servlet/3.1

X-Powered-By: Servlet/3.1 JSP/2.2 (GlassFish Open Source Edition 4.0 Java/Oracle Corporation/1.7)

5.3 非阻塞 IO

非阻塞 IO 仅对在 Servlet 和 Filter(2.3.3.3 节定义的, “异步处理”)中的异步请求处理和升级处理
(2.3.3.5 节定义的,“升级处理”)有效。否则,当调用 ServletInputStream.setReadListener
ServletOutputStream.setWriteListener 方法时将抛出 IllegalStateException。 为了支持在 Servlet 容器中的非阻塞写,除了在 3-28 页 3.7 节描述的“非阻塞 IO” 对 ServletRequest 做的更改之外,下面做出的更
改以便于处理响应相关的类/接口。

WriteListener 提供了如下适用于容器调用的回调方法。

  • void onWritePossible(). 当一个 WriteListener 注册到 ServletOutputStream 时,当可以写数据时该方法将被容器首次调用。当且仅当下边描述的 ServletOutputStreamisReady 方法返回 false,容器随后将调用该方法。

  • onError(Throwable t). 当处理响应过程中出现错误时回调。

除了 WriteListener 外,还有如下方法被添加到 ServletOutputStream 类并允许开发人员运行时检查是否可以写数据发送到客户端。

  • boolean isReady(). 如果往 ServletOutputStream 写会成功,则该方法返回 true,其他情况会返回 false。如果该方法返回 true,可以在 ServletOutputStream 上执行写操作。如果没有后续的数据能写到
    ServletOutputStream,那么直到底层的数据被刷出之前该方法将一直返回 false。且在此时容器将调用
    WriteListeneronWritePossible 方法。随后调用该方法将返回 true

  • void setWriteListener(WriteListener listener). 关联 WriteListener 和当前的 ServletOutputStream,当 ServletOutputStream 可以写入数据时容器会调用 WriteListener 的回调方法。注册了 WriteListener 将开始非阻塞 IO。此时再切换到传统的阻塞 IO 是非法的。

容器必须线程安全的访问 WriteListener 中的方法。

5.4 简便方法

HttpServletResponse 提供了如下简便方法:

  • sendRedirect
  • sendError

sendRedirect 方法将设置适当的 header 和内容体将客户端重定向到另一个地址。使用相对 URL 路径调用该
方法是合法的,但是底层的容器必须将传回到客户端的相对地址转换为全路径 URL。无论出于什么原因,如 果 给 定 的 URL 是 不 完 整 的 , 且 不 能 转 换 为 一 个 有 效 的 URL , 那 么 该 方 法 必 须 抛 出
IllegalArgumentException

sendError 方法将设置适当的 header 和内容体用于返回给客户端返回错误消息。可以 sendError 方法提供一
个可选的 String 参数用于指定错误的内容体。

如果响应已经提交并终止,这两个方法将对提交的响应产生负作用。这两个方法调用后 servlet 将不会产生
到客户端的后续的输出。这两个方法调用后如果有数据继续写到响应,这些数据被忽略。 如果数据已经写
到响应的缓冲区,但没有返回到客户端(例如,响应没有提交),则响应缓冲区中的数据必须被清空并使用
这两个方法设置的数据替换。如果想要已提交,这两个方法必须抛出 IllegalStateException

5.5 国际化

Servlet 应设置 response 的 locale 和字符集。使用 ServletResponse.setLocale 方法设置 locale。该方法可以重复的调用;但响应被提交后调用该方法不会产生任何作用。如果在页面被提交之前 Servlet 没有设置 locale,
容器的默认 locale 将用来确定响应的 locale,但是没有制定与客户端通信的规范,例如使用 HTTP 情况下的
Content-Language header。

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

如果该元素不存在或没有提供 mapping, setLocale 使用容器依赖的 mapping。 setCharacterEncoding
setContentTypesetLocale 方法可以被重复的调用来改变字符编码。如果在 servlet 响应的 getWriter 方法已经调用之后或响应被提交之后,调用相关方法设置字符编码将没有任何作用。只有当给定的 content type 字
符 串 提 供 了 一 个 charset 属 性 值 , 调 用 setContentType 可 以 设 置 字 符 编 码 。 只 有 当 既 没 有 调 用
setCharacterEncoding 也没有调用 setContentType 去设置字符编码之前调用 setLocale 可以设置字符编码。

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

如果使用的协议提供了一种这样做的方式,容器必须传递 servlet 响应的 writer 使用的 locale 和字符编码到
客户端。使用 HTTP 的情况下, locale 可以使用 Content-Language header 传递,字符编码可以作为用于指定
文本媒体类型的 Content-Type header 的一部分传递。注意,如果没有指定 content type,字符编码不能通过
HTTP header 传递;但是仍使用它来编码通过 servlet 响应的 writer 写的文本。

5.6 结束响应对象

当响应被关闭时,容器必须立即刷出响应缓冲区中的所有剩余的内容到客户端。

以下事件表明 servlet 满足了请求且响应对象即将关闭:

  • servlet 的 service 方法终止。
  • 响应的 setContentLengthsetContentLengthLong 方法指定了大于零的内容量,且已经写入到响应。
  • sendError 方法已调用。
  • sendRedirect 方法已调用。
  • AsyncContextcomplete 方法已调用。

5.7 Response 的生命周期

每个响应对象是只有当在 servlet 的 service 方法的范围内或在 filter 的 doFilter 方法范围内是有效的,除非该组件关联的请求对象已经开启异步处理。如果相关的请求已经启动异步处理,那么直到 AsyncContext
complete 方法被调用,请求对象一直有效。为了避免响应对象创建的性能开销,容器通常回收响应对象。
在相关的请求的 startAsync 还没有调用时,开发人员必须意识到保持到响应对象引用,超出之上描述的范
围可能导致不确定的行为。

免责声明:文章转载自《20200311 5. Response》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇winform语音提示漫谈软件系统中的形式结构下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

[Swift]遍历集合类型(数组、集合和字典)

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/ )➤GitHub地址:https://github.com/strengthen/LeetCode➤原文地址:https://...

Redis 监视器

一  介绍 客户端可以通过执行MONITOR命令,将客户端转换成监视器,接收并打印服务器处理的每个命令请求的相关信息。 当一个客户端从普通客户端变为监视器时,该客户端的REDIS_MONITOR标识会被打开。服务器将所有监视器都记录在monitors链表中。每次处理命令请求时,服务器都会遍历monitors链表,将相关信息发送给监视器。 当前客户端变身监...

解决adober reader已停止工作的问题

公司电脑出现打开pdf阅读器后没到1分钟就闪退,应该是adobe做了什么正版审核策略,让安装了这个软件的电脑自动连接到adobe服务器验证导致。 解决方法:在C:WindowsSystem32driversetchosts文件下添加这行即可 127.0.0.1 acroipm.adobe.com...

Hive调优实战[转]

Hive优化总结 【转自:http://sznmail.iteye.com/blog/1499789】 优化时,把hive sql当做map reduce程序来读,会有意想不到的惊喜。 理解hadoop的核心能力,是hive优化的根本。这是这一年来,项目组所有成员宝贵的经验总结。   长期观察hadoop处理数据的过程,有几个显著的特征: 1.不怕数据多...

Spring框架针对dao层的jdbcTemplate操作crud之query查询数据操作

查询目标是完成3个功能: (1)查询表,返回某一个值。例如查询表中记录的条数,返回一个int类型数据 (2)查询表,返回结果为某一个对象。 (3)查询表,返回结果为某一个泛型的list集合。 一、查询表中记录的条数,返回一个int类型数据的操作方法 使用jdbcTemplate 原理是把加载驱动Class.forName("com.mysql.jdbc.D...

Prism初研究之依赖管理

Prism初研究之依赖管理 Prism初研究之依赖管理关键决定:选择DI容器考虑使用容器核心情景类型注册使用Unity容器注册类型使用MEF容器注册类型依赖解析Unity实例解析MEF实例解析在Prism中使用依赖注入容器IServiceLocator扩展阅读 注意:Prism框架本身不提供指定的依赖注入容器,你可以使用其它的依赖注入容器,比如:C...