【Servlet】Servlet的一般開發流程和執行過程

Servlet 是 Server Applet 的簡稱,譯爲“服務器端小程序”。

Servlet的定義:

  1. Servlet 運行在服務端的Java小程序;
  2. sun公司提供一套規範(接口),用來處理客戶端請求、響應給瀏覽器的動態資源;
  3. servlet的實質就是java代碼,通過java的API動態的向客戶端輸出內容;

Servlet的開發步驟

實現步驟:

  1. 創建類繼承HttpServlet類;
  2. 重寫doGet和doPost方法;
  3. 在web.xml中進行servlet的配置;
  4. 部署到Tomcat服務器;
  5. 在瀏覽器中輸入URL,進行訪問;

第一個Servlet程序實現,參照前一篇文章:Hello,Servlet

**Servlet運行的過程解析: **

tomcat服務器啓動時,首先加載webapps中的每個Web項目的web.xml配置文件。
webapps文件夾裏就是一個對外開放的資源庫。

用戶在瀏覽器輸入:http://localhost:8080/KrojectDynamicWeb/HelloServlet後,

  1. http://:表明http協議
  2. localhost:到本地的hosts文件中查找是否存在該域名對應的IP地址,查找到是127.0.0.1
  3. 8080:根據端口找到運行中的Tomcat服務器
  4. KrojectDynamicWeb:在tomcat的webapps目錄下找到KrojectDynamicWeb文件夾
  5. HelloServlet:資源名稱,在KrojectDynamicWeb中的web.xml中查找,是否有匹配url-pattern的內容
  6. 如果找到匹配的url-pattern,則使用當前的servlet-name的名稱到web.xml文件中查詢是否有相同名稱的servlet配置
  7. 如果找到,則取出對象的servlet配置信息中的servlet-class內容:net.hackyle.HelloServlet,即一個Java類
  8. 通過反射,構造HelloServlet對象,調用該對象裏面的方法
  9. 執行方法,Tomcat服務器給瀏覽器做出響應,顯示在瀏覽器的頁面上

就是這樣,你就看到了頁面上你編寫的內容。

Servlet接口

Servlet接口是已經過時了的開發接口,它的開發步驟是:

  1. 創建類實現Servlet接口
  2. 覆蓋尚未實現的方法,如service方法
  3. 在web.xml進行servlet的配置

在實際開發中,我們不會直接去實現Servlet接口,因爲那樣需要覆蓋的方法太多,我們一般創建類繼承HttpServlet。但是它以及其裏面的方法任然有學習的價值,因爲HttpServlet是Servlet接口的實現

SUN公司定義了兩個默認實現類,分別爲:GenericServlet、HttpServlet。

  1. HttpServlet類:能夠處理HTTP請求的servlet,它在原有Servlet 接口上添加了一些與HTTP協議處理方法,它比Servlet接口的功能更爲強大。

  2. 因此開發人員在編寫Servlet時,通常應繼承這個類,而避免直接去實現Servlet接口

  3. HttpServlet在實現Servlet接口時,覆寫了service方法,該方法體內的代碼會自動判斷用戶的請求方式;

  4. 如爲GET請求,則調用HttpServlet的doGet方法

  5. 如爲Post請求,則調用doPost方法

  6. 因此,開發人員在編寫Servlet時,通常只需要覆寫doGet或 doPost方法,而不要去覆寫service方法

接口方法

1)init(ServletConfig config)

  • 何時執行:servlet對象創建的時候執行,由服務器創建對象並調用init方法。
    ServletConfig :代表的是該servlet對象的配置信息

2)service(ServletRequest request,ServletResponse response)

  • 何時執行:每次請求都會執行
    ServletRequest :代表請求,認爲ServletRequest 內部封裝的是http請求的信息
    ServletResponse :代表響應 認爲要封裝的是響應的信息

3)destroy()

  • 何時執行:servlet銷燬的時候執行

Servlet的生命週期

Servlet程序的生命週期由tomcat服務器控制。

1)Servlet何時創建:默認第一次訪問servlet時創建該對象
2)Servlet何時銷燬:服務器關閉servlet就銷燬了
3)每次訪問必然執行的方法:service(ServletRequest req, ServletResponse res)方法

Servlet四個生命週期方法

  1. 構造方法:創建servlet對象的時候調用。默認情況下,第一次訪問servlet的時候創建servlet對象只調用1次。證明servlet對象在tomcat是單實例的。
  2. init方法創建完servlet對象的時候調用。只調用1次。
  3. service方法: 每次發出請求時調用。調用n次
  4. destroy方法銷燬servlet對象的時候調用。停止服務器或者重新部署web應用時銷燬servlet對象。只調用1次。

證明Servlet生命週期方法調用次數

import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;

public class HelloServlet extends HttpServlet {
	 // 1.構造方法
	public HelloServlet(){
		System.out.println("1.servlet對象被創建了。");
	}

	 // 2.init方法
	@Override
	public void init(ServletConfig config) throws ServletException {
		System.out.println("2.init方法被調用");
	}
	
	 // 3.service方法
	@Override
	public void service(ServletRequest req, ServletResponse res)
			throws ServletException, IOException {
		System.out.println("3.service方法被調用");
	}
	
	 // 4.destroy方法
	@Override
	public void destroy() {
		System.out.println("4.servlet對象銷燬了");
	}
}

在這裏插入圖片描述

web.xml

功能:

  • Web項目一啓動,服務器就讀取web.xml這個文件;
  • 因爲這個文件告訴了Tomcat該從那個類開始執行,如何去執行;

HelloServlet的web.xml配置詳情:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>KrojectDynamicWeb</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  <servlet>
    <description></description>
    <display-name>HelloServlet</display-name>
    <servlet-name>HelloServlet</servlet-name>
    <servlet-class>hello.HelloServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>HelloServlet</servlet-name>
    <url-pattern>/HelloServlet</url-pattern>
  </servlet-mapping>
</web-app>

servlet標籤

<servlet>元素用於註冊Servlet,它包含有兩個主要的子元素:<servlet-name><servlet-class>,分別用於設置Servlet的註冊名稱和Servlet的完整類名
一個<servlet-mapping>元素用於映射一個已註冊的Servlet的一個對外訪問路徑,它包含有兩個子元素:<servlet-name><url-pattern>,分別用於指定Servlet 的註冊名稱和Servlet的對外訪問路徑
在這裏插入圖片描述

url-pattern的映射

訪問Web項目的URL中,最後一個組成成分(“http://localhost:8080/KrojectDynamicWeb/HelloServlet”),將會在項目工程中的web.xml中查找是否有匹配的url-pattern的內容,匹配成功才能正常運行URL;

例如URL: http://localhost:8080/Kroject/first;映射路徑是指把”/first”在web.xml中的url-pattern中尋找是否有一樣的;
在這裏插入圖片描述
在這裏插入圖片描述

在執行URL最後部分與url-pattern的匹配過程中,有兩種匹配類型:
A. 精確匹配
瀏覽器輸入:url-pattern
http://localhost:8080/day10/first: /first
http://localhost:8080/day10/itcast/demo1: /itcast/demo1

B. 模糊匹配
瀏覽器輸入 ===> url-pattern
http://localhost:8080/day10/任意路徑 ===> /*
http://localhost:8080/day10/itcast/任意路徑 ===> /itcast/*
http://localhost:8080/day10/任意路徑.後綴名 ===> *.後綴名
http://localhost:8080/day10/任意路徑.do ===> *.do
http://localhost:8080/day10/任意路徑.action ===> *.action

注意事項:

  1. 在url-pattern中有兩種固定的格式:一種格式是“*.擴展名”;另一種格式是以正斜槓(/)開頭並以*結尾。
  2. url-pattern要麼以 / 開頭,要麼以*開頭。
  3. 不能同時使用兩種模糊匹配,例如 /itcast/*.do是非法路徑
  4. 當有輸入的URL有多個servlet同時被匹配的情況下:
    a) 精確匹配優先。(長的最像優先被匹配)
    b) 以後綴名結尾。(*.後綴名)的模糊url-pattern優先級最低!!!

缺省路徑

Tomcat的安裝“config”目錄下的web.xml文件指定了缺省路徑(即當我們輸入的一個URL,在webapps目錄下並沒有找到,於是就把缺省路徑下的一個HTML資源返回。)
在這裏插入圖片描述
在這裏插入圖片描述

Tomcat安裝目錄下的config/web.xml

servlet的缺省路徑(/)是在tomcat服務器內置的一個路徑。該路徑對應的是一個DefaultServlet(缺省Servlet)。這個缺省的Servlet的作用是用於解析web應用的靜態資源文件。

匹配問題例題
問題: URL輸入http://localhost:8080/day10/index.html 如何讀取文件????
解答:
1)到當前day10應用下的web.xml文件查找是否有匹配的url-pattern。
2)如果沒有匹配的url-pattern,則交給tomcat的內置的DefaultServlet處理
3)DefaultServlet程序到day10應用的根目錄下查找是存在一個名稱爲index.html的靜態文件。
4)如果找到該文件,則讀取該文件內容,返回給瀏覽器。
5)如果找不到該文件,則返回404錯誤頁面。

結論:先找動態資源,再找靜態資源。儘量不要在web.xml文件下配置僞靜態文件。

Tomcat服務器運行Servlet的過程

  1. 當服務器接收到URL後;

  2. 經過URL與web.xml中的url-pattern進行映射匹配後;

  3. 找到了servlet-class的內容,得到了本次URL需要調用的類的全名:net.hackyle.HelloServlet;

  4. 通過反射構造該類對象,即構造HelloServlet類的對象;

  • 得到字節碼對象:Class class = class.forName("net.hackyle.HelloServlet ");
  • 調用無參數的構造方法來構造對象:Object obj = class.newInstance(); (注意:此時servlet的構造方法被調用)
  1. 創建ServletConfig對象,通過反射調用init方法
  • 得到方法對象:Method m = class.getDeclareMethod(“init”,ServletConfig.class);
  • 調用方法:m.inmoke(obj,config); (注意:此時servlet的init方法被調用)
  1. 創建request,response對象,通過反射調用service方法
  • 得到方法對象:Methodm m=class.getDeclareMethod(“service”,HttpServletRequest.class,HttpServletResponse.class);
  • 調用方法:m.invoke(obj,request,response); (注意:servlet的service方法被調用)
  1. 當tomcat服務器停止或web應用重新部署,通過反射調用destroy方法
  • 得到方法對象:Method m = clazz.getDeclareMethod(“destroy”,null);
  • 調用方法:m.invoke(obj,null); (注意:servlet的destroy方法被調用)

再次請求相同URL

① Web服務器首先檢查是否已經裝載並創建了該Servlet的實例對象。如果是,則直接執行第④步,否則,執行第②步。
② 裝載並創建該Servlet的一個實例對象。
③ 調用Servlet實例對象的init()方法。
④ 創建一個用於封裝HTTP請求消息的HttpServletRequest對象和 一個代表HTTP響應消息的HttpServletResponse對象,然後調用 Servlet的service()方法並將請求和響應對象作爲參數傳遞進去。
⑤ WEB應用程序被停止或重新啓動之前,Servlet引擎將卸載 Servlet,並在卸載之前調用Servlet的destroy()方法。

自動加載機制

出現背景:

  1. 默認情況下,第一次訪問servlet的時候創建servlet對象。
  2. 如果servlet的構造方法或init方法中執行了比較多的邏輯代碼,那麼導致用戶第一次訪問sevrlet的時候比較慢。

解決方案:

  1. 改變servlet創建對象的時機;
  2. 提前到加載web應用的時候!!! 即在servlet的web.xml配置信息中,加上一個即可!!
  3. 在中的整數值越大,創建優先級越低!!
  4. 可以爲多個類創建快速啓動;

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