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的更多相关文章

  1. 深入刨析tomcat 之---第8篇 how tomcat works 第11章 11.9应用程序,自定义Filter,及注册

    writed by 张艳涛, 标签:全网独一份, 自定义一个Filter 起因:在学习深入刨析tomcat的学习中,第11章,说了调用过滤链的原理,但没有给出实例来,自己经过分析,给出来了一个Filt ...

  2. 深入刨析tomcat 之---第9篇 how tomcat works 第9章,Session的实现 关于request.setContext(context)

    writedby 张艳涛,在学第9章session的时候,做了个实验在给的demo代码中添加了 package com.zyt.tomcat.ex09.core; public class Simpl ...

  3. 深入刨析tomcat 之---第12篇 how tomcat works( 第17章 ) 解析catalina.bat 梳理启动流程

    我们如何启动tomcat呢? 答案是双击startup.bat文件,这个文件在bin目录下 @echo off    不显示批处理命令 rem Licensed to the Apache Softw ...

  4. 深入刨析tomcat 之---第11篇 how tomcat works( 第15章 ) 如何解析web.xml 文件

    writedby 张艳涛 记得当年是学习jsp的时候,写过web.xml中的标签.在之后的springmvc中也是有关于配置mvc 过滤器 和dispatchServlet的标签,之前是看不懂呢!看到 ...

  5. 深入刨析tomcat 之---第6篇 how tomcat works 第5章 容器实现原理

    writedby 张艳涛

  6. python爬微信公众号前10篇历史文章(2)-拼接URL&发送http请求

    如何拼接想要的url http://weixin.sogou.com/weixin?type=1&page=1&ie=utf8&query=%E5%A4%A7%E7%BA%BD ...

  7. 深入刨析tomcat 之---第2篇,解决第3章bug 页面不显示内容http://localhost:8080/servlet/ModernServlet?userName=zhangyantao&password=1234

    writedby 张艳涛7月2日, 在学习第4张的过程中,发现了前一篇文章写的是关于1,2张的bug不用设置response响应头,需要在servlet的service()方法里面写是错误想 serv ...

  8. 30s源码刨析系列之函数篇

    前言 由浅入深.逐个击破 30SecondsOfCode 中函数系列所有源码片段,带你领略源码之美. 本系列是对名库 30SecondsOfCode 的深入刨析. 本篇是其中的函数篇,可以在极短的时间 ...

  9. Orchard 刨析:导航篇

    之前承诺过针对Orchard Framework写一个系列.本应该在昨天写下这篇导航篇,不过昨天比较累偷懒的去玩了两盘单机游戏哈哈.下面进入正题. 写在前面 面向读者 之前和本文一再以Orchard ...

随机推荐

  1. Java第一次博客作业

    第一次博客作业 目录 三次作业题目详情 作业中的错误分析 感想与心得 题目详情 题目1:第一次作业: 类图: 题目2 类图: 题目3 类图: 题目4 题目5 题目6 类图: 题目7 类图: 题目8 第 ...

  2. 「模拟8.19 A嚎叫..(set) B主仆..(DFS) C征程..(DP+堆优化)」

    为啥这一套题目背景感到很熟悉. T1  嚎叫响彻在贪婪的厂房 考试一个小时没调出来,自闭了.......... 正解很好想,最后实在打不出来了只好暴力骗分了... 联想到以前做的题:序列(涉及质因数分 ...

  3. leetcode5698.基本计算器

    给你一个整数数组 nums ,和两个整数 limit 与 goal .数组 nums 有一条重要属性:abs(nums[i]) <= limit . 返回使数组元素总和等于 goal 所需要向数 ...

  4. Vue(5)计算属性computed

    前言 一般情况下属性都是放到data中的,但是有些属性可能是需要经过一些逻辑计算后才能得出来,那么我们可以把这类属性变成计算属性.比如以下: <div id="example" ...

  5. 《MySQL面试小抄》索引失效场景验证

    我是肥哥,一名不专业的面试官! 我是囧囧,一名积极找工作的小菜鸟! 囧囧表示:小白面试最怕的就是面试官问的知识点太笼统,自己无法快速定位到关键问题点!!! 本期主要面试考点 面试官考点之什么情况下会索 ...

  6. excel替换函数substitute

    1.substitute(需要执行替换操作的单元格区域,旧文本,新文本,第N个旧内容) 例:substitute(A1,"a","b",2)    A1=aab ...

  7. 信奥赛一本通1573:分离与合体C++分离与合体

    题目链接 #include<cstdio> #include<algorithm> using namespace std; int dp[305][305]={},jojo[ ...

  8. ps2020 将图片中的字清除 并且不损坏背景图

    步骤:1:使用选框工具选中要删除的字:2:选择-->色彩范围,选中字体颜色  :3.选择-->修改-->扩展:4.图片区域,右键填充--内容识别--确定: 1.使用选框工具选中要删除 ...

  9. Software Architecture软件架构(方法、模式与框架)纵横谈

    Software Architecture软件架构是啥 随着软件行业的发展,软件的规模越来越大,"Software Architecture软件架构"这个名词开始频繁出现.&quo ...

  10. Windows软件包管理工具:Scoop

    前言 删库跑路后,Windows系统如何快速安装应用程序,部署环境呢? 以前想过这个问题,最近在安装Hugo时发现使用软件包管理工具可以解决这个问题. 阅读建议 首先需要测试下载速度,尝试从官网下载, ...