前一篇博客,我总结了Tomcat对于生命周期组件的管理。在了解了容器的启动之后,我们开始剖析它的内部运行机制。今天我们来分析一下Tomcat如何处理Request。Socket作为网络通信的基础也是Request和Response的底层实现,有过Socket使用经验的读者一定不会对下面的伪代码陌生:

// Java伪代码
...
while(true) {
Socket soc = ServerSocket.accept(); // 监听并阻塞
new Thread(new Runnable() { // 开辟新的线程处理Socket
inputStream(soc); // 读取Socket中的数据
outputStream(soc); // 写入数据
});
}
...

一、从Socket到Request

Tomcat容器对Socket的处理思路与以上伪代码基本一致,只是更加复杂。下图展示了从Tomcat启动到Socket到来后,主要类的调动过程(虚线箭头表示有新的线程启动):

Acceptor是定义在JIoEndpoint中的内部类实现了Runnable接口。在run方法中定义了循环语句while (running){...}重点是ServerSocketFactory获取监听端口(默认8080)上的Socket请求

Socket socket = null;
try {
// Accept the next incoming connection from the server
// socket
socket = serverSocketFactory.acceptSocket(serverSocket);
...

然后,这个Socket对象会被封装成SocketWrapper对象并交给给JIoEndpoint的另一个内部类SocketProcessor处理。

protected boolean processSocket(Socket socket) {
// Process the request from this socket
try {
SocketWrapper<Socket> wrapper = new SocketWrapper<Socket>(socket);
wrapper.setKeepAliveLeft(getMaxKeepAliveRequests());
wrapper.setSecure(isSSLEnabled());
...

一直到AbstractHttp11Processor.process方法,我们第一次见到了Request的身影。不过此时的Request实际上是org.apache.coyote.Request,它是Tomcat内部的定义类并且被final修饰。在CoyoteAdapter.service方法中,它又被处理成:org.apache.catalina.connector.Request,它继承了HttpServletRequest。直到这时,从Socket到Request才真正完成。

二、Pipeline、FilterChain以及设计模式

ContainerBase是Tomcat中的生命周期组件。它包含了4个标准的实现类:StandardContext、StandardEngine、StandardHost和StandardWrapper。每一个Container对象都含有各自的Pipeline和Valve。

/**
* The Pipeline object with which this Container is associated.
*/
protected Pipeline pipeline = new StandardPipeline(this); /**
* Create a new StandardContext component with the default basic Valve.
*/
public StandardContext() { super();
pipeline.setBasic(new StandardContextValve());
...
}
...

它们通过Container的构造函数被初始化,并负责处理Request。每一个Containner组件都实现了各自的invoke方法,具体的业务逻辑读者可以自己去分析。

经过4次invoke,Request会继续交给FilterChain(责任链模式的核心对象)处理。

ApplicationFilterChain filterChain = factory.createFilterChain(request, wrapper, servlet);

try {
if ((servlet != null) && (filterChain != null)) {
if (context.getSwallowOutput()) {
...
} else {
if (request.isAsyncDispatching()) {
...
} else if (comet) {
...
} else {
filterChain.doFilter(request.getRequest(), response.getResponse());
}
}
...

经过多个Filter的处理,才会交到Servlet的手中。

Tomcat 源码分析(二)——Request处理全过程的更多相关文章

  1. Tomcat源码分析二:先看看Tomcat的整体架构

    Tomcat源码分析二:先看看Tomcat的整体架构 Tomcat架构图 我们先来看一张比较经典的Tomcat架构图: 从这张图中,我们可以看出Tomcat中含有Server.Service.Conn ...

  2. Tomcat 源码分析(转)

    本文转自:http://blog.csdn.net/haitao111313/article/category/1179996 Tomcat源码分析(一)--服务启动 1. Tomcat主要有两个组件 ...

  3. Tomcat源码分析三:Tomcat启动加载过程(一)的源码解析

    Tomcat启动加载过程(一)的源码解析 今天,我将分享用源码的方式讲解Tomcat启动的加载过程,关于Tomcat的架构请参阅<Tomcat源码分析二:先看看Tomcat的整体架构>一文 ...

  4. [Tomcat 源码分析系列] (二) : Tomcat 启动脚本-catalina.bat

    概述 Tomcat 的三个最重要的启动脚本: startup.bat catalina.bat setclasspath.bat 上一篇咱们分析了 startup.bat 脚本 这一篇咱们来分析 ca ...

  5. Tomcat源码分析(二)------ 一次完整请求的里里外外

    Tomcat源码分析(二)------ 一次完整请求的里里外外   前几天分析了一下Tomcat的架构和启动过程,今天开始研究它的运转机制.Tomcat最本质就是个能运行JSP/Servlet的Web ...

  6. Tomcat源码分析--转

    一.架构 下面谈谈我对Tomcat架构的理解 总体架构: 1.面向组件架构 2.基于JMX 3.事件侦听 1)面向组件架构 tomcat代码看似很庞大,但从结构上看却很清晰和简单,它主要由一堆组件组成 ...

  7. Tomcat源码分析

    前言: 本文是我阅读了TOMCAT源码后的一些心得. 主要是讲解TOMCAT的系统框架, 以及启动流程.若有错漏之处,敬请批评指教! 建议: 毕竟TOMCAT的框架还是比较复杂的, 单是从文字上理解, ...

  8. Tomcat源码分析 (四)----- Pipeline和Valve

    在 Tomcat源码分析 (二)----- Tomcat整体架构及组件 中我们简单分析了一下Pipeline和Valve,并给出了整体的结构图.而这一节,我们将详细分析Tomcat里面的源码. Val ...

  9. tomcat源码--springboot整合tomcat源码分析

    1.测试代码,一个简单的springboot web项目:地址:https://gitee.com/yangxioahui/demo_mybatis.git 一:tomcat的主要架构:1.如果我们下 ...

  10. tomcat源码分析(三)一次http请求的旅行-从Socket说起

    p { margin-bottom: 0.25cm; line-height: 120% } tomcat源码分析(三)一次http请求的旅行 在http请求旅行之前,我们先来准备下我们所需要的工具. ...

随机推荐

  1. GIT命令一页纸

    ,配置用户名和邮箱 $ git config --global user.name "Your Name" $ git config --global user.email &qu ...

  2. mysql存储过程 详细注释

    原文:https://my.oschina.net/u/3582142/blog/1581929

  3. MySQL 行锁 表锁机制

    MySQL 表锁和行锁机制 行锁变表锁,是福还是坑?如果你不清楚MySQL加锁的原理,你会被它整的很惨!不知坑在何方?没事,我来给你们标记几个坑.遇到了可别乱踩.通过本章内容,带你学习MySQL的行锁 ...

  4. python基础(六)dict字典和文件操作open

    字典dict 使用key来标注value的数据类型,key和value是一一对应的.在字典中key是唯一的,所以字典也是无序的. #定义一个字典 dict = { 'name' : 'sylar', ...

  5. [Spark内核] 第32课:Spark Worker原理和源码剖析解密:Worker工作流程图、Worker启动Driver源码解密、Worker启动Executor源码解密等

    本課主題 Spark Worker 原理 Worker 启动 Driver 源码鉴赏 Worker 启动 Executor 源码鉴赏 Worker 与 Master 的交互关系 [引言部份:你希望读者 ...

  6. 第十三章:Python の 网络编程进阶(二)

    本課主題 SQLAlchemy - Core SQLAlchemy - ORM Paramiko 介紹和操作 上下文操作应用 初探堡垒机 SQLAlchemy - Core 连接 URL 通过 cre ...

  7. adb 获取Android手机信息命令(2)

    #Android命令 #获取手机名称 GET_PHONE_NAME = 'adb shell getprop ro.product.model' #获取手机版本 GET_PHONE_VERSION = ...

  8. 【读书笔记】【深入理解ES6】#9-JavaScript中的类

    大多数面向对象的编程语言都支持类和类继承的特性,而JavaScript却不支持这些特性,只能通过其他方法定义并关联多个相似的对象.这个状态一直从ECMAScript 1持续到ECMAScript 5. ...

  9. 【转】jar包和war包的介绍和区别

    JavaSE程序可以打包成Jar包(J其实可以理解为Java了),而JavaWeb程序可以打包成war包(w其实可以理解为Web了).然后把war发布到Tomcat的webapps目录下,Tomcat ...

  10. Java分布式应用技术架构

    分布式架构的演进 系统架构演化历程-初始阶段架构初始阶段 的小型系统 应用程序.数据库.文件等所有的资源都在一台服务器上通俗称为LAMP特征:应用程序.数据库.文件等所有的资源都在一台服务器上.描述: ...