Tom_No_02 Servlet向流中打印内容,之后在调用finsihResponse,调用上是先发送了body,后发送Header的解释
上次在培训班学上网课的时候就发现了这个问题,一直没有解决,昨天又碰到了,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的解释的更多相关文章
- 使用定时器实现在console中打印内容
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 用servlet在网页中打印字符串(初接触)、servlet调用过程
一.servlet是什么: 二.在官方文档中点servlet 这就是servlet的方法,这里说一下什么叫生命周期的方法(life-cycle methods):就是这个对象一旦创生之后一定会执行的方 ...
- 从servlet向jsp中传数据用Java接收js调用
servlet: response.sendRedirect("showMessage.jsp?ValueA=1"); jsp: var a=<%=request.getPa ...
- H264码流中SPS PPS详解<转>
转载地址:https://zhuanlan.zhihu.com/p/27896239 1 SPS和PPS从何处而来? 2 SPS和PPS中的每个参数起什么作用? 3 如何解析SDP中包含的H.264的 ...
- 描述了say_hello函数的具体内容,调用zend_printf系统函数在php中打印字符串
下载一个php的源代码包,这里使用的是php 4.0.5版,解压后会看到php的根目录下会有README.EXT_SKEL这样一个文件,打开详细阅读了一下,发现了一个非常好用的工具,这个工具可以帮你构 ...
- js打印Iframe中的内容,并且不需要预览。
js打印Iframe中的内容,并且不需要预览 js代码如下: <script type="text/javascript" language="Javascript ...
- window.print打印指定html元素中的内容
通常有些时候我们项目过程中使用到打印功能,而wndow.print便是系统里提供的一个函数. 但是直接使用的话,它打印的将是整个页面的所有元素,而有些时候我们又只需要打印部分内容. <body& ...
- 1.关于QT中的Graphics绘图,定时器,动画,将窗口中的内容打印到图片上,打印机,打印预览
1 新建项目 A 修改pro中的内容如下: HEADERS += \ MyWidget.h SOURCES += \ MyWidget.cpp QT += gui widgets prints ...
- 过滤器将获取到的内容注入到servlet的request中
过滤器将获取到的内容注入到servlet的request中
随机推荐
- Mysql优化(出自官方文档) - 第二篇
Mysql优化(出自官方文档) - 第二篇 目录 Mysql优化(出自官方文档) - 第二篇 1 关于Nested Loop Join的相关知识 1.1 相关概念和算法 1.2 一些优化 1 关于Ne ...
- Spring Cloud专题之三:Hystrix
在微服务架构中,我们将系统拆分成很多个服务单元,各单位的应用间通过服务注册与订阅的方式相互依赖.由于每个单元都在不同的进程中运行,依赖通过远程调用的方式执行,这样就有可能因为网络原因或是依赖服务自身问 ...
- Local dimming algorithm in matlab
LED局部背光算法的matlab仿真 最近公司接了华星光电(TCL)的一个项目LCD-BackLight-Local-Diming-Algorithm-IP ,由于没有实际的硬件,只能根据客户给的论文 ...
- 35、sudo权限设置
提示:sudo的介绍在"13.linux中用户和用户组"中有详细介绍: (1)简历里要加上如下项目经验: 服务器用户权限管理改造方案与实施项目 日期: 在了解公司业务流程后,提出权 ...
- as3.0 Flex 图像处理
as3.0 Flex 图像处理 已知的一些图像处理,主要是得到颜色过滤矩阵,不完整,大家一起来补充. //颜色转换数组,所有的0都是可调值public var colorArray:Array = [ ...
- hud 3308 LCIS 线段树 区间合并
题意: Q a b 查询[a, b]区间的最长连续递增子序列的长度 U a b 将下表为a的元素更新为b 区间合并一般都有3个数组:区间最值,左区间最值和右区间最值 具体详见代码 #include & ...
- Quartz:Quartz定时代码实现
1.添加pom.xml <dependency> <groupId>org.quartz-scheduler</groupId> <artifactId> ...
- getopt模块的学习
在运行程序时,可能需要根据不同的条件,输入不同的命令行选项来实现不同的功能.目前有短选项和长选项两种格式.短选项格式为"-"加上单个字母选项:长选项为"--"加 ...
- 递推算法,AI衍生
引言 最近在刷leetcode算法题的时候,51题很有意思: 题目是这样的: n 皇后问题 研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击.给你一个整数 n ,返回 ...
- 关于SOA和AOP
SOA:面向服务的架构(SOA)是一个组件模型,它将应用程序的不同功能单元(称为服务)通过这些服务之间定义良好的接口和契约联系起来.C/S端框架有WPF,服务端应用程序有WCF.asp.net web ...