文档章节

Tomcat8源码分析-请求处理过程(含源码中新建web应用一起调试)

特拉仔
 特拉仔
发布于 2019/12/11 14:31
字数 1143
阅读 39
收藏 1

上一篇:Tomcat8源码分析-启动流程-start方法

 此篇主要将Tomcat8从接收请求到处理请求的时序图画出来,并用文字描述一下主要流程

时序图

图片有点大,需要点开了放大看

说明

文字描述流程之前先提示如下两点:
1.Acceptor、Poller、SocketProcessor都是NioEndpoint的内部类

2.Tomcat不一定只有NioEndpoint还有Nio2Endpoint AprEndpoint,只是常规的请求和默认都使用的是http和nio,所以在时序图中就用NioEndpoint了

 

Acceptor负责接收发起的请求,经过NioEndpoint和Poller将socket最终包装为一个PollerEvent放入到SynchronizedQueue同步队列当中,接着继续等待新的请求到底重复前面的步骤

Poller循环判断同步队列中是否有问题处理的Event,如果有则使用WindowsSelectorImpl读取socket,将socket中的attachment添加到SocketProcessor( implements runnable),使用线程池启动SocketProcessor

SocketProcessor经过一层层调用直到按照StandardEngine-StandardHost-StandardContext-StandardWrapper顺序执行它们的Pipeline.First Valve,最后由StandardWrapperValve执行Servlet的加载,加载完后会调用Servlet的init方法,然后由ApplicationFilterChain调用HttpServlet的service,进而调用到自己的Servlet中的doXxx方法

如图:

 

CoyoteAdapter里面的postParseRequest方法包含了非常重要的根据path找到对应Servlet的逻辑,具体规则如下:

先精确匹配-通配符匹配-后缀名匹配(默认有jsp和jspx,这也是为什么可以处理jsp的原因)-Welcome资源匹配-前面都没匹配到就是DefaultServlet

匹配成功之后,StandardWrapperValve对应的StandardWrapper.servlet才会是我们想要的,才能实现真正的业务调用。

总结:

1.接收请求参数的流程还是比较简单清晰,里面使用了模板方法模式、责任链模式(如Pipeline的执行)、门面模式等。

2.里面发现了两种扩展点

  • 自定义Valve,将Valve配置到不同容器下面,可以在不同时间点和范围(调用顺序决定)作用与请求过程
  • 自定义Filter,Filter是配置在应用的web.xml中的,只能作用与当前这个应用,并且可以配置Filter拦截的请求格式

3.要想快速搞清楚调用过程,建议直接在自定义的Servlet方法中加断点,要达到这个效果需要新建的web应用和tomcat是在同一个项目中,方式如下:

先看看idea中的目录结构

图中还有一处没有标记出来:就是在idea中选择新建了一个maven的web-module之后是没有源码目录的,我是在main下新建的一个java目录,然后右键标记为source root,再在目录下编写Servlet的

Servlet代码

package com.jv.tomcat;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class TestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setHeader("content-type", "text/html;charset=UTF-8");
        resp.setCharacterEncoding("UTF-8");
        System.out.println("My TestServlet  doGet");
        resp.getWriter().print("<html><body><h1>My TestServlet  doGet</h1></body></html>");
    }
}

看看pom.xml

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>apache-tomcat-8</artifactId>
        <groupId>gxf</groupId>
        <version>1.0</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>testweb</artifactId>
    <packaging>war</packaging>

    <name>testweb</name>
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        <!-- 配置了这个依赖,需要将tomcat源码install到本地maven仓库,否则会提示依赖不存在 -->
        <dependency>
            <groupId>org.apache.tomcat</groupId>
            <artifactId>tomcat-8</artifactId>
            <version>8.5</version>
        </dependency>
    </dependencies>

    <build>
        <finalName>testweb</finalName>
        <pluginManagement>
            <plugins>
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.0.2</version>
                </plugin>
                <!-- 编译的时候将class文件输出到配置目录下,因为打war包的时候会从整个目录复制class文件 -->
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.0</version>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                        <encoding>UTF-8</encoding>
                        <outputDirectory>F:\projects\own\tomcat-8.5.49\testweb\src\main\webapp\WEB-INF\classes</outputDirectory>
                    </configuration>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.22.1</version>
                </plugin>
                <!-- 打war包,并将war包复制到tomcat的工作目录下 -->
                <plugin>
                    <artifactId>maven-war-plugin</artifactId>
                    <configuration>
                        <archiveClasses>true</archiveClasses>
                        <outputDirectory>F:\projects\own\tomcat-8.5.49\deploy-test\webapps</outputDirectory>
                    </configuration>
                    <version>3.2.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>2.5.2</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>2.8.2</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

 

© 著作权归作者所有

特拉仔
粉丝 62
博文 266
码字总数 259663
作品 0
渝中
部门经理
私信 提问
Tomcat8源码分析-启动流程-start方法

上一篇:Tomcat8源码分析-启动流程-load方法 前面讲了启动流程中的Catalina.load,进一步调用绝大部分组建的init操作,主要完成对server.xml解析,并根据解析的结果结合设置的Rule(规则)构造...

特拉仔
2019/12/08
44
0
在Intellij下远程调试tomcat应用(含tomcat源码调试)

环境 服务器: 操作系统:centos6 jdk:1.7 tomcat:8.5.9 本地: 操作系统:mac osx 10.11.6 jdk:1.7 intellij:2016.2 tomcat:8.5.9(本地也需要下载tomcat) 应用调试步骤 java应用远程...

wooyoo
2017/01/23
0
0
Idea中构建Tomcat8源码开发环境

在研究SpringMVC源码之前得先看看Tomcat的源码(因为WEB应用要工作在容器中)。先构建Tomcat8的源码环境 下载 进入Tomcat官网https://tomcat.apache.org/download-80.cgi,选择tomcat8,下载...

特拉仔
2019/11/27
61
0
Spring MVC 原理探秘 - 一个请求的旅行过程

1.简介 在前面的文章中,我较为详细的分析了 Spring IOC 和 AOP 部分的源码,并写成了文章。为了让我的 Spring 源码分析系列文章更为丰富一些,所以从本篇文章开始,我将来向大家介绍一下 Sp...

coolblog.xyz
2018/07/02
0
0
Tomcat 源码分析(-)启动过程分析

前面几篇文章分别介绍了Tomcat的安装、优化和框架,本文主要用于分析Tomcat源码启动过程,研究一个框架最好的着手方式可能就是研究它的启动过程,因为在这过程中我们可以看到它内部的层次关系...

AaronSheng
2016/11/28
171
0

没有更多内容

加载失败,请刷新页面

加载更多

什么是专用字节,虚拟字节,工作集?

我试图使用perfmon Windows实用程序来调试进程中的内存泄漏。 这就是perfmon解释这些术语的方式: Working Set是此过程的工作集的当前大小(以字节为单位)。 工作集是过程中线程最近触及的一...

技术盛宴
28分钟前
52
0
创建重复N次的单个项目的列表

我想创建一系列长度不一的列表。 每个列表将包含相同的元件e ,重复n次(其中n列表=长度)。 如何创建列表,而不为每个列表使用列表[e for number in xrange(n)] ? #1楼 在Python中创建重复...

javail
44分钟前
64
0
为什么图片反复压缩后普遍会变绿,而不是其他颜色?

作者:Lion Yang 链接:https://www.zhihu.com/question/29355920/answer/119088684 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 业余版概要:安卓的...

shzwork
今天
47
0
每天AC系列(二):最接近的三数之和

1 题目 leetcode第16题,给定一个数组与一个目标数,找出数组中其中的三个数,这三个数的和要与目标数最接近。 2 暴力 按惯例先来一次O(n3)的暴力: int temp = nums[0]+nums[1]+nums[2];fo...

Blueeeeeee
今天
46
0
EFK教程(5) - ES集群开启用户认证

基于ES内置及自定义用户实现kibana和filebeat的认证 作者:“发颠的小狼”,欢迎转载 目录 ▪ 用途 ▪ 关闭服务 ▪ elasticsearch-修改elasticsearch.yml配置 ▪ elasticsearch-开启服务 ▪ ...

小慢哥
今天
58
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部