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. Redis源码解析之跳跃表(一)

    跳跃表(skiplist) 有序集合(sorted set)是Redis中较为重要的一种数据结构,从名字上来看,我们可以知道它相比一般的集合多了一个有序.Redis的有序集合会要求我们给定一个分值(s ...

  2. 实现一个带有动效的 React 弹窗组件

    我们在写一些 UI 组件时,若不考虑动效,就很容易实现,主要就是有无的切换(类似于 Vue 中的 v-if 属性)或者可见性的切换(类似于 Vue 中的 v-show 属性). 1. 没有动效的弹窗 ...

  3. 从零开始学前端,React框架背后的核心机制和原理JSX

    什么是React React是起源于Facebook的一个前端框架,用于构建用户界面的JavaScript库,Facebook用来探索一种更加高效优雅的Javascript MVC框架来架设Insta ...

  4. Elasticsearch的配置学习笔记

    文/朱季谦 Elasticsearch是一个基于Lucene的搜索服务器.它提供一个分布式多用户能力的全文搜索引擎,基于RESTful web接口,Elasticsearch是用Java语言开发的. ...

  5. HDU 1686 Oulipo kmp裸题

    kmp算法可参考 kmp算法 汇总 #include <bits/stdc++.h> using namespace std; const int maxn=1000000+5; cons ...

  6. 10 年 bloger 告诉你要不要写博客,又该如何优雅地写博客?

    关于作者:程序猿石头(ID: tangleithu),现任阿里巴巴技术专家,清华学渣,前大疆后端 Leader.公众号后台回复关键字 "1024" 获取程序员大厂面试指南. 图:D ...

  7. Docker:Docker常用命令

    docker信息 ##查看docker容器版本 docker version ##查看docker容器信息 docker info ##查看docker容器帮助 docker --help 镜像列表 ...

  8. js定时器中引用的外部函数如何传递参数

    问题:比如在一个点击事件中我需要将点击事件参数event传入到定时器中,如果只是单纯的在setTimeout(timer(e),1000)中写上括弧e,则该定时器不会等到1s才执行,而是会立即执行.那 ...

  9. 如何为HttpServer服务器配置PHP FastCGI,从而让HttpServer具备动态交互能力

    一.软件准备 1.下载HttpServer :HttpServer.zip HttpServer是一款windows平台下基于IOCP模型的轻量级.高并发.高性能web服务器(参见文章). 2.下载W ...

  10. Git远程操作详解(clone、remote、fetch、pull、push)

    https://blog.csdn.net/u013374164/article/details/79091677 Git是目前最流行的版本管理系统,学会Git几乎成了开发者的必备技能. Git有很多 ...