JAVA WEB 技术是当今主流的互联网WEB应用技术之一,而Servlet则是JAVA WEB 中的核心基础。最近在看了《深刻分析Java Web技术内幕》(许令波 著)这本书发现了之前没有看到的内容,就想对书中的内容进行总结,也方便本身之后的回顾,因此就有了这篇文章。java
经过这篇文章你将了解到如下内容:web
1.Servlet容器是如何工做 2.web应用中的Servlet如何建立 3.Servlet是如何被调用
在Tomcat中整个的体系结构中,Context容器直接管理Servlet在容器中的包装类Wrapper,因此Context是真正管理Servlet的容器。经过图咱们还能够看出,一个Context对应着一个Web工程。在Tomcat配置文件中就能够看出:apache
<Context path="/projectOne " docBase="D:\projects\projectOne" reloadable="true" />
既然Context容器如此的重要咱们就来了解下Tomcat是如何解析Context容器的。tomcat
首先,咱们已经知道了Context容器是Tomcat运行时的容器,它只有在添加web应用是被加载。服务器
public Context addWebapp(Host host, String url, String path) { silence(url); Context ctx = new StandardContext(); ctx.setPath( url ); ctx.setDocBase(path); if (defaultRealm == null) { initSimpleAuth(); } ctx.setRealm(defaultRealm); ctx.addLifecycleListener(new DefaultWebXmlListener()); ContextConfig ctxCfg = new ContextConfig(); ctx.addLifecycleListener(ctxCfg); ctxCfg.setDefaultWebXml("org/apache/catalin/startup/NO_DEFAULT_XML"); if (host == null) { getHost().addChild(ctx); } else { host.addChild(ctx); } return ctx; }
当一个WEB应用被添加时Tomcat将会建立一个StandardContext容器,并给这个Context容器设置必要的参数,URL和path分别表明这个应用在访问路径和这个应用实际的物理路径。其中最重要的配置就是ContextConfig,这个类很是重要,是负责整个WEB应用的解析工做。app
咱们就来看看这个ContextConfig:框架
ContextConfig继承了LifecycleListener接口,它是在调用addWebApp方法时被加入到StandardContext容器中的,负责整个web应用的配置文件解析工做。 自带的init()方法和startInternal()方法最为重要 1.init()主要完成如下工做 -建立用于解析的XML配置文件的contextDisester对象。 -读取默认的context.xml配置文件,若是存在则解析。 -读取默认的Host配置文件,若是存在则解析。 -读取默认的Context自身的配置文件,若是存在则解析。 -设置Context的DocBase。 2. startInternal()方法 -建立读取资源文件的对象 -建立ClassLoader对象。 -设置应用的工做目录。 -启动相关的辅助类。 -修改启动状态,通知感兴趣的观察者。 -子容器的初始化。 -获取ServletContext并设置必要的参数 -初始化“load on startup”的Servlet。
最后将这个Context容器添加到父容器中,而后就是调用Tomcat的start方法启动Tomcat。这样就完成了整个WEB应用加载的前期工做。jsp
学过Javaweb基础的同窗应该知道,web.xml是咱们整个web工程中不可缺乏的一个部分,若是你的项目中缺乏了它,可能就会致使一些
必要的BUG。同时,整个web应用的初始化主要也是解析这个文件,由于这个文件描述了你的web项目中一些关键信息,也是整个web项目的入口。url
接下来咱们来看下Tomcat是如何加载到这个如此重要的配置文件的。spa
1.首先会找到globalWebXml 2.接着会找到hostWebXml 3.最后是寻找应用的配置文件web.xml
完成以上的步骤以后,Tomcat会将web.xml中的相应属性保存到WebXml对象中。如今不少的后台web应用都已经升级到Servlet3.0了,若是你的项目也支持了这个版本,那么在解析配置文件的时候,还要完成Servlet3.0中新增的特性的解析以及对annotat的支持。Servlet3.0在这里就很少介绍了,他不是本文的重点内容。
将属性存入WebXml对象后,也将相关的属性设置到Context容器中,这些属性包括Servlet,listener,filter,其中Servlet被包装成具备容器属性的StandardWrapper。
看到这里咱们来对web.xml的做用进行一个总结
1.web应用的解析入口 2.做为用来指定context容器属性的配置文件
首先咱们来看看Tomcat是如何建立Servlet:
建立Servlet实例的方法是从Wrapper.loadServlet开始的,这个方法要完成的就是获取servletClass,而后交给InstanceManager去建立一个基于servletClass.class的对象。
若是在web.xml中配置了 <jsp-file>。。。。</jsp-file>这个参数的话,在建立Servlet时初始化的就不是你本身编写的JAVA类了,而是conf/web.xml中的org.apache.jasper.servlet.JspServlet。
Servlet的初始化操做是在StandardWrapper的initServlet方法中完成的,做用就是调用Servlet的init(),同时将StandardWrapperFacade做为ServletConfig传给Servlet。
StandardWrapperFacade的做用就是从StandardWrapper中拿到的数据只是ServltConfig中规定的数据,而不把不关心的数据暴露给Servlet,起到了对数据封装的做用。
若是初始化的是JspServlet,那Tomcat会模拟一次请求,去请求这个JSP文件,为的是将这个jsp文件编译成类,并初始化这个类,用于后面的使用。
在前面的内容中咱们了解了Servlet的加载、建立、初始化,下面的内容中咱们就来看看Servlet是如何被调用的。
用户向服务器发送请求一般包含的信息:
http://hosthome:port/contextpath/servletpath 其中 hosthome 和 port 用于与服务器创建TCP链接,然后面的URL则是用户请求服务器中的某个子容器的数据。
咱们以Tomcat这个经常使用的容器来讲明服务器是如何根据这个URL找到正确的Servlet容器。
在Tomcat中这种映射工做是由org.apache.tomcat.util.http.mapper这个专门的类去处理的。 这个类保存了Tomcat的Container容器中全部子容器的信息,当请求的Request类进入Container容器以前, Mapper将会根据此次请求的hostname和contextPath将host和context容器设置到Request的mappingData属性中。
因此在请求进入容器以前就已经知道要访问那个子容器。
在知道要访问那个子容器后,接下来就是要执行Servlet的service方法。咱们一般的作法就是不继承javax.servlet.servlet接口更为简单的HttpServlet类。
可是如今的WEB应用已经直接使用Servlet来完成用户的交互逻辑了,而是使用更为高效的MVC框架来完成这些任务。
而这些框架的入口也是Servlet的Service方法。
当Servlet从Servlet容器中移除时,也就说明Servlet的生命周期就结束了,这时Servlet的destroy方法将被调用,作一些扫尾工做。
这篇文章是个人第一篇文章,若是有写的很差的地方,请各位大佬轻喷,小弟再此跪谢了。