JavaWeb之 Servlet執行過程 與 生命周期


Servlet的概念

什么是Servlet呢?

  Java中有一個叫Servlet的接口,如果一個普通的類實現了這個接口,這個類就是一個Servlet。Servlet下有一個實現類叫HttpServlet,一個普通的java如果繼承了HttpServlet類,覆蓋了它的doGet和doPost方法,那么這個普通類也可以叫做Servlet。最后,servlet程序交給服務器運行!

  那么,當我們寫好了一個Servlet,交給了服務器,它是如何執行的呢!?

Servlet的執行過程

我們寫了一個Servlet名叫hello。那么瀏覽器是如何訪問到這個資源呢?

要說這個,我們先來學習一下瀏覽器的地址輸入。

  有這樣一個輸入:   http://localhost:8080/day10/hello

http:    http協議

localhost:   域名,到本地C盤下的hosts文件查找是否存在域名對應的ip映射記錄地址。有的話就直接訪問該IP,沒有的話就到DNS上去找。

8080        端口號,這里指tomcat服務器。localhost匹配到tomcat的默認站點,到webapps目錄下找web應用。

/day10      web應用的名稱。在webapps下找是否存在day10的目錄。

/hello       web資源。在day10web應用下查找是否有這個資源。(如果看不懂,最好先去了解一下tomcat里的文件結構。)

 

    這里/hello 資源就是我們寫的一個Servlet,服務器得到這個字符串后就是經過以下過程來找到servlet的

        ->   得到/hello字符串

 

        ->   使用/helloweb.xml文件中查找每一個<servlet-mapping>下的<url-pattern>標簽里的內容,然后得到sevlet-name

 

        ->   使用sevlet-nameservlet標簽中找到對應的相同名稱的servlet配置。

 

        ->   得到servlet配置中的servlet-class內容。字符串:gz.itcast.a_servlet.HelloServlet

 

<servlet>
    <servlet-name>HelloServlet</servlet-name> 
  <servlet-class>com.vmaxtam.numzero.addServlet</servlet-class>
</servlet>

<servlet-mapping>
  <servlet-name>HelloServlet</servlet-name>
   <url-pattern>/hello</url-pattern>
</servlet-mapping>

 

    最后通過反射實例化HelloServlet對象,然后調用HelloServlet中的方法。

 

 

Servlet的映射路徑

 

<url-pattern>/hello</url-pattern> 這里的映射路徑還可以用多種方式來填寫!

                url-pattern                           瀏覽器輸入URL

精確匹配                       /demo1                              http://localhost:8080/day10/demo1

                 /itcast/demo1          http://localhost:8080/day10/itcast/demo1  

 

模糊匹配

                   /*                                 http://localhost:8080/day10/任意路徑

                  /itcast/*                            http://localhost:8080/day10/itcast/任意路徑

                  *.后綴名                        http://localhost:8080/day10/任意路徑.后綴。例如 *.do,*.action, *.html

 

注意: 

1url-pattern要以/開頭,要么以*開頭。demo1這種寫法是錯誤的!!

2) /itcast/*.do 這種寫法不合法。不能同時使用兩種模糊匹配

3)當一個請求有多個servlet被匹配的情況下:

a)長的最像的url-pattern會優先被匹配

b)以后綴名結尾的url-pattern優先級最低!!!

 

說到這里,就有人問:這個只是在找Servlet文件,那么如果要找服務器的靜態文件(html,xml等),服務器的執行過程如何??如果要找的文件不存在又會怎么樣?

下面為大家講解:

 

 

缺省路徑

 

tomcat服務器中有一個默認的Servlet,叫DefaultServletDefaultServlet的url-pattern為 。這個DefaultServlet的作用主要用於處理靜態資源的請求。

 

    輸入: http://localhost:8080/day10/test.html 如何找到資源呢?

 

        1)在day10web應用下查找web.xml文件,用/test.html,存在匹配是否存在符合規則url-pattern,找到就會執行對應的動態資源(servlet)。

 

        2)如果找不到對應的url-pattern,則到day10當前web應用的根目錄下查找一個test.html名稱的靜態資源文件。如果找到這個文件,DefaultServlet讀取該靜態文件內容輸出到瀏覽器客戶端。

 

        3)如果在day10下找不到test.html的靜態資源文件,那么返回404的頁面。

 

前面只說到服務器是如何找到Servlet這個文件,那么Servlet是如何執行的呢!!!這就是重點,Servlet的生命周期

 

Servlet的生命周期

tomcat服務器什么時候創建servlet對象?什么時候銷毀對象?什么時候調用了什么方法?!

其實也就是這樣的一個過程 :   

      1.Servlet對象的創建。

      2.Servlet對象執行某些方法來給我們服務。

      3.Servlet對象的銷毀。

 

而這個過程有4個很核心的方法需要執行:

構造方法: servlet對象創建時調用。默認情況下,第一次訪問servlet時,servlet對象創建。只被調 用1次。servlettomcat服務器中是單實例的。

init方法:  在創建完servlet對象之后被調用。用於對servlet對象進行初始化。只調用1次。

service方法:每次發出請求時被調用。調用n次。

destroy方法: 在tomcat服務器停止或者web應用重新加載時調用。只調用1次。

 

下面我們用偽代碼來演示一下 瀏覽器發出請求 到服務器作出相應 整個過程中Servlet的執行過程!

瀏覽器輸入: http://localhost:8080/day10/hello

 進入web.html查詢資源。

得到字符串 gz.itcast.a_servlet.HelloServlet

 

模擬tomcat服務器內部的運行代碼:

1)用反射構造HelloServlet對象

  1.1 得到字節碼對象

    Class clazz = Class.forName("gz.itcast.a_servlet.HelloServlet ")

  1.2 調用無參的構造方法構造對象

    Object obj = clazz.newInstance();       ----1.Servlet的構造方法被執行

2)創建ServletConfig對象,調用init方法

     2.1 得到init方法對象

    Method method = clazz.getDeclareMethod("init",ServletConfig.class);

  2.2 執行init方法

    method.invoke(obj, config);               --2. Servletinit方法被執行

 

3)創建requestresponse對象,調用service方法

  3.1 得到service方法對象

    Method m = clazz.getDeclareMethod("service",HttpServletRequest.class,HttpServletResponse.class);

  3.2 執行方法

    m.invoke(obj,request,response);          --3.Servletservice方法被執行

 

4tomcat服務器停止或web應用重新加載時,調用destroy方法

  4.1 得到destroy方法對象

    Method method = clazz.getDeclareMethod("destroy",null);

   4.2 執行方法

    method.invoke(obj,null);               --4.Servletdestroy方法被執行

 

如果文字不夠直觀,那么我看可以看一下流程圖

Servlet對象自動加載

引入

    默認情況下,servlet對象會在第一次請求servlet時被創建。創建完之后調用init方法。假如構造方法或者init方法執行的業務邏輯比較多,那么用戶在第一次訪問servlet時的等待會變長,影響用戶的體驗。

解決辦法

    改變servlet的創建時機:讓servlet對象在tomcat服務器啟動web應用加載時創建。

 

servlet的配置中,加入一個配置:

<load-on-startup>正整數</load-on-startup>

 

<servlet>

    <servlet-name>LifeDemo1</servlet-name>

    <servlet-class>gz.itcast.c_life.LifeDemo1</servlet-class>

    <load-on-startup>1</load-on-startup>

  </servlet>

注意: 正整數的數值越大,創建的優先級就越低!!

 

 Servlet的多線程安全問題

    結論: servlettomcat服務器中是單實例多線程的.

 

多線程並發問題

  多個線程之間同時操作了共享數據!!!

解決多線程並發問題

  給需要同步的代碼塊加上唯一的對象鎖。

 

如何編寫線程安全的servlet類:

  1)盡量不要使用成員變量。

  2)如果使用成員變量,要給用到了成員變量的代碼塊加上鎖。盡量縮小同步代碼塊的范圍,以避免因為同步導致執行效率問題。

 

Init方法

  在GenericServlet中提供了一個無參數的init方法!!!

    有參數的init:該方法是Servlet的四個生命周期方法中的一個,該方法一定會被服務器調用。在該方法中會調用無參數的init方法。

    無參數的init:該方法是Sun公司設計出來方便開發者進行重寫,在該方法中實現對servlet對象的初始化工作,這個方法會被有參的init方法調用!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM