servlet这个东西让许多刚入行的攻城狮或者有一定年限的工程师都望而生畏,原因就是在Spring MVC架构下没有太多人还会去编写servlet,甚至没有人会抽时间研究servlet的实现原理及种种性质。但是这项技术原理是所有web人员都应该掌握的。下面我们开始正文。
学习servlet之前首先了解tomcat容器的基本组成:
container:大盒子 engine:引擎容器 host:主机容器 servlet容器:管理很多context容器 context:对应的是一个web项目 |
Container 酒店 | 接口org.apache.catalina.Container是对容器的抽象,定义了许多方法 |
Engine 通信设备 | 表示整个Catalina的servlet引擎,其下面拥有多个虚拟主机,它的责任就是将用户请求分配给一个虚拟上机处理 |
Host 楼层 | tomcat中一个Host代表一个虚拟主机,一个虚拟主机上可以有多个应用。 |
Servlet容器 客房 | 一个Context就代表一个Servlet容器,所以这是一个容器的集合 |
Context 电视 | 对应Context组件,该层代表某个虚拟主机上的实际目录或一个WAR,即单个Web应用程序。 它运行在特定的虚拟主机中,使用最为频繁。 一个Host层包含多个Context层,每一个Context都有唯一的路径, Host层接到请求后,根据用户请求的URL,将请求定位到Context层。 真正的Servlet运行时容器 |
Warpper 电视信号转换器 | 一个经过包装的servlet小程序,一个web应用程序可能有多个Warpper |
Tomcat添加一个Web项目的工作流程
1、添加一个Web应用时会创建一个StandardContext容器:Context ctx = new StandardContext();
2、为这个StandardContext实例添加tomcat的项目浏览器访问路径,项目磁盘真实路径等参数;
3、在进行StandardContext配置的时候初始化一个ContextConfig配置类,他负责整个web项目配置解析工作;
4、将ContextConfig添加到StandardContext中;
5、将StandardContext实例添加到Host容器中;
6、调用Tomcat的start方法启动Tomcat;
StandardContext容器的启动过程-ContextConfig执行init方法
1、ContextConfig继承了LifecycleListener接口,当context容器初始化状态为init,调用监听。
2、ContextConfig创建解析XML的contextDigester对象
3、读取并解析context.xml配置文件
4、读取并解析Host.xml配置文件
5、读取并解析默认配置文件
6、设置context的DocBase:docBase:指定Web应用的文件路径,可以给定绝对路径,也可以给定相对于<Host>的appBase属性的相对路径
StandardContext容器的启动过程-Context执行startInternal方法
1、创建读取资源文件对象
2、创建classloader对象
3、设置应用的工作目录
4、启动相关的辅助类
5、修改启动状态,通知感兴趣的观察者
6、子容器的初始化
7、获取ServletContext并设置必要的参数
8、初始化 load on startup的servlet
web应用初始化工作步骤
Web应用初始化工作实在ContextConfig中的configureStart方法实现的。
1、 首先寻找golbalWebXml
接下来会找hostWebXml
最后会找webxml
2、寻找完XML文件之后,XML的内容将会设置到Context容器中
3、创建Servlet对象,并包装秤StandardWrapper供Context容器使用。context.addChild(wrapper);
Servlet对象如何创建及初始化
<load-on-startup>1</load-on-startup> //如果load-on-startup>0 那么context容器启动的时候就会自动实例化Servlet。
tomcat启动的时候有两个Servlet会被启动,那就是DefaultServlet和JspServlet
创建Servlet实例的方法是从Wrapper.loadServlet方法开始,获取一个servletClass,然后交给InstanceManager去创建一个基于servletClass.class的对象。
初始化Servlet实例是从Wrapper的initServlet方法中,这个方法很简单就是调用Servlet的init方法。与此同时Servlet还会接收含有StandardWrapper门面类的ServletConfig
servlet的继承关系
Servlet接口<-----GenericServlet<------HttpServlet<------自定义Servlet
Servlet接口 | 三个方法 init()、service()、destroy() |
GenericServlet |
实现了Servlet接口 1.init方法 妥善的保存config对象并实现getServletInfo,getServletConfig, 2.增加一个空参init方法,供开发人员初始化,为了防止开发人员重写 原生init方法 3.service方法空实现=> 声明成抽象(强制开发人员实现该方法) 4.destory方法空实现 5.实现了servletConfig接口. 接口中的方法直接调用config实现类实现. |
HttpServlet | 实现了http协议的servlet 1.service函数中强转参数 |
自定义Servle | 需要重写doGet doPost方法 |
编写servlet的三个步骤
- 1、编写一个类,继承HTTPServlet
- 2、实现重写doGet()、doPost()方法
- 3、在web.xml中注册
servlet执行流程
用户点击超链接,发送Get请求
tomcat会寻找与注册在web.xml中地址相同的servlet
找到对应的servlet后会执行类中的doget方法。
servlet生命周期
第一步 Tomcat检查是否存在Servlet实例对象、如果存在直接第四步。
第二步 装载Servlet类并创建实例
装载方式一:Servlet容器启动时,自动装载Web.xml中注册的Servlet,根据loadonstartup判断优先级
装载方式二:请求来时,会装载Servlet
装载方式三:Servlet类被更新,重新装载Servlet
第三步 调用init方法
第四步 调用service方法,判断执行doget或者dopost方法
第五步 服务器结束或停止服务,调用destroy方法销毁