1.servlet 是什么?
首先我们进入看看详细信息。找到javax.servlet的包,我们发现其实servlet包里面就是一些接口,找到servlet核心接口,里面定义是这样说的A servlet is a small program that runs within a Web server. Servlets receive and respond to requests from Web clients, usually across HTTP, the HyperText Transfer Protocol.
意思是说servlet是一个运行在web服务器中的小程序,用来接收和响应来自web客户端的请求,使用HTTP进行通信。这里的web服务器就可以有很多了,如常见的tomcat,jetty等。
servlet存在于servlet容器中,servlet容器是运行在tomcat服务器上面。tomcat来管理servlet容器,而每个servlet容器有context容器。
2.servlet容器又是什么?
servlet和servlet容器是彼此依存的,但是又相互发展,servlet,jsp等都是运行在servlet容器内的,而servlet容器又是运行在web服务器的(tomcat,jetty),我们可以看看tomcat容器模型
可以看出tomcat容器分为四个等级真正管理servlet的是context容器,其实我们可以在tomcat的目录中tomcat/config/server.xml中发现这样的标签
<Context docBase="D:\Tomcat 8.0\webapps\TomcatTest" path="/TomcatTest" reloadable="true" source="org.eclipse.jst.j2ee.server:TomcatTest"/>
<Context docBase="D:\Tomcat 8.0\webapps\GitTest" path="/GitTest" reloadable="true" source="org.eclipse.jst.j2ee.server:GitTest"/>
可以看出一个servlet容器可以有多个context,也就意味可以有多个应用,每个应用又互不干扰。
3.Servlet容器的启动过程
我们可以看看tomcat源码中有这样一个,可以用来手动启动一个tomcat实例,并且配置相关信息,然后添加webapp应用,这一系列工作相当复杂,当好在我们可以不用这么麻烦,直接在ide既可以启动tomcat,tomcat容器就会按照流程对web应用进行初始化等一系列工作。
4.Web应用的初始化
web应用的初始化工作室在ContextConfig的configureStart返回中实现的,主要用来解析web.xml.也就是web程序的入口,tomcat首先会找到globalWebXml,存在于cof.web.xml中,接下来会寻找hostWebXml,然后寻找应用的配置文件web.xml,通过解析保存在WebXml对象中,最后tomcat会将WebXml对象中的属性设置到Context容器中,这里就包括了Servlet对象、filter过滤器、监听器等,但是最后返回的并不是servlet对象,而是经过包装后的ServletWrapper对象。这也就解释了为什么tomcat容器模型有四层。
context是什么:
一、context可以理解成一个聚宝盆,在当前环境下你能拿到的参数都可以从context出发去拿,而不仅仅是放URL的.从里面可以拿到request,session,response.......,可以说只要你拿到了context就可以访问任何你有权限访问的东西二、context就是“容器”,放的就是应用程序的所有资源,要用时候就访问它,所以context里面的东西,在同一个应用程序里面是全局的。三、是一个包含各种context的设置的对象例如:pageContext就包含了该页面的各种设置。可以通过他得到该页面所在服务器路径等等。Context 用于在 Request 操作中指定上下文对象的对象,上下文字符串在与请求调用一起被发送之前,必须在该指定的上下文对象中进行解析。Context 对象包含 NamedValue 对象形式的属性列表。这些属性表示关于客户端、环境或请求情形的信息,它们通常是一些可能不方便作为参数传递的属性。
5.创建servlet实例
当Context容器启动是,它会读取conf/web.xml下的内容,这个是所有web应用程序的根,里面定义了很多默认配置项,其实当我们的项目只有一个index.jsp没有任何的servlet的时候,运行起来可以直接访问index.jsp,这是因为在默认配置项中有这样一句话
- <!-- ================== Built In Servlet Definitions ==================== -->
- <servlet>
- <servlet-name>default</servlet-name>
- <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
- <init-param>
- <param-name>debug</param-name>
- <param-value>0</param-value>
- </init-param>
- <init-param>
- <param-name>listings</param-name>
- <param-value>true</param-value>
- </init-param>
- <load-on-startup>1</load-on-startup>
- </servlet>
- <servlet>
- <servlet-name>jsp</servlet-name>
- <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
- <init-param>
- <param-name>fork</param-name>
- <param-value>false</param-value>
- </init-param>
- <init-param>
- <param-name>xpoweredBy</param-name>
- <param-value>false</param-value>
- </init-param>
- <load-on-startup>3</load-on-startup>
- </servlet>
这其中有两个类,DefaultServlet和JspServlet,他们的载入顺序分别为1和3,意味着当tomcat启动的时候他们就启动了,其实这两个类都继承了httpservlet,而创建servlet实例是由Wrapper.loadServlet开始的,首先它会获得servletClass,然后把它交给InstanceManager去创建基于servletClass.class的对象,如果这个对象配置了jsp-file的话,那么这个servletClass对象就是在上面的JspServlet。
6.servlet的初始化
在StandardWrapper中有个initServlet方法,它就是来调用servlet的init方法,同时把包装了StandardWrapper对象的StandardWrappperFacade作为ServletConfig对象传给servlet。如果该servlet关联的是jsp文件,那么初始化的就是jspServlet,接下来就会模拟以此请求,调用这个jsp,并编译它,然后初始化这个类。
有关servlet初始化工作非常复杂,中间有非常多的过程,我们可以仔细查看源码文档。
7.Request和Response对象剖析
HttpServletRequest和HttpServletRequest呢?解释如下:
当tomcat接收到一个请求时候,会创建org.apache.coyote.Request和org.apache.coyote.Response两个类,用来描述请求和相应的信息,经过简单处理后会分发给后续线程处理,所以他们的对象很小,容易被jvm回收,后续线程会创建org.apache.catalina.connector.Request和org.apache.catalina.connector.Response对象,这两个对象一直存在于整个servlet容器,直到传给目标Servlet,但是目标接收的类型却是RequestFacade和ResponseFacade,这两个叫做门面类,相当于两个童子,当书信要来的时候是这两个童子负责处理,目的是为了封装数据。
8.Servlet是如何处理请求的