背景
Tomcat作为JavaWeb领域的Web容器,大多数Java应用的Web容器都使用了Tomcat,为了对平时开发的Web系统有更深入的理解,出于好奇心对我们的Web系统是如何跑在Tomcat上的,前段时间仔细研究整理了Tomcat的源码以及之前看过的技术点进行分享,大家都知道Servlet规范是Java领域中为服务端编程制定的规范,对于我们开发者只是关注了Servlet规范中提供的编程组件(ServletContextListener,Filter,Servlet等),但是规范中还有一些我们经常使用的接口(ServletContext,ServletRequest,ServletResponse,FilterChain)等都是由Tomcat去实现的,并且我们开发者实现的编程组件只是被Tomcat去回调而已,所以看Tomcat源码有助于我们更好的理解Servlet规范及系统如何在容器中运行的(一些开源的MVC框架Struts2,Webx,SpringMVC本质上就是这),整理相关学习资料,以便日后回顾(Tomcat版本:10.0.10)
Tomcat和Catalina是什么关系
Tomcat的前身为Catalina,Catalina是一个轻量级的Servlet容器
Tomcat的前身为Catalina,Catalina又是一个轻量级的Servlet容器。Tomcat从4.x开始除了作为支持Servlet容器外,额外加了很多的功能,不如:jsp、el、naming等等,所以Tomcat不仅仅是Catalina。
什么是Servlet
所谓Servlet,其实就是Sun为了让Java能实现动态可交互的网页,从而进入Web编程领域而制定的一套标准
一个Servlet主要做下面三件事情:
- 创建并填充Request对象,包括:URL、参数、method、请求头信息、请求体信息等
- 创建Response对象
- 执行业务逻辑,将结果通过Response的输出流出到客户端
Servlet没有main方法,所以:如果要执行,则需要在一个容器里面才能执行,这个容器就是为了支持Servlet的功能而存在,Tomcat其实就是一个Servlet容器的实现。
Tomcat整体架构
从组件角度看
-
Server: 表示服务器,它提供了一种优雅的方式来启动和停止整个系统,不必单独启停连接器和容器;它是Tomcat构成的顶级构成元素,所有一切均包含在Server中;
-
Service: 表示服务,Server可以运行多个服务。Server的实现类StandardServer可以包含一个到多个Services
-
Container: 表示容器,可以看做Servlet容器;引擎(Engine)、主机(Host)、上下文(Context)和Wraper均继承自Container接口,所以它们都是容器。
-
Engine -- 引擎
-
Host -- 主机
-
Context -- 上下文
-
Wrapper -- 包装器
-
Connector : 表示连接器, 它将Service和Container连接起来,首先它需要注册到一个Service,它的作用就是把来自客户端的请求转发到Container(容器),这就是它为什么称作连接器, 它支持的协议如下:
-
支持AJP协议
-
支持Http协议
-
支持Https协议
-
Service内部还有各种支撑组件,下面简单罗列一下这些组件
-
Manager -- 管理器,用于管理会话Session
-
Logger -- 日志器,用于管理日志
-
Loader -- 加载器,和类加载有关,只会开放给Context所使用
-
Pipeline -- 管道组件,配合Valve实现过滤器功能
-
Valve -- 阀门组件,配合Pipeline实现过滤器功能
-
Realm -- 认证授权组件
从一个完整请求的角度来看
来自客户的请求为:http://localhost:8080/test/index.jsp请求被发送到本机端口8080,被在那里监听的Coyote HTTP/1.1 Connector,然后
- Connector把该请求交给它所在的Service的Engine来处理,并等待Engine的回应
- Engine获得请求localhost:8080/test/index.jsp,匹配它所在虚拟机主机Host
- localhost Host获得请求/test/index.jsp,匹配它所拥有虚拟主机Context
- Context匹配URL PARRTERN为*.jsp的servlet,对应于JspServlet类,构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet或doPost方法
- Context把HttpServletResponse对象返回给Engine
- Engine把HttpServletResponse对象返回给Connector
- Connector把HttpServletResponse对象返回给浏览器
从源码的设计角度看
- **Jsper模块:**这个模块负责jsp页面的解析、jsp属性的验证,同时负责jsp页面动态转换为java代码并编译成class文件。在源码中,org.apache.jasper的源码都属于这个子模块
- Servlet和Jsp模块: 这个子模块的源代码属于javax.servlet包及其子包,如我们非常熟悉的javax.servlet.Servlet接口、javax.servet.http.HttpServlet类及javax.servlet.jsp.HttpJspPage就位于这个子模块中;
- Catalina模块: 这个模块是需要阅读和学习的重点,包含了所有org.apache.catalina开头的源码,该模块规范了Tomcat的总体架构,定义了Server、Service、Host、Connector、Context、Session以及Cluster等关键组件的实现,同时也规范了Catalina的启动及停止事件的执行流程。
- **Connector模块:**上面三个子模块实现的是tomcat应用服务器,该模块是Web服务的实现,它接收用户的请求,并把用户请求包装成标准的Http请求(包含协议名称、请求头Head,请求方法Get 或Post).
- **Resource 模块:**这个模块包括一些资源文件,如Server.xml及Web.xml配置文件。这个子模块不包含java源码,但是是Tomcat编译运行所必须的
展望
后面将从源码视角对Tomcat如何启动初始化和如何接收请求具体展开分析讲解