知识小罐头05(tomcat8请求源码分析 上)
这一篇我们不看源码,就大概理一下Tomcat内部组成部分!前面花费了两篇博客的篇幅来说说了一般的maven web项目并部署到tomcat运行,其实都是为这篇做铺垫的!
其实我下载了tomcat7,tomcat8,tomcat9这三个版本的,但是tomcat9有个问题,就是启动的时候黑窗口出现中文乱码,试了很多方法都没用,改了tomcat9配置文件,改了cmd的编码utf8,去了注册表也改了tomcat的65001的那个,虽然都没什么用就对了,后面我看看能不能解决一下这个问题!
我们还是以tomcat7为例,看看其中原理!
注意:我说的内容可能会删减很多不怎么重要的内容,我们只关注核心原理,把核心的原理搞定了,再去研究那些细枝末节的东西会事半功倍!
ok,进入正题,首先我们从Tomcat的目录出发;
1.Tomcat基本结构
我们重点先看看conf文件夹,tomcat最主要的原理就在这里
打开conf文件夹可以看到这么东西,我们只看关键的server.xml,这个配置文件搞清楚了,tomcat基本的组成部分也就ok了!
打开server.xml,我删除了所有的注释以及感觉不怎么重要的东西!第一部分和第二部分就组成了tomcat的骨架
第一部分是一个连接器,用于接受我们在浏览器发送的localhost:8080/xxx这个请求
第二部分是处理请求的地方,将连接器接收的请求再放到这里处理;通常很多人就把这部分叫做Container(就是容器的意思),其实这Container是一个笼统的称呼,为了方便我们理解才这样说的!实际上配置文件中哪有Container啊!(注:其实Container是一个接口,这里Engine,Host,Context等都实现了这个接口,所以才会把这整块地方叫做Container)
所以,总的来说,tomcat分为两部分,一个接收请求的Connector和处理请求的Container!假如你还要说的简单一点,Tomcat其实就是一个Container,而这个Container里面就是很多的Servlet,将我们的请求交给这些servlet处理然后返回,所以Tomcat本质上就是一个servlet容器!
Connector和Container的关系就好像一个公司的前台和老板,外面的人想要跟老板说点什么肯定要经过前台,前台看你是个正常人才会帮你通知一下老板,不然五花八门的几十人都一下子跑到老板的办公室坐着,emmm...后果就不用多说了吧!
下面我们就来仔细研究研究Connector和Container,只要把这两个研究清楚了,Tomcat整个结构就清晰了!
2. Connector内部结构
其实从上面的Connector标签可以看的出来一点端倪;这个连接器可以有多个,常用的就是处理HTTP协议和AJP协议的,听说这个AJP的运用场景是:当Tomcat服务器和其他的HTTP服务器(例如Apache)集成一起使用的时候,这个连接器就会生效;这个以后用到再说,我们现在只关注HTTP的这个连接器
只看Http的连接器:
在说Connector内部结构之前,肯定能够想象得到Connector内部到底干了什么事!首先肯定是要接收整个HTTP请求,HTTP请求里面就是一些请求头,请求空行,请求体这些东西组成嘛!想办法把这些东西解析一下,取出我们需要的一些信息,什么请求路径啊,ip啊,端口啊什么的等等,然后根据这些信息包装成Request,传到Container进行进一步处理;
下面用一个图来说明这个步骤:
根据上图,可以看到Connector内部有一个ProtocalHandler(协议处理器,种类有Http11Protocol用于普通的socket连接;Http11NioProtocol用于NioSocket连接;不了解的也不要深究,后面也许我会说一说bio,nio,aio的一些东西,看情况)
而这个协议处理器内部大概分为三个部分,Endpoint,Processor,Adapter(图上Adapter可能拼错了,我也是随便找的图,没仔细看)。
我们分析一下这三个东西是干什么的,那么这个Connector的大概逻辑就出来了!
Endpoint:看到其中的Acceptor就能知道,这个肯定是用来处理socket连接的,并且要实现TCP/IP协议;Acceptor用来监听请求,然后Handler(处理器)内部调用processor来处理接收的socket请求;不过这个东西比较底层了,有兴趣的小伙伴可以继续深究,这里就说到这里;
Processor:上一步说到Handler内部调用这个Processor去处理socket请求,怎么处理呢?其实就是将请求的一些数据拿出来,进行包装成一个普通的Request对象;而且这个Processor要实现HTTP协议;
Adaptor:上一步是包装成一个普通的Request对象,但是我们是做web应用,Request对象不是我们需要的,要继续包装成一个HttpServletRequest对象,传到Container中就可以使用或者看情况进一步处理;
3.Container内部结构
前面分析了一下Connector的内部就够,其实就是根据socket连接接收请求,实现xxx协议,将请求中的数据最后封装成一个HttpServletRequest对象,传到Container;
但是传到Container中又经过了什么处理呢?
我们可以继续想象一下内部干了什么事,比如浏览器请求这个url:localhost:8080/ssm/hello,包含了主机ip,端口,项目名,uri,而且这些数据最后会被封装到HttpServletRequest中,在Container中会拿出这些数据,进行查找具体的主机,哪个项目,项目中的servlet映射路径;无非是做这些事,不要想的太复杂
从server中的标签来看,能看到几个标签Engine,Host,Context,其实应该还有一个Wrapper,这个Wrapper是用来包装真正的servlet的,便于扩展,后面会说到的;
上图就是一个Container,一层包装一层,Engine>>>Host>>>Context>>>Wrapper;其中一个Container中的Engine只能配置一个,Host可以配置多个,Context可以配置多个;
我们可以看作:一个最大的容器Container,里面有个小一号的Engine容器,里面还有一个更小一号的Host容器,里面还有一个还小号的Context容器,里面还有一个最小号的Wrapper,而这个Wrapper容器就是最小的容器了,这个容器有很多个,一个Wrapper其实就是一个servlet,为了扩展方便才封装成Wrapper!
下面说说这些东西有什么作用;
Engine:看到名字应该就知道这是一个引擎,这是一个完整的servlet引擎,内部还包括了一些东西
Host:就是主机名,例如我们常见的localhost,由于可以配置多个,所以一个Tomcat实例可以配置多域名,也是为了灵活使用吧!
Context:很多人都喜欢把这个叫做应用上下文,其实就是指的你的web应用;你想啊,你的web应用在tomcat运行的时候,是以Context这个形式表现出来的,你就可以把这个Context当作你的应用本身,比较类似的应该是:类加载到内存中是以Class对象存在,应该差不多的道理吧!
Wrapper:可以有很多的Wrapper容器,一个Wrapper里面就是一个Servlet,用几行粗略代码表示如下,可以很清楚的看到Wrapper和servlet之间的关系
再说一下Host和Context的关系,请看下图Tomcat8目录和webapps内部,这就应该说的很清楚了;
3.研究一下Container的内部运行过程
前面分析了Container中的各个组成部分,无非是容器一层套一层,HttpServletRequest请求穿过一层一层,最后就到达servlet中执行service方法,然后处理,再返回;
就好像中学时候学的生物细胞结构一样,营养物质首先要穿过血管壁,再是细胞壁,细胞膜等等,就是一层一层的穿过,而且在穿过的途中会碰到很多关卡,会对这个营养物质做一些处理;(嘿嘿,生物的知识我也不知道说的对不对,瞎扯一下!)
其实在这里HttpServletRequest就如同一个营养物质,每经过一个容器都会被处理一下,在Tomcat中就有这么一个叫做Pipeline-Value机制(就是管道-阀门机制)来处理;
阀门其实类似一个过滤器Filter;而且可以把每一层容器看作是一个管道,管道中有一个一个的阀门,最重要的就是每条管道的最后一个阀门(叫做基础阀,英语是BaseValue),会调用下一条管道的第一个阀门,一直到Wrapper的基础阀中会创建一个拦截器链FilterChain,依次调用所以拦截器的doFilter方法以及Servlet的service方法,再返回!在这个过程中,HttpServletRequest每经过一个阀门,都会被处理一下(其中假如出现异常,那么就会取到异常信息包装成一个xxxResponse返回给客户端!)
可以想象最后形状应该是一个奇奇怪怪的形状;于是我找了一幅图来看看
4.总结:
这一节我们用图形来看了一下tomcat的基本结构和大概的运行过程,其实Tomcat底层就是依赖socket来获得请求,然后进行封装,把请求放进一个容器中,经过一连串的管道-----阀门机制进行处理,最后到Wrapper中会创建一个拦截器链,执行每一个拦截器的doFilter方法,然后再执行servlet的service方法,然后将结果返回客户端;
用一幅图来看看这整个过程:
知识小罐头05(tomcat8请求源码分析 上)的更多相关文章
- 知识小罐头07(tomcat8请求源码分析 下)
感觉最近想偷懒了,哎,强迫自己也要写点东西,偷懒可是会上瘾的,嘿嘿!一有写博客的想法要赶紧行动起来,养成良好的习惯. ok,继续上一篇所说的一些东西,上一篇说到Connector包装了那两个对象,最后 ...
- 知识小罐头06(tomcat8请求源码分析 中)
更正上一篇一个小错误,Connector中首先是将socket请求过来的信息封装成一个普通的Request对象(上一篇我写成HttpRequest对象,失误失误,根本就木有HttpRequest这样的 ...
- 知识小罐头08(tomcat8启动源码分析 上)
前面好几篇都说的是一个请求是怎么到servlet中的service方法的,这一篇我们来看看Tomcat8是怎么启动并且初始化其中的组件的? 相信看了前面几篇的小伙伴应该对Tomcat中的各个组件不陌生 ...
- Tomcat处理HTTP请求源码分析(下)
转载:http://www.infoq.com/cn/articles/zh-tomcat-http-request-2 很多开源应用服务器都是集成tomcat作为web container的,而且对 ...
- Tomcat处理HTTP请求源码分析(上)
Tomcat处理HTTP请求源码分析(上) 作者 张华 发布于 2011年12月8日 | 8 讨论 分享到: 微博 微信 Facebook Twitter 有道云笔记 邮件分享 稍后阅读 我的阅读清单 ...
- # Volley源码解析(二) 没有缓存的情况下直接走网络请求源码分析#
Volley源码解析(二) 没有缓存的情况下直接走网络请求源码分析 Volley源码一共40多个类和接口.除去一些工具类的实现,核心代码只有20多个类.所以相对来说分析起来没有那么吃力.但是要想分析透 ...
- Tomcat处理HTTP请求源码分析(上)(转)
转载自:http://www.infoq.com/cn/articles/zh-tomcat-http-request-1 很多开源应用服务器都是集成tomcat作为web container的,而且 ...
- Okhttp同步请求源码分析
进阶android,OKhttp源码分析——同步请求的源码分析 OKhttp是我们经常用到的框架,作为开发者们,我们不单单要学会灵活使用,还要知道他的源码是如何设计的. 今天我们来分析一下OKhttp ...
- SpringBoot事件监听机制源码分析(上) SpringBoot源码(九)
SpringBoot中文注释项目Github地址: https://github.com/yuanmabiji/spring-boot-2.1.0.RELEASE 本篇接 SpringApplicat ...
随机推荐
- 【原创】分布式之redis复习精讲
引言 为什么写这篇文章? 博主的<分布式之消息队列复习精讲>得到了大家的好评,内心诚惶诚恐,想着再出一篇关于复习精讲的文章.但是还是要说明一下,复习精讲的文章偏面试准备,真正在开发过程中, ...
- Discuz3.4-SSRF-从触发点到构造payload
目录 SSRF逆向分析 0x00 前言 0x01 收集情报 0x02 尝试逆向找到触发点 0x03 尝试构造payload 0x04 总结 SSRF逆向分析 0x00 前言 之前有复现过一些漏洞,但是 ...
- 华为手机无法使用USB调试的解决方案
在Android开发中,一直在使用华为的荣耀8进行调试,但是突然某一次,发现USB调试无法使用了,且在其他的电脑上进行调试也不行. 后来经过查资料,总算解决了此问题,在这里进行一下解决方案的记录. 需 ...
- 跟我一起学opencv 第四课之图像的基本操作
1.图像是由像素组成的,所以修改了像素就可以实现图像的改变. 2先看灰度图像(单通道): *****2.获取灰度图像的像素值使用: int gray = gray_src.at<uchar&g ...
- Java语言编程 - Java第一个程序HelloWorld
3.1 新建Java文件 首先新建一个文件夹,用于存放写的Java程序,例如我存放Java程序的位置为” D:\Files\code\java”. 在该文件夹中,右键新建一个文本文档 将文件名重命名为 ...
- asp.net core系列 46 Identity介绍
一. Identity 介绍 ASP.NET Core Identity是一个会员系统,可为ASP.NET Core应用程序添加登录功能.可以使用SQL Server数据库配置身份以存储用户名,密码和 ...
- 理解 KMP 算法
KMP(The Knuth-Morris-Pratt Algorithm)算法用于字符串匹配,从字符串中找出给定的子字符串.但它并不是很好理解和掌握.而理解它概念中的部分匹配表,是理解 KMP 算法的 ...
- Java进阶篇 设计模式之十四 ----- 总结篇
前言 本篇是讲述之前学习设计模式的一个总结篇,其目的是为了对这些设计模式的进行一个提炼总结,能够通过查看看此篇就可以理解一些设计模式的核心思想. 设计模式简介 什么是设计模式 设计模式是一套被反复使用 ...
- Asp.NETCore轻松学系列阅读指引目录
前言 耗时两个多月,坚持写这个入门系列文章,就是想给后来者更好更快的上手体验,这个系列可以说是从入门到进阶,适合没有 .NETCore 编程经验到小白同学,也适合从 .NET Framework 迁移 ...
- 结合JDK源码看设计模式——原型模式
定义: 指原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象.不需要知道任何创建的细节,不调用构造函数适用场景: 类初始化的时候消耗较多资源 new产生的对象需要非常繁琐的过程 构造函数比较 ...