上次在培训班学上网课的时候就发现了这个问题,一直没有解决,昨天又碰到了,2-3小时也未能发现点端倪,今早又仔细缕了下,让我看了他的秘密

1.Servlet向流中打印内容,之后在调用finsihResponse,调用上是先发送了body,后发送Header的问题描述

public class ServletProcessor {
public void process(HttpRequest request,HttpResponse response){
...
try {
servlet = (Servlet) myClass.newInstance();
HttpRequestFacade requestFacade = new HttpRequestFacade(request);
HttpResponseFacade responseFacade = new HttpResponseFacade(response);
servlet.service(requestFacade, responseFacade);//先调用servlet代码
((HttpResponse) response).finishResponse();//后执行完成response
}
catch (Exception e) {
System.out.println(e.toString());
}
catch (Throwable e) {
System.out.println(e.toString());
}
}
}
servlet.service(requestFacade, responseFacade);//先调用servlet代码
public class PrimitiveServlet implements Servlet {

  public void init(ServletConfig config) throws ServletException {
System.out.println("init");
}
public void service(ServletRequest request, ServletResponse response)
throws ServletException, IOException {
System.out.println("from service");
PrintWriter out = response.getWriter();//这里是关键稍后分析
out.println("Hello. Roses are red.");//打印
out.print("Violets are blue.");
}
public void destroy() {
System.out.println("destroy");
}
public String getServletInfo() {
return null;
}
public ServletConfig getServletConfig() {
return null;
} }
((HttpResponse) response).finishResponse();//后执行完成response

    public void finishResponse()throws IOException{
sendHeaders();
// Flush and close the appropriate output mechanism
if(writer !=null){
writer.flush();
System.out.println("finishResponse writer.flush");
writer.close();
}
} protected void sendHeaders() throws IOException{
if(isCommitted())
return;
OutputStreamWriter osr=null;
try{
osr=new OutputStreamWriter(getStream(),getCharacterEncoding());
}catch (UnsupportedEncodingException e) {
osr = new OutputStreamWriter(getStream());
}
final PrintWriter outputWriter = new PrintWriter(osr);
outputWriter.print(this.getProtocol());
outputWriter.print(" ");
outputWriter.print(status);
if(message!=null){
outputWriter.print(" ");
outputWriter.print(message); //OK 状态描述
}
outputWriter.print("\r\n");
if (getContentType()!=null){
outputWriter.print("Content-Type: " + getContentType() + "\r\n");
}
if(getContentLength()>=0){
outputWriter.print("Content-Length: " + getContentLength() + "\r\n");
}
synchronized (headers){
Iterator items=headers.keySet().iterator();
while(items.hasNext()){
String name=(String)items.next();
ArrayList list =(ArrayList) headers.get(name);
Iterator iterator = list.iterator();
while (iterator.hasNext()){
String value = (String)iterator.next();
outputWriter.print(name);
outputWriter.print(": ");
outputWriter.print(value);
outputWriter.print("\r\n");
}
}
}
synchronized (cookies){
Iterator items=cookies.iterator();
while(items.hasNext()){
Cookie cookie=(Cookie)items.next();
outputWriter.print(CookieTools.getCookieHeaderName(cookie));
outputWriter.print(": ");
outputWriter.print(CookieTools.getCookieHeaderValue(cookie));
outputWriter.print("\r\n");
}
}
// Send a terminating blank line to mark the end of the headers
outputWriter.print("\r\n");
outputWriter.flush();
System.out.println("给response的header发送完成"); committed = true;
}

问题描述完毕

2.突破口,在sendHeader中的outputWriter与servlet中的 PrintWriter out = response.getWriter();不是一个东西

先说sentHader中的

 try{
osr=new OutputStreamWriter(getStream(),getCharacterEncoding());
}catch (UnsupportedEncodingException e) {
osr = new OutputStreamWriter(getStream());
}
final PrintWriter outputWriter = new PrintWriter(osr);
outputWriter.print(this.getProtocol());
outputWriter.print(" ");
outputWriter.print(status);
其中
public OutputStream getStream(){
return this.output;
}
构造方法
public HttpResponse(OutputStream output)
{
this.output=output;
}
他被调用位置见图片

小结:sendheader中的PrintWriter就是使用了outputSteam做为底层的输出流

3.servlet中的 PrintWriter out = response.getWriter()的包裹关系

    public PrintWriter getWriter() throws IOException{
ResponseStream newStream = new ResponseStream(this);
newStream.setCommit(false);
OutputStreamWriter osr=
new OutputStreamWriter(newStream,getCharacterEncoding());
writer=new ResponseWriter(osr);
return writer;
}

见解释图

说明:

1.servlet中getWrter得到是ResponseWriter,调用responseWriter的frint("")方法,通过流的调用,最后底层流是ResponseStream,调用其方法为writer(...)

  writer方法是将"Rode Are Red" 字符串写入到HttpResponse的成员变量buff中

2.在调用close的时候,最后调用ResponseStream的close方法,接着在flushbuffer中才最终叫内容"Rode Are Red",发送给浏览器

几张debugger图

atzhang

Tom_No_02 Servlet向流中打印内容,之后在调用finsihResponse,调用上是先发送了body,后发送Header的解释的更多相关文章

  1. 使用定时器实现在console中打印内容

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. 用servlet在网页中打印字符串(初接触)、servlet调用过程

    一.servlet是什么: 二.在官方文档中点servlet 这就是servlet的方法,这里说一下什么叫生命周期的方法(life-cycle methods):就是这个对象一旦创生之后一定会执行的方 ...

  3. 从servlet向jsp中传数据用Java接收js调用

    servlet: response.sendRedirect("showMessage.jsp?ValueA=1"); jsp: var a=<%=request.getPa ...

  4. H264码流中SPS PPS详解<转>

    转载地址:https://zhuanlan.zhihu.com/p/27896239 1 SPS和PPS从何处而来? 2 SPS和PPS中的每个参数起什么作用? 3 如何解析SDP中包含的H.264的 ...

  5. 描述了say_hello函数的具体内容,调用zend_printf系统函数在php中打印字符串

    下载一个php的源代码包,这里使用的是php 4.0.5版,解压后会看到php的根目录下会有README.EXT_SKEL这样一个文件,打开详细阅读了一下,发现了一个非常好用的工具,这个工具可以帮你构 ...

  6. js打印Iframe中的内容,并且不需要预览。

    js打印Iframe中的内容,并且不需要预览 js代码如下: <script type="text/javascript" language="Javascript ...

  7. window.print打印指定html元素中的内容

    通常有些时候我们项目过程中使用到打印功能,而wndow.print便是系统里提供的一个函数. 但是直接使用的话,它打印的将是整个页面的所有元素,而有些时候我们又只需要打印部分内容. <body& ...

  8. 1.关于QT中的Graphics绘图,定时器,动画,将窗口中的内容打印到图片上,打印机,打印预览

     1 新建项目 A  修改pro中的内容如下: HEADERS += \ MyWidget.h SOURCES += \ MyWidget.cpp QT += gui widgets prints ...

  9. 过滤器将获取到的内容注入到servlet的request中

    过滤器将获取到的内容注入到servlet的request中

随机推荐

  1. 使用 Hexo 搭建静态博客

    目录 Hexo 简介 什么是 Hexo? Hexo 安装 Hexo 建站 Hexo 配置 Hexo 自定义主题 Hexo 写作 Hexo 服务器 Hexo 生成与发布 一键部署 Hexo 站点到 gi ...

  2. 「10.10」神炎皇(欧拉函数)·降雷皇(线段树,DP)·幻魔皇

    A. 神炎皇 很好的一道题,可能第一次在考场上遇到欧拉函数 题意:对于一个整数对 $(a,b)$,若满足 $a\times b\leq n$且$a+b$是$a\times b$的因子, 则称为神奇的数 ...

  3. Echarts中X轴坐标太密集,分段显示

    在axisLabel中设置刻度间隔interval,再加上强制显示最大值showMaxLabel和最小值showMinLabel axisLabel: {//X轴文字 interval: day == ...

  4. CS 面试题目总结(问题+答案)

    开源了一个新的github仓库CS 面试题目总结(问题+答案),主要总结一些CS大厂常见的面试问题,所有的问题与答案参考了网络上的许多博客和github仓库,也希望各位读者能够对这个仓库进行补充,毕竟 ...

  5. OpenGL 实用攻关 001 准备(开题)

    开篇 这里是OpenGL学习中的随笔,会大致讲述定下的目标需求,思路和贴出认为的关键代码以及git仓库地址.会选择性的讲述途中遇到的陷阱,和注意点. 一些资源 笔者是windows 操作系统 VS 2 ...

  6. @EnableDiscoveryClient与Nacos自动注册

    前一阵看到有篇博客说cloud从Edgware版本开始,可以不加@EnableDiscoveryClient注解,只要配置好注册中心的相关配置即可自动开启服务注册功能,比较好奇其中的原理,研究了一番特 ...

  7. 不藏了,这些Java反射用法总结都告诉你们

    摘要:Java反射是一种非常强大的机制,它可以在同一个系统中去检测内部的类的字段.方法和构造函数.它非常多的Java框架中,都大量应用了反射技术,如Hibernate和Spring.可以说,反射机制的 ...

  8. POJ 1654 Area 多边形面积 G++会WA

    #include<stdio.h> #include<algorithm> #include <cstring> using namespace std; type ...

  9. Docker:如何修改Docker0网桥的默认网段

    1. 背景 Docker 服务启动后默认会创建一个 docker0 网桥(其上有一个 docker0 内部接口),它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络. ...

  10. Https:Java代码设置使用证书访问Https

    设置证书进行访问或被访问操作 String keyStore = "keyStore的文件路径": String KEY_STORE_PWD = "1234"; ...