1. 程式人生 > >【每日一學190728】servlet基礎

【每日一學190728】servlet基礎

什麼是servlet

Servlet是在伺服器上執行的一個小程式,一個servlet就是一個java類,並且可以通過“請求-響應”程式設計模型來訪問的這個駐留在伺服器記憶體裡的servlet程式。如下圖所示:

比如說瀏覽器去訪問部署在tomcat中的專案,既然是訪問,總得有一個訪問地址,而且訪問後要處理的事情處理完了也需要將該返回的東西給到瀏覽器,那麼這個地址是怎麼樣的呢?或者說這個請求是誰處理的呢?這裡就需要使用到servlet的了,也就是servlet是用來接收瀏覽器的請求並且最後將結果返回的那一道處理程式。

servlet是javaWeb的三大元件之一,另外兩個是Filter(攔截器),Listener(監聽器)

tomcat容器等級

tomcat的容器分為四個等級,分別是container容器->engine容器->host(也就是主機容器)->servlet容器,等級是從大到小,也就是前面的容器時包含後面的容器,servlet容器管理context容器,一個context(上下文)對應一個web工程

編寫一個簡單的servlet的步驟

  • 自定義的類,該類有三種實現方式
    • 方式一就是編寫一個類之後去實現Servlet介面(必須重寫該接口裡面所有的抽象方法)
    • 方式二就是編寫一個類繼承GenericServlet抽象類(重寫生命週期的service方法),GenericServlet抽象類實現了Servlet介面,還實現了GenericConfig介面,GenericServlet其實是定義的一個一般的、與協議無關的servlet。
    • 方式三就是編寫一個類去繼承HttpServlet抽象類(沒有抽象方法,根據頁面的提交方式重寫doGet或者doPost方法),HttpServlet這是基於http協議的,也是使用的最多的
  • 如果是繼承HttpServlet抽象類就需要重寫doGet()或者doPost()方法,這裡取決於使用哪種方式提交,get請求就重寫doGet,post請求就重寫doPost(但是需要注意的是並不是只有這兩種提交方式,還有put,delele請求)。
    • 這裡只是重寫doGet或者doPost方法是因為即使重寫service方法,但是service方法裡面也是呼叫的doGet或者doPost方法,所以不需要重寫service方法
    • 至於為什麼不重寫doPut或doDelete等方法,是因為最常用的是doPost和doGet,而且使用doPost方法也能實現doDelet和doPut請求的功能,所以也是沒有必要。
  • 在web.xml中註冊servlet,主要配置的是servlet和servlet-mapping標籤
    	<?xml version="1.0" encoding="UTF-8"?>
    	<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <!--servlet與servlet-mapping一定是成對出現的,servlet標籤是配置servlet處理的類,但是訪問規則並沒有配置,所以就需要使用servlet-mapping標籤來配置-->
    <servlet>
        <!--servlet的名字-->
        <servlet-name>ServletDemo</servlet-name>
        <!--具體的servlet的類-->
        <servlet-class>servletPackage.ServletDemo</servlet-class>
    </servlet>
    <servlet-mapping>
        <!--指定與對映的servlet的名字-->
        <servlet-name>ServletDemo</servlet-name>
        <!--servlet的具體對映路徑-->
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    	</web-app>
    
    後面的url-pattern其實是我們配置的訪問路徑,比如這裡配置的是/hello,那麼在訪問的時候就需要是http://ip:埠/專案名/hello, 這樣就可以對應到這裡的url-pattern,然後通過servlet-mapping裡面的servlet-name找到與之匹配的servlet標籤裡面的servlet-name,這樣就可以找到servlet標籤裡面的servlet-class(也就是請求的處理類)。

eclipse中建立一個servlet

  • 第一種方式就是直接new一個servlet(這裡建立的方式其實是實現HttpServlet抽象類)
  • 第二種則是在建立類的時候實現Servlet介面

新增servl-api.jar包

如果使用第一種方式建立的servlet顯示沒有導包或者第二種方式時搜尋servlet沒有結果則說明是沒有新增Servlet-api.jar包。 新增方式有兩步:

  • 在eclipse中配置tomcat 在window->perference中新增
  • 第二步就是新增將tomcat新增到執行環境 新增方式是選中專案右鍵開啟Properties->java Bulid path->Libraries->Add Libraries->Server Runtime,選擇tomcat伺服器即可。

在idea中建立一個servlet

參考文章

servlet的生命週期

從方法層面上看

主要是三個方法 init->service->destory

  • 當servlet被第一次訪問的時候init會被呼叫,說明servlt的例項預設情況下是第一次訪問的時候被建立的。(但是可以自己修改),該例項只會被建立一次。說明servlet的例項是單例的。
  • service方法是隻要有請求就會被呼叫
  • 當伺服器關閉時destory方法會被呼叫

當tomcat啟動時建立servlet例項

上面已經說過在預設情況下,servlet例項是在第一次訪問的時候被建立的,也就是說即使tomcat伺服器已經啟動了,但是隻要沒有請求過來那麼servlet例項還是不會被建立,不過這一點是可以自己修改的,可以在web.xml中修改:

<servlet>
    <!--servlet的名字-->
    <servlet-name>ServletDemo</servlet-name>
    <!--具體的servlet的類-->
    <servlet-class>servletPackage.ServletDemo</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

需要注意的是load-on-startup這個標籤的值必須是大於等於0的整數,所有添加了該標籤的servlet,都會在tomcat啟動時建立,該元素的值是一個序號,tomcat會使用這個序號給多個servlet排序,然後在tomcat啟動時會按照這個順序來建立servlet的例項物件。

  • load-on-startup元素標記容器是否在啟動的時候就載入這個servlet(例項化並呼叫其init()方法)。

  • 它的值必須是一個整數,表示servlet應該被載入的順序

  • 當值為0或者大於0時,表示容器在應用啟動時就載入並初始化這個servlet;

  • 當值小於0或者沒有指定時,則表示容器在該servlet被選擇時才會去載入。

  • 正數的值越小,該servlet的優先順序越高,應用啟動時就越先載入。

  • 當值相同時,容器就會自己選擇順序來載入。

ServletConfig

在使用HttpServlet時會有兩個init方法,其中一個含有ServletConfig引數,ServletConfig主要有四個方法,其中有兩個方法是獲取初始化引數的:分別是getInitParameter和getInitParameterNames

String getServletName();
ServletContext getServletContext();
String getInitParameter(String var1);
Enumeration<String> getInitParameterNames();

初始化引數

上面講到ServletConfig中有兩個方法是獲取初始化引數的,那麼什麼是初始化引數呢?其實就是在servlet標籤中的init-param標籤裡面配置的值:

<servlet>
    <!--servlet的名字-->
    <servlet-name>ServletDemo</servlet-name>
    <!--具體的servlet的類-->
    <servlet-class>servletPackage.ServletDemo</servlet-class>
    <init-param>
        <param-name>username</param-name>
        <param-value>1341234</param-value>
    </init-param>
    <init-param>
        <param-name>password</param-name>
        <param-value>helloworldnas</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

上面的配置檔案中在servlet標籤裡面配置了兩個init-param,裡面配置的就是初始化引數。(這裡只是示例,初始化引數一般在框架中使用的比較多)

獲取初始化引數

@Override
public void init(ServletConfig config) throws ServletException {
    String username = config.getInitParameter("username");
    String password = config.getInitParameter("password");
    System.out.println(username + "," + password);
    super.init(config);
}

上面的程式碼就是在init方法裡面通過servletConfig物件獲取配置的引數。

servlet路徑匹配

關於url-pattern路徑匹配有三種方式:

  1. 完全路徑匹配 以/開頭 比如 /aaa /aaa/bbb
  2. 目錄匹配 以/開頭 比如 /aaa/* /*
  3. 副檔名匹配 不能以 /開頭 例如 *.do, *.action

優先順序:完全路徑匹配>目錄匹配>副