9.1 从Servlet容器说起

Servlet和Servlet容器的关系,就像枪和子弹的关系,彼此依存又互相独立发展,这一切都是为了适应工业化生产。从技术角度来说,是为了解耦,通过标准化接口来互相协作。

所以说,接口是连接Servlet和Servlet容器的关键。那么我们就从它们的接口说起。

以Tomcat为例:

下图为Tomcat的容器等级:

Wrapper为Servlet在容器中的包装类。Context直接管理包装类Wrapper.

上图可以看出,Tomcat容器分为4个等级(Container容器,Engine,Host,Context),真正管理Servlet的容器是Context容器。一个Context对应一个web工程。

Servlet容器的启动过程

选择的是Tomcat7自带的examples web工程。(书中代码)

创建了一个Tomcat实例并新增了一个web应用,然后启动Tomcat并调用其中一个HelloWorldExample Servlet。

Tomcat tomcat = getTomcatInstance();
File appDir = new File(getBuilderDirectory(),"webapps/examples");
tomcat.addWebapp(null,"/examples",appDir.getAbsolutePath());
tomcate.start();
ByteChunk res = getUrl("http://localhost:"+getPort()+
"/examples/servlets/servlet/HelloWorldExample");
assertTrue(res.toString().indexOf("<h1>Hello </h1>")>0);

关于以上代码中的addWebapp{

  创建一个StandardContext容器,并且给这个Context容器设置必要的参数(url,path)。url和path分别代表这个应用在Tomcat中的访问路径和这个应用的实际物理路径。

  创建ContextConfig,用Context来接收(多态),这个类会负责整个web应用配置的解析工作。

  然后将ContextConfig添加到StandardContext的LifecycleListener中。

  配置完后将Context容器加到父容器Host中。

}

接下来调用Tomcat的start方法启动Tomcat。

Tomcat的启动逻辑是基于观察者模式设计的。所有的容器都会继承LifecycleListener接口。它管理着容器的整个生命周期。所有容器的修改和状态的改变都会由它去通知已经注册的观察者(listener)

ContextConfig类的init方法主要完成以下工作:

  创建用于解析XML配置文件的contextDigester对象。

  读取默认的context.xml配置文件,如果存在则解析它。

  读取默认的Host的文件,如果存在则解析它

  读取默认的Context自身的配置文件,如果存在则解析它

  设置Context的DocBase。

ContextConfig的init方法完成以后,Context容器就会执行startInternal方法,主要包括如下:

  创建读取资源文件的对象

  创建ClassLoader对象

  设置应用的工作目录

  启动相关的辅助类,如logger,realm,resources等

  修改启动状态,通知感兴趣的观察者

  子容器的初始化

  获取ServletContext并设置必要的参数

  初始化"load on startup"的Servlet

web应用的初始化工作:

web应用的初始化工作是在ContextConfig的configureStart方法中实现的,应用的初始化主要是解析web.xml文件。

Tomcat →globalWebXml→hostWebXml→examples/WEB-INF/web.xml。  (web.xml文件的各个配置项将会被解析成相应的属性保存在WebXml对象中)

如果当前应用支持servlet 3.0,还会完成额外9项工作。

接下来将WebXml对象中的属性设置到Context容器中。这段代码在WebXml的configureContext方法中。(这段代码将Servlet包装成了StandardWrapper并添加在了Context容器中)

把Servlet包装成StanderdWrapper的原因:

  这里的StanderWrapper是Tomcat容器的一部分,它具有容器的特征,而Servlet作为一个独立的Web开发标准,不应该强耦合在Tomcat中。

9.2 创建Servlet实例

如果Servlet的load-on-startup配置项大于0,那么在Context容器启动时就会被实例化。

conf/web.xml中定义了两个Servlet,分别是DefaultServlet和JspServlet,他们的load-on-startup分别是1和3。当tomcat启动时,他们两个都会启动。

创建Servlet实例的方法是从Wrapper.loadServlet开始的

Wrapper.loadServlet (获取servletClass)→交给InstanceManager→创建一个基于servletClass.class的对象。

初始化Servlet

StandardWrapper的initServlet方法{

  调用Servlet的init方法

  将StanderdWrapperFacade作为ServletConfig传给Servlet。

}

9.3 Servlet体系结构

与Servlet主动关联的三个类:ServletConfig     ServletRequest      ServletResponse

ServletConfig在Servlet初始化的时候就传给Servlet了。

  ServletConfig里面的方法可以获取一些Servlet的配置属性。

后两个是在请求达到时调用Servlet传递过来的。

  Servlet的运行模式是一个典型的握手型交互模式。就是说,两个模块为了交换数据通常都会准备一个交易场景,这个场景一直跟随这个交易过程直到这个交易完成为止。交易场景的初始化是根据这次交易对象指定的参数来定制的。

  交易场景就由ServletContext来描述,定制的参数集合就由ServletConfig来描述。

  ServletRequest和ServletResponse通常作为运输工具来传递交互结果。

init时,StanderdWrapperFacade作为ServletConfig传给Servlet,那么ServletConfig到底是个什么对象呢?

  StanderdWrapper和StandardWrapperFacade都实现了ServletConfig接口。而StandardWrapperFacade是StandardWrapper的门面类。这个类传给Servlet的作用是保证从StandardwWrapper中拿到的ServlertConfig所规定的的数据,而又不把ServletConfig不关心的数据暴露给Servlet。

  同理:在Servlet中拿到的ServletContext的实际对象也是ApplicationContextFacade对象。作用和上面相同。

  同理:在Servlet中拿到的Request和Response类也是门面类RequestFacade和ResponseFacade。(这里多了几步操作)

  这里使用的都是门面设计模式。

9.4 Servlet如何工作

  用户从浏览器向服务器发起的一个请求通常会包含如下信息:http://hostname:port/contextpath/servletpath   ,hostname和port用来与服务器建立TCP连接。后面的URL才用来选择在服务器中哪个子容器服务用户的请求。那么服务器是如何根据这个URL来到达正确的Servlet容器呢?

  在Tomcat 7 中很容易解决,这种映射专门交给了一个叫Mapper的类来完成。这个类保存了Tomcat类的Container容器中的所有子容器信息。在Request类进入Container容器之前,Mapper将会根据这次请求的hostname和contextpath将Host和Context容器设置到Request 的MappingData属性中。所以,在Request进入Container容器之前,对于它要访问哪个子容器就已经确定了。

  那么,Mapper中是怎么拥有容器的完整关系的?

  MapperListener的init()方法{

    将MapperListener类作为一个监听者加到整个Container容器的每个子容器中。这样只要任何一个容器发生变化,MapperListener都会被通知到。

    同时,MapperListener的Mapper属性也会被更改。

  }

Request请求是如何到达最终的Wrapper容器的呢(查资料 结合书  再来填坑)

  接下来,该执行Servlet的service方法了。

  通常情况下,我们自己定义的Servlet并不直接去实现Servlet接口,而是去继承更简单的HttpServlet类或者GenericServlet类,我们可以有选择的覆盖相应的方法完成要实现的工作。

  现在的web应用很少直接将交互的全部页面用Servlet实现,而是采用更加高效的MVC框架来实现。这些MVC框架的基本原理是将所有的请求都映射到一个Servlet,然后去实现service方法。这个方法也就是MVC框架的入口。这个博客讲的很好

  当Servlet从Servlet容器中移除时,也就表明Servlet的生命周期结束了。destory()方法开始被调用。

9.5 Servlet中的Listener

  Listener是基于观察者模式设计的

  能够方便地从另一个纵向维度控制程序和数据。目前Servlet提供了6种两类事件的观察者接口。

事实上,这6个Listener都继承了EventListener接口。

注意:ServletContextListener在容器启动后就不能再添加新的了,因为它所监听的事件已经不会再出现了。

9.6 Filter如何工作

使用:通过<filter>和<filter-mapping>组合使用Filter。

Filter除了提供request和response对象外,还提供了一个FilterChain对象。

而Filter的实现类,是用户自定义的。只需要实现Filter接口中定义的三个接口就行。

  init(FilterConfig):初始化接口。与Servlet中的init(ServletConfig)基本一样。可以获取到ServletContext对象,还能获取到在<filter>下配置的<init-param>参数值

  doFilter(ServletRequest,ServletResponse,FilterChain)每个用户请求进来的时都会被调用,在service方法之前被调用。FilterChain代表当前的整个请求链。这里是责任链设计模式。

  destory:Filter容器被销毁时调用。当web容器调用这个方法之后,还会再调用一次doFilter方法。

FilterChain的实现类ApplicationFilterChain里面有一个filters数组,保存了到达最终Servlet对象的所有Filter对象,每执行一个Filter对象,数组当前的计数都会加1。计数等于数组长度时,Servlet执行。

9.7 Servlet中的url-pattern

  Servlet和Filter在web.xml中都有<url-pattern>这个配置项。

  Servlet是通过Mapper类完成的,它在一个请求被创建时就已经匹配了。

  Filter的<url-pattern>是在创建ApplicationFilterChain对象时进行的。它会把所有的定义的Filter的url-pattern与当前的url匹配。匹配成功就将这个Filter保存到filters数组里,然后在FilterChain中调用。

  <url-pattern>的解析规则:精确匹配,路径匹配(前缀匹配),后缀匹配。

  web.xml加载时,会首先检查<url-pattern>配置是否符合规则。在StandardContext的validateURLPattern方法中检查的。不成功会报错。

  

  Servlet的匹配规则:精确匹配>最长路径匹配>后缀匹配。 注:一次请求只会成功匹配到一个Servlet。

  Filter的匹配规则:只要匹配成功,都会在请求链被调用。<url-pattern>不能用以“/”开头并且以“/*”结尾的根据路径映射,和以"*."开头的作为根据扩展名映射。

第九章:Servlet工作原理解析的更多相关文章

  1. 第九章 Servlet工作原理解析

    9.1 从Servlet容器说起    Servlet容器:Jetty, Tomcat等. 这里以Tomcat为例,  真正管理Servlet的容器是Context容器,一个Context对应一个WE ...

  2. 第九章 Servlet工作原理解析(待续)

    从 Servlet容器说起 创建 Servlet实例 Servlet体系结构 Servlet如何工作 Servlet中的Listener Filter如何工作 Servlet中的url-pattern

  3. Servlet工作原理解析 《深入分析java web 技术内幕》第九章

    参考关于servblet的相关文章 侧重概况:https://blog.csdn.net/levycc/article/details/50728921 ibm的相关:https://www.ibm. ...

  4. Servlet 工作原理解析

    转自:http://www.ibm.com/developerworks/cn/java/j-lo-servlet/ Web 技术成为当今主流的互联网 Web 应用技术之一,而 Servlet 是 J ...

  5. [转]Servlet 工作原理解析

    Web 技术成为当今主流的互联网 Web 应用技术之一,而 Servlet 是 Java Web 技术的核心基础.因而掌握 Servlet 的工作原理是成为一名合格的 Java Web 技术开发人员的 ...

  6. Servlet 工作原理解析--转载

    原文:http://www.ibm.com/developerworks/cn/java/j-lo-servlet/index.html?ca=drs- Web 技术成为当今主流的互联网 Web 应用 ...

  7. 【Java】Servlet 工作原理解析

    Web 技术成为当今主流的互联网 Web 应用技术之一,而 Servlet 是 Java Web 技术的核心基础.因而掌握 Servlet 的工作原理是成为一名合格的 Java Web 技术开发人员的 ...

  8. 【Tomcat】Servlet 工作原理解析

    Web 技术成为当今主流的互联网 Web 应用技术之一,而 Servlet 是 Java Web 技术的核心基础.因而掌握 Servlet 的工作原理是成为一名合格的 Java Web 技术开发人员的 ...

  9. JavaWeb总结--Servlet 工作原理解析

    从 Servlet 容器说起 要介绍 Servlet 必须要先把 Servlet 容器说清楚,Servlet 与 Servlet 容器的关系有点像枪和子弹的关系,枪是为子弹而生,而子弹又让枪有了杀伤力 ...

随机推荐

  1. Collectors类中的静态工厂方法

    工厂方法 返回类型 用于 toList List<T> 把流中的所有数据元素收集到List集合中. stream.collect(toList());  toSet Set<T> ...

  2. Lyrics来源

    Lyre 里拉琴,古希腊语,在北欧流行至中世纪.   Lyrics in sheet music. This is a homorhythmic (i.e., hymn-style) arrangem ...

  3. [数据算法]D1.BloomFilter

    BloomFilter是一种高效的去重算法,算法的要义是散列对比. 1.原理 当一个元素加入集合时,判断这个元素是否 2.举例 例如我要对URL去重(这个在爬虫上可以用): URL1 -> 3. ...

  4. 微信小程序的MVVM思想

    本文参照:[微信小程序开发]秒懂,架构及框架 同时多看:https://blog.csdn.net/qq_26585943/article/details/54378684 微信小程序开发,主要分清楚 ...

  5. spring RedisTemplate的使用(一)--xml配置或JavaConfig配置

    1.xml配置 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="h ...

  6. This application failed to start because it could not find or load the Qt platform plugin异常

    双击项目Release文件夹下的exe程序无法启动: 解决办法: 1.将用到的QT组件拷贝到程序目录: 2.将D:\Qt\Qt5.3.2\5.3\msvc2013_64_opengl\plugins目 ...

  7. qt程序编译错误:could not exec ‘/usr/lib/x86_64-linux-gnu/qt4/bin/qmake’

    linux下安装Qt5.7后添加qmake环境变量后出现错误 执行: qmake -v 出现错误:qmake: could not exec ‘/usr/lib/x86_64-linux-gnu/qt ...

  8. PS笔刷的使用

    直接进入正文了! 第一步 打开你的ps,至少是CS6哦,没有安装包的可以去网上找,或者找我0.0. 第二步 将面板改为绘画功能. 第三步打开“窗口”调出“画笔”“画笔预设”“图层”等面板,“颜色”面板 ...

  9. Java 自增原理

    很多人都知道 i++ 和 ++i 的区别 a = i++: a = i; i = i+1; a = ++ i; i = i + 1; a = i; 但碰到 i = i ++;的时候很多人就懵了? i是 ...

  10. 微信为什么不能下载apk 微信不能打开App下载地址的问题

    此方法可以实现微信内置浏览器跳转到手机其它浏览器,现在网上其它的方法都只是一个页面,让访问者自己手动点右上角浏览器打开,而这个不同,是可以直接自动跳转的.       <?php   error ...