深入刨析tomcat 之---第10篇 how tomcat works 第13章,Response 发送错误信息 sendError
writedby 张艳涛 在浏览器中发送一个错误应用url 那么tomcat是如何发送错误的呢?
基本上是发送http 的response协议,分为两部分一部分是response设置头信息, 那么先分析一下,tomcat是如花添加响应头的
当我发送:http://localhost:8080/app4/Primitive 的时候,我的应用名字为app1 那么tomcat 会将url 的app4/Primitve进行切分,将app4 做为一个host,如果有标准StandardHost 的时候, 那么看代码
public void invoke(Request request, Response response,
ValveContext valveContext)
throws IOException, ServletException { // Validate the request and response object types
if (!(request.getRequest() instanceof HttpServletRequest) ||
!(response.getResponse() instanceof HttpServletResponse)) {
return; // NOTE - Not much else we can do generically
} // Select the Context to be used for this Request
StandardHost host = (StandardHost) getContainer();
Context context = (Context) host.map(request, true);
if (context == null) {
((HttpServletResponse) response.getResponse()).sendError
(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
sm.getString("standardHost.noContext"));
return;
} // Bind the context CL to the current thread
Thread.currentThread().setContextClassLoader
(context.getLoader().getClassLoader()); // Update the session last access time for our session (if any)
HttpServletRequest hreq = (HttpServletRequest) request.getRequest();
String sessionId = hreq.getRequestedSessionId();
if (sessionId != null) {
Manager manager = context.getManager();
if (manager != null) {
Session session = manager.findSession(sessionId);
if ((session != null) && session.isValid())
session.access();
}
} // Ask this Context to process this request
context.invoke(request, response); }
结果是context找不到,就发送错误信息
public void sendError(int sc, String msg)
throws IOException { if (isCommitted())
throw new IllegalStateException
(/*sm.getString("responseBase.reset.ise")*/); resp.setAppCommitted(true); ((HttpServletResponse) response).sendError(sc, msg); }
-->
public void sendError(int status, String message) throws IOException {
addHeader("Connection", "close");
super.sendError(status, message);
}
-->
public void sendError(int status, String message) throws IOException {
if (isCommitted())
throw new IllegalStateException
(sm.getString("httpResponseBase.sendError.ise"));
if (included)
return; // Ignore any call from an included servlet
setError();
// Record the status code and message.
this.status = status; //500
this.message = message; //Cannot find message associated with key 'standardHost.noContext'
// Clear any data content that has been buffered
resetBuffer();
// Cause the response to be finished (from the application perspective)
setSuspended(true);
}
设置respose对象的header属性
进入 ErrorReportValve 错误页面处理类
protected void report(Request request, Response response,
Throwable throwable)
throws IOException { // Do nothing on non-HTTP responses
if (!(response instanceof HttpResponse))
return;
HttpResponse hresponse = (HttpResponse) response;
if (!(response instanceof HttpServletResponse))
return;
HttpServletResponse hres = (HttpServletResponse) response;
int statusCode = hresponse.getStatus();
String message = RequestUtil.filter(hresponse.getMessage());
if (message == null)
message = ""; // Do nothing on a 1xx and 2xx status
if (statusCode < 300)
return;
// Do nothing on a NOT MODIFIED status
if (statusCode == HttpServletResponse.SC_NOT_MODIFIED)
return; // FIXME: Reset part of the request
/*
try {
if (hresponse.isError())
hresponse.reset(statusCode, message);
} catch (IllegalStateException e) {
;
}
*/ Throwable rootCause = null; if (throwable != null) { if (throwable instanceof ServletException)
rootCause = ((ServletException) throwable).getRootCause(); } // Do nothing if there is no report for the specified status code
String report = null;
try {
report = sm.getString("http." + statusCode, message);
} catch (Throwable t) {
;
}
if (report == null)
return; StringBuffer sb = new StringBuffer(); sb.append("<html><head><title>");
sb.append(ServerInfo.getServerInfo()).append(" - ");
sb.append(sm.getString("errorReportValve.errorReport"));
sb.append("</title>");
sb.append("<STYLE><!--");
sb.append("H1{font-family : sans-serif,Arial,Tahoma;color : white;background-color : #0086b2;} ");
sb.append("H3{font-family : sans-serif,Arial,Tahoma;color : white;background-color : #0086b2;} ");
sb.append("BODY{font-family : sans-serif,Arial,Tahoma;color : black;background-color : white;} ");
sb.append("B{color : white;background-color : #0086b2;} ");
sb.append("HR{color : #0086b2;} ");
sb.append("--></STYLE> ");
sb.append("</head><body>");
sb.append("<h1>");
sb.append(sm.getString("errorReportValve.statusHeader",
"" + statusCode, message)).append("</h1>");
sb.append("<HR size=\"1\" noshade>");
sb.append("<p><b>type</b> ");
if (throwable != null) {
sb.append(sm.getString("errorReportValve.exceptionReport"));
} else {
sb.append(sm.getString("errorReportValve.statusReport"));
}
sb.append("</p>");
sb.append("<p><b>");
sb.append(sm.getString("errorReportValve.message"));
sb.append("</b> <u>");
sb.append(message).append("</u></p>");
sb.append("<p><b>");
sb.append(sm.getString("errorReportValve.description"));
sb.append("</b> <u>");
sb.append(report);
sb.append("</u></p>"); if (throwable != null) {
StringWriter stackTrace = new StringWriter();
throwable.printStackTrace(new PrintWriter(stackTrace));
sb.append("<p><b>");
sb.append(sm.getString("errorReportValve.exception"));
sb.append("</b> <pre>");
sb.append(stackTrace.toString());
sb.append("</pre></p>");
if (rootCause != null) {
stackTrace = new StringWriter();
rootCause.printStackTrace(new PrintWriter(stackTrace));
sb.append("<p><b>");
sb.append(sm.getString("errorReportValve.rootCause"));
sb.append("</b> <pre>");
sb.append(stackTrace.toString());
sb.append("</pre></p>");
}
} sb.append("<HR size=\"1\" noshade>");
sb.append("<h3>").append(ServerInfo.getServerInfo()).append("</h3>");
sb.append("</body></html>"); try { Writer writer = response.getReporter(); if (writer != null) { Locale locale = Locale.getDefault(); try {
hres.setContentType("text/html");
hres.setLocale(locale);
} catch (Throwable t) {
if (debug >= 1)
log("status.setContentType", t);
} // If writer is null, it's an indication that the response has
// been hard committed already, which should never happen
writer.write(sb.toString());
writer.flush(); } } catch (IOException e) {
;
} catch (IllegalStateException e) {
;
} }
获取
public PrintWriter getReporter() {
if (isError()) {
try {
if (this.stream == null)
this.stream = createOutputStream();
} catch (IOException e) {
return null;
}
return (new PrintWriter(this.stream));
} else {
if (this.stream != null) {
return null;
} else {
try {
return (new PrintWriter(getOutputStream()));
} catch (IOException e) {
return null;
}
}
}
}
获取的out流 底层是 ResponseStream ,这个流我write方法底层是写到response的buffer数组中, 在connector类中,完成了调用,接着就处理发送页面
发送头的方法是sendHeaders,接着发body
深入刨析tomcat 之---第10篇 how tomcat works 第13章,Response 发送错误信息 sendError的更多相关文章
- 深入刨析tomcat 之---第8篇 how tomcat works 第11章 11.9应用程序,自定义Filter,及注册
writed by 张艳涛, 标签:全网独一份, 自定义一个Filter 起因:在学习深入刨析tomcat的学习中,第11章,说了调用过滤链的原理,但没有给出实例来,自己经过分析,给出来了一个Filt ...
- 深入刨析tomcat 之---第9篇 how tomcat works 第9章,Session的实现 关于request.setContext(context)
writedby 张艳涛,在学第9章session的时候,做了个实验在给的demo代码中添加了 package com.zyt.tomcat.ex09.core; public class Simpl ...
- 深入刨析tomcat 之---第12篇 how tomcat works( 第17章 ) 解析catalina.bat 梳理启动流程
我们如何启动tomcat呢? 答案是双击startup.bat文件,这个文件在bin目录下 @echo off 不显示批处理命令 rem Licensed to the Apache Softw ...
- 深入刨析tomcat 之---第11篇 how tomcat works( 第15章 ) 如何解析web.xml 文件
writedby 张艳涛 记得当年是学习jsp的时候,写过web.xml中的标签.在之后的springmvc中也是有关于配置mvc 过滤器 和dispatchServlet的标签,之前是看不懂呢!看到 ...
- 深入刨析tomcat 之---第6篇 how tomcat works 第5章 容器实现原理
writedby 张艳涛
- python爬微信公众号前10篇历史文章(2)-拼接URL&发送http请求
如何拼接想要的url http://weixin.sogou.com/weixin?type=1&page=1&ie=utf8&query=%E5%A4%A7%E7%BA%BD ...
- 深入刨析tomcat 之---第2篇,解决第3章bug 页面不显示内容http://localhost:8080/servlet/ModernServlet?userName=zhangyantao&password=1234
writedby 张艳涛7月2日, 在学习第4张的过程中,发现了前一篇文章写的是关于1,2张的bug不用设置response响应头,需要在servlet的service()方法里面写是错误想 serv ...
- 30s源码刨析系列之函数篇
前言 由浅入深.逐个击破 30SecondsOfCode 中函数系列所有源码片段,带你领略源码之美. 本系列是对名库 30SecondsOfCode 的深入刨析. 本篇是其中的函数篇,可以在极短的时间 ...
- Orchard 刨析:导航篇
之前承诺过针对Orchard Framework写一个系列.本应该在昨天写下这篇导航篇,不过昨天比较累偷懒的去玩了两盘单机游戏哈哈.下面进入正题. 写在前面 面向读者 之前和本文一再以Orchard ...
随机推荐
- pandas的数据结构介绍(一)—— Series
pandas两个主要数据结构之一--Series 类似于一维数组,由一组数据和与其相关的一组索引组成 obj = Series([4, 7, -5, 3], index=['d', 'b', 'a', ...
- 《四大点,搞懂Redis到底快在哪里?》
一.开发语言 二.纯内存访问 三.单线程 四.非阻塞多路I/O复用机制 前言 Redis是一种基于键值对(Key-Value)的NoSQL数据库 ,Redis的Value可以由String,hash, ...
- 21、linux系统grup和bios加密
21.1.grup加密(加密单用户模式): 1.使用加密算法对grup密码进行加密: 2.修改grup.conf配置文件: 21.2.bios加密(因为救援模式可以破解grup加密,所以使用bios加 ...
- POJ 1220 大数字的进制转换,偷下懒,用java
题意为进制转换,Java的大数类就像是作弊 import java.math.BigInteger; import java.util.Scanner; public class Main { pub ...
- Docker搭建Prometheus+grafana监控系统
一.Prometheus简介 1.简介 Prometheus是由SoundCloud开发的开源监控报警系统和时序列数据库(TSDB). Prometheus使用Go语言开发,是Google BorgM ...
- 【知识点】inline函数、回调函数、普通函数
目录 一.inline内联函数 1.1 使用 1.2 编译器对 inline 函数处理步骤 1.3 优缺点 1.3.1 优点 1.3.2 慎用内联 1.3.3 不宜使用内联 1.4 虚函数(virtu ...
- php操作redis集群哨兵模式
前段时间项目里正好用到了redis的集群哨兵部署,因为此前并无了解过,所以一脸懵逼啊,查阅了几篇资料,特此综合总结一下,作为记录. 写在前沿:随着项目的扩张,对redis的依赖也越来越大,为了增强re ...
- 深入理解Java并发类——AQS
目录 什么是AQS 为什么需要AQS AQS的核心思想 AQS的内部数据和方法 如何利用AQS实现同步结构 ReentrantLock对AQS的利用 尝试获取锁 获取锁失败,排队竞争 参考 什么是AQ ...
- external-resizer 源码分析/pvc 扩容分析
kubernetes ceph-csi分析目录导航 基于tag v0.5.0 https://github.com/kubernetes-csi/external-resizer/releases/t ...
- 对抗攻击(一) FGSM
引言 在对抗样本综述(二)中,我们知道了几种著名的对抗攻击和对抗防御的方法.下面具体来看下几种对抗攻击是如何工作的.这篇文章介绍FGSM(Fast Gradient Sign Method). 预备知 ...