• Servlet中response对象Commit状态的分析


    response是服务端对客户端请求的一个响应,其中封装了响应头、状态码、内容(也就是最终要在浏览器上显示的HTML代码或者其他数据格式)等。

    服务端在把response提交到客户端之前,会使用一个缓冲区,并向该缓冲区内写入响应头和状态码,然后将所有内容flush(flush包含两个步骤:先将缓冲区内容发送至客户端,然后将缓冲区清空)。

    这就标志着该次响应已经committed(提交)。


    对于当前页面中已经committed(提交)的response:

    就不能再使用这个response向缓冲区写任何东西  。(原文这里可能有错误

    不可以再进行send***这类发送响应内容的操作(因为响应已经提交给客户端),

    可以使用set***这类设置响应内容的函数(设置后无效,因为响应已经提交给客户端),

    实测可以继续进行页面内容的输出(--此处存疑--不能理解--实测(执行response.getWriter().close()后会导致后续输出无效,但不会爆异常)),

    实测可以进行request.getRequestDispatcher(“”).include(request, response);,

    实测不可以进行request.getRequestDispatcher(“”).forward(request, response);(会抛出IllegalStateException异常Cannot forward after response has been committed),

    (注:以为JSP中,response是一个JSP页面的内置对象,所以同一个页面中的response.XXX()是同一个response的不同方法,只要其中一个已经导致了committed,那么其它类似方式的调用都会导致 IllegalStateException异常)。


    导致 response 状态变为 committed 的原因:

    send***这类方法:向客户端发送状态码或重定向会直接提交响应。

    刷新缓存:当response对象缓存区满时,或者使用response对象的flushbuffer方法会刷新response对象的缓存导致响应提交。

    转发:将未提交的response通过forward转发可能会在转发目标的处理流程内被提交(include转发不会)。

    forward指令和include指令很相似,它们都采用方法来导入目标。

    执行forward指令时,response必须未提交,目标获得的response与原Servlet中同一个(ResponseFacade对象)。原先存放在response对象中的内容将会自动被清除,目标可以直接发出响应,之后程序流程回到原Servlet转发处继续执行,但是原Servlet似乎连页面内容都不可输出了。

    而执行include指令时,目标获得的response与原Servlet中不是同一个(被换成了一个ApplicationHttpResponse对象,让目标无法对源请求做出实质响应,但是该对象进行提交操作后会导致原Servlet中的response对象也变为已提交,但仍然可以进行页面输出)。原Servlet把目标产生的响应的内容部分包含到自身响应的内容中,目标改变响应消息的状态码和响应头的语句执行结果将被忽略(即被调用的Servlet的响应只有内容部分会并入原Servlet的响应的内容部分中)。

    关于forward和include的详细分析不在此处深究。


    关于JSP中的flushBuffer

    每一个JSP页面都有一个缓冲区,默认的缓冲区大小为8KB,如果缓冲区被占满的话,web服务器就会自动将response 进行commit,然后清空缓冲区(即flush)。

    JSP内置对象out相关方法:

    public abstract void clear() throws java.io.IOException 清除缓冲区中的内容。如果缓冲区已经被刷新,clear()方法将抛出IOException异常
    public abstract void clearBuffer() throws java.io.IOException 清除缓冲区中的当前内容。这个方法和clear()方法的区别是,如果缓冲区已经被刷新,这个方法不会抛出IOException异常
    public abstract void close() throws java.io.IOException

    刷新缓冲区,关闭输出流。注意,我们在编写JSP页面时,不需要显式地去调用这个方法,因为在JSP容器所生成的代码中会自动包含对close()方法的调用。

    public abstract void flush() throws java.io.IOException 刷新缓冲区,两个步骤:1,提交response  2.清空缓冲区
    public int getBufferSize() 获得缓冲区大小,同response.getBufferSize()相同
    public abstract int getRemaining() 获得缓冲区中未使用的字节数
    public boolean isAutoFlush() 判断out对象是否是自动刷新 
    <%@ page autoFlush="true" %> <%--Default--%>

    内置对象response相关方法:

    response.isCommitted() 确认response是否已经committed
    response.flushbuffer(); 同out.flush相同

    增大缓冲区大小:

    <%@ page buffer="10kb" %>


     文参考:https://www.cnblogs.com/ismallboy/p/6785328.html

  • 相关阅读:
    前端安全
    关于HTTPS的概念性了解
    数组去重
    防抖与节流
    对meta标签的再次认识
    关于路由, 我好奇的那些点
    关于构造函数,实例,原型对象一纯手工的理解
    数据库查找操作-java
    python之图像加载和简单处理
    python之excel表格操作
  • 原文地址:https://www.cnblogs.com/Leroscox/p/8305141.html
Copyright © 2020-2023  润新知