IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 浅谈Tomcat接收到一个请求后在其内部的执行流程(源码) -> 正文阅读

[Java知识库]浅谈Tomcat接收到一个请求后在其内部的执行流程(源码)

写在前面,本文不涉及具体的tomcat内部数据处理的讲解,只涉及具体的执行流程逻辑处理。在阅读本文后,如果你能够完成tomcat源码中接收请求后的代码执行流程调试,那么本文的目的也就达到了,希望对你有帮助。

本文的大背景是,tomcat7.x,http协议,BIO模型。如文中出现表述不准确的,请告诉我,我将及时做出调整。





一、前提

在阅读们本文前,请务必要了解tomcat的启动流程,因为该篇文章会出现大量的组件类名词,如果对tomcat启动不了解的,可以参考我之前的博客:浅谈Tomcat的启动流程

通过tomcat的启动流程,你除了会明白tomcat的整体架构,你还将了解到各个组件的实例化位置,这对于后期梳理tomcat内部的执行流程至关重要。




下列的两张图来源于我之前写过的博客,均是tomcat的设计架构图






二、流程图

下图是tomcat内部处理请求的核心流程图,也是本文的大纲图示,请一定要记牢。


大致的流程描述如下:
1、浏览器发起一次http请求,是将数据发送给操作系统的缓冲池里;
2、tomcat内部通过Java的API去操作系统的缓冲池中获取此次请求;
3、然后tomcat将此次请求按照指定的协议、IO模型进行解析(请求行、请求头等);
4、再根据请求的mapping映射,一层一层的经过Pipeline管道,最终将请求中的数据传递给具体的Servlet;
5、完成操作,返回给浏览器。






三、详细流程(附源码截图)

写在前面,观察第二章的流程图示,我们需要明确几个问题:

1、如果我们想要使用Java的API自己去实现一个端口的监听,我们的做法是直接new ServerSocket(port);

2、编写一个servlet我们通常的做法是实现HttpServlet接口,然后重写doGet、doPost方法;

3、tomcat接收到的是浏览器的请求,但是发送给servlet的却只有请求体,这个过程一定经过某些处理。



1、初始化Connector

该过程在tomcat的启动过程执行,所以我直接接着tomcat的启动进行讲解,此时tomcat已经在启动的过程中了

1、实例化规则入口

下图为对应的启动的规则,前文提到的博客中有详细的解释,这里不再进行赘述。



2、根据传入的协议,选择待实例的Protocol对象。

在实例化Connector对象的时候,会调用setProtocol方法,完成对应协议的设置,然后通过反射创建对应的Protocol实例对象。

protocol参数值根据server.xml配置文件中配置决定




2、实例化Http11Protocol

实例化Http11Protocol第一步就是创建对应的IO模型

此处的JIoEndpoint表示对应的IO模型为BIO




3、调用JIoEndpoint内部类Acceptor

目前完成的工作,根据配置,创建出了connector,并且创建了具体的xxxEndpoint对象

在tomcat启动的时候,tomcat会调用具体的xxxEndponit的startInternal方法,在该方法中会调用createAcceptor方法,完成对应的监听处理。这在我之前的tomcat启动流程中的第五章有讲解



那么我们此时直接进入到JIoEndpoint的Acceptor方法中

1、接收请求

然后会调用下面的代码(源码过长,仅复制关键源码),接收浏览器发送过来,操作系统接收到的请求

socket = serverSocketFactory.acceptSocket(serverSocket);



// acceptSocket方法实现。不难发现,此处就是开启了一个服务端口
@Override
public Socket acceptSocket(ServerSocket socket) throws IOException {
    return socket.accept();
}



2、处理请求

如果接收到数据,就会调用下面的执行逻辑



3、执行对应的封装好的scoket任务

将我们的socket数据封装为一个wrapper,然后递交给线程池



4、执行SocketProcessor类的run方法

交给线程池的是一个线程任务,线程池底层会开启线程,然后线程再调用线程任务的run方法,所以我们可以直接点击对应的run方法查看执行细节。

注意,SocketProcessor同样也是xxxEndpoint的内部类





4、调用具体的协议的process方法

目前为止完成的任务,对应的协议(http、ajp)、协议内的数据模型(BIO、NIO、APR)都创建好了。并且我们也接收到了浏览器发送来的数据,我们把对应的任务交给了线程池,线程池调用对应的run方法,在run方法内部,会调用对应的协议的process方法,好在这是http协议的父类方法


1、根据具体的请求协议解析请求



2、再次转发给具体的我们在server.xml中配置的协议的方法

在这个方法中(AbstractHttp11Processor的process方法),你会看到Http请求对浏览器发送过来的请求数据进行了哪些操作处理

通过调试,我们可以直接拿到该请求的所有数据,在该方法中,还与我们的长连接有关,这个未来再进行讲解。



3、解析请求行、请求头、预处理请求、转发请求给servlet…

// 处理请求行
getInputBuffer().parseRequestLine(keptAlive);

// 处理请求头
getInputBuffer().parseHeaders();
    
// 预处理请求
prepareRequest();

// 将请求转发给servlet(重点)
adapter.service(request, response);

// 处理下一个请求
getInputBuffer().nextRequest();




5、调用CoyoteAdapter类的service方法

1、调用对应的管道进行数据过滤

回到我们第二节的流程图,此时数据已经来到了右边区域



2、调用StandardWrapperValve的invoke方法

具体的管道赋值的位置,也和tomcat的启动流程有关,这里请自己去调试具体的赋值位置,我们直接进入最后一个管道的位置。通过代码,我们不难发现,在该类中除了转发请求给servlet,还完成了response对象的参数设置。




6、 filterChain.doFilter(request.getRequest(),response.getResponse())

看名字我们我们就能很清楚的了解到这个方法,和servlet中的过滤器相关的实现有密切的关系。自然我们的请求处理也就包裹在这个里面。传入的参数,这里还使用了一个门面模式,用来屏蔽一些操作。



然后调用internalDoFilter(request,response)方法

  • 调用filter.doFilter(request, response, this)方法,完成过滤器的处理
  • 调用servlet.service(request, response)方法,转发给具体的servlet

代码过多,展示片段




7、转发到Servlet规范中

1、tomcat转发到servlet中

此时tomcat的工作基本完成,tomcat中完成了请求头、请求行的处理、过滤器以及返回对象response等的处理,剩下的工作就交给servlet了



2、根据请求的类型调用对应的方法

我的测试类只重写了doGet方法,所以我们可以直接调试doGet方法



3、在doGet方法中,我们能找到我们的TestResponse类,即请求完成。剩下的就是请求结束后的返回操作

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-02-09 20:33:44  更:2022-02-09 20:34:39 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 12:22:56-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码