响应封装着从服务器返回到客户端的所有信息。在http中,是服务器传输到客户端的消息通过http头信息或者响应的消息体。
缓存区
servlte容器有一个缓冲的区域,用于临时保存写入的信息(在没有调用flush方法之前),不管是使用ServletOutputStream还是Writer(或者其子类),缓存区的操作都可以通过ServletResponse如下方法来操作缓存区:
getBufferSize:返回使用的底层缓存区域大小。如果没有使用缓冲则为0.
setBufferSize:servlte可以使用setBufferSize方法设置一个缓冲区大小,该方法必须在ServletOutputStream或者Writer使用前调用,否则会抛出异常
isCommitted:返回是否已经有响应字节返回到客户端的Boolean。
flushBuffer:强制刷出缓冲区的内容到客户端。
reset:当响应没有提交,用于清空缓冲区数据。这个方法响应头、状态码等都清空。
resetBuffer:当响应没有提交的时候,清空缓冲区的数据,但是不清空头信息和状态码。
如果响应已经提交并且 reset 或 resetBuffer 方法已被调用,则必须抛出 IllegalStateException,响应及它关联的缓冲区将保持不变。
头信息
servlte可以使用HttpServletResponse接口中的方法设置http响应头
setHeader 方法设置一个给定名字和值的 header。之前的 header 将被新的 header 替换。如果已经存在同名的header 值的 set, set 中的值会被清空并用新的值替换。
addHeader 方法使用给定的名字添加一个 header 值到 set。如果没有 header 与给定的名字关联,则创建一个新的 set。响应提交之后,再次设置头信息是无效的。
非阻塞 IO
非阻塞io只对于升级处理或者异步处理有效,否则会报出异常WriteListener 提供了如下适用于容器调用的回调方法。
■ WriteListener
■ void onWritePossible(). 当一个 WriteListener 注册到 ServletOutputStream 时,当可以写数据时该方法 将被容器首次调用。当且仅当下边描述的 ServletOutputStream 的 isReady 方法返回 false,容器随后将 调用该方法。
■ onError(Throwable t). 当处理响应过程中出现错误时回调。
除了 WriteListener 外,还有如下方法被添加到 ServletOutputStream 类并允许开发人员运行时检查是否可以写数据发送到客户端。
■ ServletOutputStream
■ boolean isReady(). 如果往 ServletOutputStream 写会成功,则该方法返回 true,其他情况会返回 false。如果该方法返回 true,可以在 ServletOutputStream 上执行写操作。如果没有后续的数据能写到ServletOutputStream,那么直到底层的数据被刷出之前该方法将一直返回 false。且在此时容器将调用WriteListener 的 onWritePossible 方法。随后调用该方法将返回 true。■ void setWriteListener(WriteListener listener). 关联 WriteListener 和当且的 ServletOutputStream,当
ServletOutputStream 可以写入数据时容器会调用 WriteListener 的回调方法。注册了 WriteListener 将开始非阻塞 IO。此时再切换到传统的阻塞 IO 是非法的。
容器必须线程安全的访问 WriteListener 中的方法简便方法
sendRedirect
将设置适当的 header 和内容体将客户端重定向到另一个地址。使用相对 URL 路径调用该 方法是合法的,但是底层的容器必须将传回到客户端的相对地址转换为全路径 URL。无论出于什么原因, 如 果 给 定 的 URL 是 不 完 整 的 , 且 不 能 转 换 为 一 个 有 效 的 URL , 那 么 该 方 法 必 须 抛 出 IllegalArgumentException。
sendError
将设置适当的 header 和内容体用于返回给客户端返回错误消息。可以 sendError 方法提供一 个可选的 String 参数用于指定错误的内容体。 如果响应已经提交并终止,这两个方法将对提交的响应产生负作用。
这两个方法调用后 servlet 将不会产生 到客户端的后续的输出。这两个方法调用后如果有数据继续写到响应,这些数据被忽略。 如果数据已经写 到响应的缓冲区,但没有返回到客户端(例如,响应没有提交),则响应缓冲区中的数据必须被清空并使用 这两个方法设置的数据替换。如果想要已提交,这两个方法必须抛出 IllegalStateException。
国际化
servlte可以设置response的locale和字符集,ServletResponse.setLocale设置,可以重复调用,但是开始往缓冲区写入数据的之后,设置无效。因为在 ServletResponse 接口的 getWriter 方法被调用或响应被提交之前,如果 servlet 没有指定字符编码,默认使用 ISO-8859-1。
@Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // TODO Auto-generated method stub resp.setLocale(new Locale("zh", "CN")); resp.getWriter().append("asdasdasd").append("加深对看就按是代扣"+resp.getCharacterEncoding()).flush(); }
这样子就是gbk编码了<locale-encoding-mapping-list> <locale-encoding-mapping> <locale>zh_CN</locale> <encoding>GBK</encoding> </locale-encoding-mapping> </locale-encoding-mapping-list>
setContentType和 setCharacterEncoding,如果设置了 setContentType
resp.setHeader("Content-type", "text/html;charset=UTF-8"); 则默认 setCharacterEncoding也会跟着被设置setContentType是告诉浏览器用utf-8字符集来解析,setCharacterEncoding是写入字节流的时候使用什么字符集进行编码。
为什么会乱码呢?
原因在于PrintWriter对象将采用默认的编码的ISO8859-1字符集编码进行Unicode字符串到字节数组的转换,由于IS08859-1字符集中根本没有包括中文字符,Unicode编码的中文字符将被转换成无效的字符编码后输出给客户端。所以必须设置setCharacterEncoding,控制PrintWriter对象中文字符集能正常转成Unicode。这样子浏览器就能先Unicode解码,然后正常解析了。
凡事编码的只要写入数据之前设置都有效,一旦开始写入数据了,那么就是最后那一次有效。
结束响应对象
当响应被关闭时,容器必须立即刷出响应缓冲区中的所有剩余的内容到客户端。
以下事件表明 servlet 满足了请求且响应对象即将关闭:
■ servlet 的 service 方法终止。
■ 响应的 setContentLength 或 setContentLengthLong 方法指定了大于零的内容量,且已经写入到响应。
■ sendError 方法已调用。
■ sendRedirect 方法已调用。
■ AsyncContext 的 complete 方法已调用。
Response 的生命周期每个响应对象是只有当在 servlet 的 service 方法的范围内或在 filter 的 doFilter 方法范围内是有效的,除非该
组件关联的请求对象已经开启异步处理。如果相关的请求已经启动异步处理,那么直到 AsyncContext 的
complete 方法被调用,请求对象一直有效。为了避免响应对象创建的性能开销,容器通常回收响应对象。
在相关的请求的 startAsync 还没有调用时,开发人员必须意识到保持到响应对象引用,超出之上描述的范
围可能导致不确定的行为。
Response
最新推荐文章于 2024-04-25 10:57:19 发布