Servlet解析

JAVA WEB 技術是當今主流的互聯網WEB應用技術之一,而Servlet則是JAVA WEB 中的核心基礎。最近在看了《深刻分析Java Web技術內幕》(許令波 著)這本書發現了之前沒有看到的內容,就想對書中的內容進行總結,也方便本身之後的回顧,因此就有了這篇文章。java

經過這篇文章你將瞭解到如下內容:web

1.Servlet容器是如何工做
2.web應用中的Servlet如何建立
3.Servlet是如何被調用

Servlet容器的啓動

tomcat的體系結構

在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

WEB應用的初始化

學過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容器屬性的配置文件

Servlet的建立與初始化

首先咱們來看看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的加載、建立、初始化,下面的內容中咱們就來看看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方法將被調用,作一些掃尾工做。

寫在最後

這篇文章是個人第一篇文章,若是有寫的很差的地方,請各位大佬輕噴,小弟再此跪謝了。

相關文章
相關標籤/搜索