JavaWeb之Servelt詳解

一.Servlet是什麼?

Servlet(Server Applet)是指Java語言實現的一個接口,運行在服務器端,爲客戶端的操作做出不同的響應,實現不同功能的一段代碼。

二、Servlet 創建有三種方式

1、實現 Servlet 接口

2、繼承 GenericServlet 類

3、繼承 HttpServlet 方法

創建 Servlet 的第三種方法,也是我們經常用的方法。

三、接口中的方法

1.Servlet中一共有五個方法

package javax.servlet;

在這裏插入圖片描述

  • init 第一次請求我們編寫的Serlvet時,Servlet容器調用此方法,後續不在調用,可以利用這個方法做一些初始化的工作。在調用這個方法時,Servlet容器會傳遞一個ServletConfig。一般會將這個ServletConfig賦給一個類級變量,以方便其他方法也可以使用這個對象。
  • service 每次用戶請求service時,servlet容器都會調用這個方法,我們對請求的處理就是在這裏完成的。
  • destroy 要銷燬Servlet時,Servlet容器就會調用這個方法,它通常發生在卸載應用程序,或者關閉Servlet容器的時候,這裏一般我們會寫一些資源清理相關的代碼。

Servlet中另外另個費生命週期的方法:getServletInfo和getServletConfig

  • getServletInfo 就是字面意思,返回Servlet的描述
  • getServletConfig 這個方法返回由Servlet容器傳給init方法的ServletConfig,上面說了,一般在init方法中將ServletConfig賦給一個類級變量,免得本方法返回null。

四、配置Servlet的方式

  1. 在web.xml配置Servlet程序,配置Servlet虛擬路徑(用戶通過這個虛擬路徑訪問Servlet程序)
	<servlet>
   		 <!-- 爲 Servlet程序  命名 -->
        <servlet-name>user</servlet-name>
   		 <!-- Servlet全路徑 : 包名.類名 -->
        <servlet-class>com.xinzhi.controller.UserServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <!-- 爲Servlet程序 指定 瀏覽器訪問 虛擬路徑 -->
        <servlet-name>user</servlet-name>
        <!-- 用戶 在 瀏覽器通過/user 訪問Servlet -->
        <url-pattern>/user</url-pattern>
    </servlet-mapping>
  1. 可以使用註解的方式進行Servlet配置
@WebServlet("/user")

**eg:**這兩種方式不能同時使用,即配置了web.xml就不能使用註解,使用了註解就不能使用web.xml配置。

五、Servlet 加載時機

1、創建Servlet對象的時機:

默認情況下,在Servlet容器啓動後:客戶首次向Servlet發出請求,Servlet容器會判斷內存中是否存在指定的Servlet對象,如果沒有則創建它,然後根據客戶的請求創建HttpRequest、HttpResponse對象,從而調用Servlet對象的service方法;

Servlet容器啓動時:當web.xml文件中如果元素中指定了子元素時,Servlet容器在啓動web服務器時,將按照順序創建並初始化Servlet對象;

<servlet>
        <servlet-name>user</servlet-name>
        <servlet-class>com.xinzhi.controller.UserServlet</servlet-class>
        <!-- 設置的數值大於0即可 -->
        <load-on-startup>1</load-on-startup>
    </servlet>

2、Servlet對象的生命週期:

在Servlet接口中定義了5個方法,其中3個方法代表了Servlet的生命週期:

1. init(ServletConfig)方法:負責初始化Servlet對象,在Servlet的生命週期中,該方法執行一次;

2. service(ServletRequest req,ServletResponse res)方法:負責處理客戶端的請求;爲了提高效率,Servlet規範要求一個Servlet實例必須能夠同時服務於多個客戶端請求,即service()方法運行在多線程的環境下,Servlet開發者必須保證該方法的線程安全性;

3. destroy()方法:當Servlet對象退出生命週期時,負責釋放佔用的資源;

在調用Servlet對象的destroy()方法後,Servlet由JVM的垃圾回收期進行垃圾回收。

六、Servlet匹配規則

上面的配置信息,其中標籤首先配置聲明一個servlet,包括servlet的名字和對應的java類名。
其中標籤聲明瞭與該servlet相應的匹配規則,每個標籤代表1個匹配規則。

    <servlet-mapping>
        <!-- 爲Servlet程序 指定 瀏覽器訪問 虛擬路徑 -->
        <servlet-name>user</servlet-name>
        <!-- 用戶 在 瀏覽器通過/user 訪問Servlet -->
        <url-pattern>/user</url-pattern>
    </servlet-mapping>

1、匹配規則

6.1 精確匹配

中配置的項必須與url完全精確匹配。

如配置信息如下:

    <servlet-mapping>
        <!-- 爲Servlet程序 指定 瀏覽器訪問 虛擬路徑 -->
        <servlet-name>user</servlet-name>
        <!-- 用戶 在 瀏覽器通過/user.do 訪問Servlet -->
        <url-pattern>/user.do</url-pattern>
    </servlet-mapping>

當在瀏覽器中輸入如下幾種url時,都會被匹配到該servlet
http://localhost:8080/fristweb_war_exploded/user.do

6.2 擴展名匹配

如果匹配規則如下

<servlet-mapping>
    <servlet-name>MyServlet</servlet-name>
    <url-pattern>*.do</url-pattern>
</servlet-mapping></pre>

則任何擴展名爲jsp(文件名和路徑任意)的url請求都會匹配,比如下面的url都會被匹配
http://localhost:8080/fristweb_war_exploded/demo.do

6.3 路徑匹配

路徑匹配和擴展名匹配不能同時使用

使用擴展名匹配,前面就不能有任何的路徑

如果匹配規則如下

<servlet-mapping>
    <servlet-name>MyServlet</servlet-name>
    <url-pattern>/user/*</url-pattern>
</servlet-mapping></pre>

則請求的ulr只要前面(myapp之後)的路徑是/user,而後面的路徑可以任意。比如下面的url都會被匹配。

http://localhost:8080/fristweb_war_exploded/user/demo.html
http://localhost:8080/fristweb_war_exploded/user/test.jsp

6.4 缺省匹配

如果配置成如下兩種的任意一種

<url-pattern>/</url-pattern>

<url-pattern>/*</url-pattern>

則所有的url都可以被匹配上。其中/*是路徑匹配,只是路徑就是/。

2、優先順序

路徑匹配和擴展名匹配不能同時使用

當一個url與多個servlet的匹配規則可以匹配時,則按照 “ 精確路徑 > 最長路徑>擴展名”這樣的優先級匹配到對應的servlet。舉例如下:

**例1:*比如servletA 的url-pattern爲 /test,servletB的url-pattern爲 / ,這個時候,如果我訪問的url爲http://localhost/test ,這個時候容器就會先進行精確路徑匹配,發現/test正好被servletA精確匹配,那麼就去調用servletA,不會去管servletB。

**例2:**比如servletA的url-pattern爲/test/,而servletB的url-pattern爲/test/a/,此時訪問http://localhost/test/a時,容器會選擇路徑最長的servlet來匹配,也就是這裏的servletB。

例3: 比如servletA的url-pattern:.action ,servletB的url-pattern爲 / ,這個時候,如果我訪問的url爲http://localhost/test.action,這個時候容器就會優先進行路徑匹配,而不是去匹配擴展名,這樣就去調用servletB。

七、Response

response對象包含了所有從服務端返回給客戶端的信息。在HTTP協議下,這些信息通過HTTP頭部或者response的消息體從服務器被傳輸到客戶端。

1. response操作響應行

在http響應行中,包括協議,版本號,以及有一個很重要的值,它叫做響應狀態碼.響應行中我們主要就是操作這些狀態碼,它可以有五種類型取值:

img

  • 常用狀態碼

     200請求成功(其後是對GET和POST請求的應答文檔。)
     302所請求的頁面已經臨時轉移至新的url。
     304未按預期修改文檔。客戶端有緩衝的文檔併發出了一個條件性的請求(一般是提供If-Modified-Since頭表示客戶只想比指定日期更新的文檔)。服務器告訴客戶,原來緩衝的文檔還可以繼續使用。
     404沒有找到文件或目錄。
     405請求中指定的方法不被允許
     500請求未完成。服務器遇到不可預知的情況
    
  • HttpServletResponse操作狀態碼API
    void setStatus(int sc,String sm) 設置狀態代碼
    void sendError(int sc) throws IOException設置錯誤狀態碼
    void sendError(int sc,String msg) throws IOException設置錯誤狀態碼及信息

2. response操作響應頭

http響應頭的格式是 name:value的格式,如果有多個value值,以”,”分開,
例如:
Content-Encoding: gzip
Content-Length: 123
Content-Language: zh-cn
Content-Type: text/html; charset=GB2312
Last-Modified: Tue, 11 Jul 2000 18:23:51 GMT

  • HttpServletResponse操作響應頭 API

    public void setHeader(String name,String value)
    用給定名稱和值設置響應頭。如果已經設置了頭,則新值將重寫以前的值

    public void addHeader(String name, String value)
    用給定名稱和值添加響應頭。此方法允許響應頭有多個值

    public void setIntHeader(String name, int value)
    用給定名稱和整數值設置響應頭。如果已經設置了頭,則新值將重寫以前的值。

    public void addIntHeader(String name, int value)
    用給定名稱和整數值添加響應頭。此方法允許響應頭有多個值。

    public void setDateHeader(String name, long date)
    用給定名稱和日期值設置響應頭。該日期根據距曆元時間的毫秒數指定。如果已經設置了頭,則新值將重寫以前的值。

    public void addDateHeader(String name, long date)
    用給定名稱和日期值添加響應頭。該日期根據距曆元時間的毫秒數指定。此方法允許響應頭有多個值。

案例1:重定向

img

實現:

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    	//設置狀態碼
        resp.setStatus(302);
        //設置響應頭
        resp.setHeader("location","http://www.baidu.com");
    }

開發中我們使用sendRedirect(url);

@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.sendRedirect("http://www.baidu.com");
    }

案例2:定時跳轉

在servlet中,我們通過

@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setStatus(302);
        resp.setHeader("refresh","3,http://www.baidu.com");
    }

在頁面中,我們可以通過
<meta http-equiv="refresh" content="5;url=http://localhost/day09/responseDemo3">
頁面中通過方式操作時,也會將標籤內容寫入到http響應中。

重定向是兩次請求;

重定向的URL可以是其他應用,不侷限於當前應用;

重定向的響應頭是302,並且必須要有Location響應頭;

八、Request

HttpServletRequest對象用於封裝http請求,對於http請求它有三部分組成,http請求行,http請求行及請求正文。

1. request操作請求行

public String getMethod()
返回用於發出此請求的 HTTP 方法的名稱,例如 GET、POST
public String getRequestURI()
返回此請求的 URL 的一部分,從協議名稱一直到 HTTP 請求的第一行中的查詢字符串。
public String getProtocol()
以 protocol/majorVersion.minorVersion 的形式(例如 HTTP/1.1)返回請求使用的協議的名稱和版本。
public String getQueryString()
返回包含在請求 URL 中路徑後面的查詢字符串。如果 URL 沒有查詢字符串,則此方法返回 null。

2. request獲取客戶信息

public String getContextPath()
返回請求 URI 指示請求上下文的那一部分。
public StringBuffer getRequestURL()
重新構造客戶端用於發出請求的 URL。返回的 URL 包含一個協議、服務器名稱、端口號、服務器路徑,但是不包含查詢字符串參數。
public String getRemoteAddr()
返回發送請求的客戶端或最後一個代理的 Internet Protocol (IP) 地址

3. request操作請求頭

public String getHeader(String name)
以 String 的形式返回指定請求頭的值。
public java.util.Enumeration<E> getHeaders(String name)
以 String 對象的 Enumeration 的形式返回指定請求頭的所有值。
public java.util.Enumeration<E> getHeaderNames()
返回此請求包含的所有頭名稱的枚舉。如果該請求沒有頭,則此方法返回一個空枚舉。
public int getIntHeader(String name)
以 int 的形式返回指定請求頭的值。如果該請求沒有指定名稱的頭,則此方法返回 -1。如果無法將頭轉換爲整數,則此方法拋出 NumberFormatException。
public long getDateHeader(String name)
以表示 Date 對象的 long 值的形式返回指定請求頭的值

**4. request獲取請求參數

請求參數是瀏覽器發送請求時攜帶的信息。
對於請求方式GET與POST,請求參數存在位置不同。
GET:請求參數存在於請求的資源路徑中。
POST:請求參數存在於正文中

public String getParameter(String name)
以 String 形式返回請求參數的值,如果該參數不存在,則返回 null
public String[] getParameterValues(String name)
返回包含給定請求參數擁有的所有值的 String 對象數組,如果該參數不存在,則返回 null。
public java.util.Map<K, V> getParameterMap()
返回此請求的參數的 java.util.Map。請求參數是與請求一起發送的額外信息。對於 HTTP servlet,參數包含在查詢字符串或發送的表單數據中。
public java.util.Enumeration<E> getParameterNames()
返回包含此請求中所包含參數的名稱的 String 對象的 Enumeration。如果該請求沒有參數,則此方法返回一個空的 Enumeration。

**5. request域對象的介紹

request對象同時也是一個域對象,開發人員通過request對象在實現轉發時,把數據通過request對象帶給其它web資源處理.

 setAttribute方法
 getAttribute方法
 removeAttribute方法
 getAttributeNames方法

request對象提供了一個getRequestDispatcher方法,該方法返回一個RequestDispatcher對象,調用這個對象的forward方法可以實現請求轉發,從而共享請求中的數據

**6. 請求轉發

請求轉發可以實現路徑的跳轉操作.
ReqeustDispatcher dispatcher=request.getRequestDispatcher("路徑")
dispatcher.forward(request,response)

@Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        User user = new User(1,"zhangsan","12");
        req.setAttribute("user",user);
        RequestDispatcher requestDispatcher = req.getRequestDispatcher("/user.do");
        requestDispatcher.forward(req,resp);
    }

請求轉發和重定向的區別:

1.請求轉發是服務器內部跳轉,地址欄不會發生改變
重定向地址欄會發生改變。

2.請求轉發,只有一次請求,一次響應.
重定向,有兩次請求,兩次響應。

3.請求轉發存在request域,可以共享數據.
重定向不存在request域。

4.請求轉發只能在服務器的內部跳轉,簡單說,只能訪問本站內資源。
重定向可以訪問站外資源,也可以訪問站內資源.

5.請求轉發是由request 發起的 . request.getRequestDispatcher().forward()
重定向是由response 發起的 response.sendRedirect();

6.請求轉發與重定向時路徑寫法不一樣.
重定向要跳轉的路徑是從瀏覽器在次發起的,是瀏覽器端路徑,寫法: /工程名/資源
請求轉發是服務器內部跳轉,這時它與瀏覽器無關 寫法:/資源

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章