web開發1——servlet

shuaishuai3409發表於2016-09-26

一. 什麼是servlet
servlet是伺服器端(tomcat)執行的一段java程式(java介面),通過http協議,負責接收和響應web客戶端(瀏覽器)的請求。
先附上servlet家族圖譜。
這裡寫圖片描述
以一個簡單servlet小程式,講述servlet的實現方式:

  • 1 編寫java類,實現servlet介面,主要實現service方法。
  • 2 配置web.xml檔案,給servlet一個可訪問的統一資源識別符號URI(servlet-mapping)。
類HelloServlet  實現了servlet介面
配置web.xml檔案
<servlet>
    <servlet-name>wahaha</servlet-name>
    <servlet-class>cn.ishuai.HelloServlet</servlet-class>
</servlet>

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

<servlet-name>名字隨便取,只是個識別符號而已,只要<servlet-mapping><servlet><servlet-name>子元素相同就行。


二 執行過程

  • 1 瀏覽器輸入http://localhost:8080/day01/hello

  • 2 tomcat收到請求後,查詢web.xml配置檔案。先查<servlet-mapping>,因為該配置屬性向瀏覽器刻意暴露了訪問地址hello。然後讀取mapping的子元素<servlet-name>,確定servlet名字為wahaha。然後去查詢<servlet-name>為wahaha的<servlet>元素,讀取<servlet>子元素<servlet-class>的值,確定要訪問的類名及路徑為cn.ishuai.HelloServlet。

  • 3 到tomcat安裝目錄/webapps/day01/WEB-INF/classes/cn/ishuai目錄下查詢到HelloServlet.class檔案,執行。

注:看一下web專案目錄:

WebRoot   web應用所在目錄
|-html css js jsp檔案                  這些檔案存在根目錄下,可被外界直接訪問
|-WEB-INF目錄                          該目錄下檔案不能被外界訪問,由web伺服器負責呼叫 
    |-class目錄 (java 類)
    |-lib   (jar包)
    |-web.xml  (配置檔案)

瀏覽器想要執行的就是伺服器中的HelloServlet這個類,可是它如何才能訪問到這個類呢?答案就是通過配置檔案web.xml,通過<servlet-mapping>這個元素,向外暴露可訪問的URL,瀏覽器輸入URL來訪問伺服器,伺服器通過URL找到對應的servlet名字及地址,向瀏覽器返回結果。<url-pattern>向外暴露的名稱需加反斜線,其相當於http://localhost:8080/projectName/Hello中專案名projectName後的hello類,day01就是專案名。如果不加反斜線,表示在8080後找,認為projectName是類,這樣就不能執行了。

詳細執行過程:
Servlet程式是由WEB伺服器呼叫,web伺服器收到客戶端的Servlet訪問請求後:

  • 1> Web伺服器首先檢查是否已經裝載(裝進記憶體,包括web配置檔案)並建立了該Servlet的例項物件。如果是,則直接執行第4步,否則,執行第2步。

  • 2> 裝載並建立該Servlet的一個例項物件 (呼叫初始化方法)。

  • 3> 呼叫Servlet例項物件的init()方法。

  • 4> 建立一個用於封裝HTTP請求訊息的HttpServletRequest物件和一個代表HTTP響應訊息的HttpServletResponse物件,然後呼叫Servlet的service()方法並將請求和響應物件作為引數傳遞進去。service方法讀取請求資訊,寫入相應資訊,然後web容器讀取相應資訊,通過http協議返回給瀏覽器。

  • 5> WEB應用程式被停止或重新啟動之前,Servlet引擎將解除安裝Servlet(刪除掉專案檔案),並在解除安裝之前呼叫Servlet的destroy()方法。


三 servlet的生命週期

分為四個階段,例項化(建構函式)–>初始化(init)–>服務(service)->銷燬(destroy)

  1. 出生:(例項化–>初始化)瀏覽器第一次訪問Servlet就出生(預設情況下,如果想在web容器啟動時就出生,需要在<servlet>元素中新增<load-on-startup>2</load-on-startup>這個子元素,其值為正整數,越小,優先順序越高,表示在多個servlet下會優先被啟動)。

  2. 活著:(服務)應用活著,servlet就活著。

  3. 死亡:(銷燬)應用解除安裝了servlet就銷燬。(解除安裝是指通過瀏覽器的tomcat介面—manage
    app—undeploy,點選undeploy表示解除安裝應用,即在tomcat的webapps目錄下,會把day01這個應用(專案)刪掉)

針對客戶端的多次Servlet請求,通常情況下,伺服器只會建立一個Servlet例項物件,也就是說Servlet例項物件一旦建立,它就會駐留在記憶體中,為後續的其它請求服務,直至web容器退出,servlet例項物件才會銷燬。

在Servlet的整個生命週期內,Servlet的init方法只被呼叫一次。而對一個Servlet的每次訪問請求都導致Servlet引擎呼叫一次servlet的service方法。對於每次訪問請求,Servlet引擎都會建立一個新的HttpServletRequest請求物件和一個新的HttpServletResponse響應物件,然後將這兩個物件作為引數傳遞給它呼叫的Servlet的service()方法,service方法再根據請求方式分別呼叫doXXX方法。


四 servlet的三種建立方式

  • 1 實現javax.servlet.Servlet介面.(需要重寫servlet裡的5個抽象方法)
  • 2 繼承javax.servlet.GenericServlet(由於GenericServlet簡單實現了Servlet介面,只需你重寫service方法即可—介面卡模式)
  • 3 繼承javax.servlet.http.HttpServlet(HttpServlet繼承了GenericServlet類,不再需要重寫service方法。原因是HttpServlet重寫了service方法,裡面呼叫了自己過載的service方法,而過載的service方法裡又呼叫了doGet和doPost方法,故在使用HttpServlet時,需要重寫doGet和doPost方法,以便讓web容器呼叫我們自己的程式–模板方法設計模式)

servlet對映(<servlet-mapping>)細節:

  • 1 同一個servlet可以有多個servlet-mapping(同一個servlet可以被對映到多個URL上),maping的子元素servlet-name必須是相同的,向外暴露的url-pattern不同。

  • 2 URL(url-pattern)中可以使用萬用字元。 /**: 瀏覽器輸入/day01/haha 、day01/ha 、
    day01/haha/aha/hahd都符合要求

  • 3 *.xx 注:不加斜線,表示任意副檔名,如day01/ha.do 、day01/haha/ha.dododo符合要求 /xx/ * 以任意字元開頭,如day01/action/haha、day01/wahaha/ha都是符合要求的

萬用字元匹配優先順序:絕對匹配–> /開頭 匹配 –> 副檔名方式匹配。/是可以匹配任何輸入的。除了絕對匹配,/* 優先順序始終大於*.do


五 servlet獲取配置資訊

主要通過ServletConfig物件獲取配置資訊,該物件有四種方法:

這裡寫圖片描述

通過三種方式獲得ServletConfig物件,可呼叫下面這四種方法獲取物件資訊。

  • 1> 通過(父)介面servlet的init(ServletConfig)方法,得到該物件。
public class ServletGetInfo extends HttpServlet {

    private ServletConfig config;
    @Override
    public void init(ServletConfig config) throws ServletException {
        // TODO Auto-generated method stub
        this.config=config;
    }

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        System.out.print(config.getInitParameter("encoding"));
    }
}
  • 2>通過使用父類(GenericServlet)的getServletConfig方法,獲取ServletConfig物件,然後呼叫getInitParameter獲取配置資訊。(不要重寫init方法)
public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String ec=this.getServletConfig().getInitParameter("encoding");
        System.out.println(ec);
    }
  • 3>使用父類(GenericServlet)的getInitParameter方法.(GenericServlet繼承了ServletConfig)。(不要重寫init方法,否則Tomcat不會自己建立ServletConfig物件)
public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String ec=this.getInitParameter("encoding");
        System.out.println(ec);
    }

六 servletContext

通過ServletConfig可獲得ServletContext。

有4個作用:

  • 作為域物件(map集合),在當前應用中使多個servlet共享資料
public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        ServletContext sc=this.getServletContext();
        sc.setAttribute("name", "xiaoqiang");
        //String str=(String)sc.getAttribute("name");
        //System.out.print(str);
    }
  • 獲取全域性配置資訊
public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String str=this.getServletContext().getInitParameter("encoding");
        //String str=this.getInitParameter("encoding");
        System.out.println(str);
        String s=(String)this.getServletContext().getAttribute("name");
        System.out.println(s);
    }
  • 獲取資源路徑
public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        ServletContext sc=this.getServletContext();
        String path=sc.getRealPath("/WEB-INF/a.properties");
        Properties prop=new Properties();
        prop.load(new FileInputStream(path));   //IO操作
        System.out.println(prop.getProperty("key"));
    }

相關文章