几个问题:
Servlet是什么?Servlet容器是什么??Tomcat是什么???Tomcat的组成结构????Tomcat的工作模式?????
Servlet是什么
为了能让Web服务器与Web应用这两个不同的软件系统协作,需要一套标准接口,Servlet就是其中最主要的一个接口。
SUN公司制定了Web应用与Web服务器进行协作的一系列标准Java接口(统称为Java Servlet API),这一系列标准Java接口和规约统称为Servlet规范。
Servlet容器是什么
在Servlet规范中,把能够发布和运行JavaWeb应用的Web服务器称为Servlet容器,他的最主要特称是动态执行JavaWeb应用中的Servlet实现类中的程序代码。
Tomcat是什么
Tomcat是Servlet容器,同时也是轻量级的Web服务器。这是它的两个身份!Apache Server、Microsoft IIS、Apache Tomcat都是Web服务器。Tomcat作为Web服务器时,主要负责实现HTTP传输等工作。
Tomcat作为Servlet容器时,主要负责解析Request,生成ServletRequest、ServletResponse,将其传给相应的Servlet(调用service( )方法),再将Servlet的相应结果返回。
容器结构
服务访问流程,一
服务访问流程,二
Server,代表整个Servlet容器组件,是Tomcat的顶层元素。其中可以包含一到多个Service;
Service,包含一个Engine,以及一到多个Connector;
Connector,代表和客户端程序实际交互的组件,负责接收客户请求,以及向客户返回响应结果;
Engine,处理同一个Service中所有Connector接收到的客户请求;
Host,在Engine中可以包含多个Host,每个Host定义了一个虚拟主机,它可以包含一个到多个Web应用;
Context,一个Host中可以包含多个Context,每个Context代表了运行在虚拟主机上的单个Web应用;
再一次对照server.xml配置文件理解
Service对外提供Web应用服务,而Service核心组件Container的灵魂便是Servlet容器。而真正管理Servlet的是Context容器。Context容器直接管理Servlet在容器中的包装类Wrapper,一个Web应用对应一个Context容器。添加一个Web应用就会创建一个Context容器,并将这个Context容器加入到父容器Host中。
Tomcat 的启动逻辑是基于观察者模式设计的,所有的容器都会继承 Lifecycle 接口,它管理着容器的整个生命周期,所有容器的的修改和状态的改变都会由它去通知已经注册的观察者(Listener)。
Tomcat主要类的启动时序图:
当Context容器初始化状态设为init时,添加在Contex容器的Listener将会被调用。ContextConfig继承了LifecycleListener接口,它被加载到StandardContext容器中。ContextConfig类会负责整个Web应用的配置文件的解析工作。ContextConfig的init方法将会主要完成以下工作:
ContextConfig的init方法完成后,Context容器的会执行startInternal方法,这个方法启动逻辑比较复杂,主要包括如下几个部分:
web应用的初始化
web的初始化是在contextConfig中实现的,应用的初始化主要是对web.xml进行解析,这个文件描述了Web应用的关键信息,也是整个Web应用的入口。Tomcat将web.xml文件解析后,将其中的属性设置到Context容器中,这里包括创建Servlet实例,Filter和Listener。将Servlet包装成Context中的包装类Wrapper。
创建Servlet实例
如果Servlet在web.xml中load-on-startup的配置大于0,那么在Context容器启动时就会被实例化。
Servlet初始化
初始化 Servlet 在 StandardWrapper 的 initServlet 方法中,这个方法就是调用 Servlet 的 init 的方法,同时把包装了 StandardWrapper 对象的 StandardWrapperFacade 作为 ServletConfig 传给 Servlet。
如果该 Servlet 关联的是一个 jsp 文件,那么前面初始化的就是 JspServlet,接下去会模拟一次简单请求,请求调用这个 jsp 文件,以便编译这个 jsp 文件为 class,并初始化这个 class。这样
Servlet 对象就初始化完成了,事实上 Servlet 从被 web.xml 中解析到完成初始化,这个过程非常复杂,中间有很多过程,包括各种容器状态的转化引起的监听事件的触发、各种访问权限的控制和一些不可预料的错误发生的判断行为等等。
Servlet的初始化时序图:
Servlet顶层类关联图:
Servlet如何工作
清楚了Servlet是如何被加载以及被初始化的,以及Servlet的体系结构,现在的问题就是它如何被调用。
当用户从浏览器向服务器发起一个请求,通常会包含如下信息:http://hostname:port/contextpath/servletpath。
hostname和port是用来与服务器建立TCP连接,而后面的URL才是用来选择服务器中那个子容器服务用户的请求。服务器由org.apache.tomcat.util.http.mapper完成映射工作,根据这个URL来达到正确的Servlet容器中,这个类保存了Tomcat的Container容器中的所有子容器的信息,当org.apache.catalina.connector.Request类在进入Container容器之前,mapper将会根据这次请求的hostnane和contextpath将host和context容器设置到Request的mappingData属性中。所以当Request进入Container容器之前,它要访问那个子容器这时就已经确定了。
请求执行过程