Servlet 是 Server Applet 的簡稱,譯爲“服務器端小程序”。
文章目錄
Servlet的定義:
- Servlet 運行在
服務端
的Java小程序; - 是
sun公司提供一套規範
(接口),用來處理客戶端請求、響應給瀏覽器的動態資源; - servlet的
實質就是java代碼
,通過java的API動態的向客戶端輸出內容;
Servlet的開發步驟
實現步驟:
- 創建類繼承HttpServlet類;
- 重寫doGet和doPost方法;
- 在web.xml中進行servlet的配置;
- 部署到Tomcat服務器;
- 在瀏覽器中輸入URL,進行訪問;
第一個Servlet程序實現,參照前一篇文章:Hello,Servlet
**Servlet運行的過程解析: **
tomcat服務器啓動時,首先加載webapps中的每個Web項目的web.xml配置文件。
webapps文件夾裏就是一個對外開放的資源庫。
用戶在瀏覽器輸入:http://localhost:8080/KrojectDynamicWeb/HelloServlet後,
http://
:表明http協議localhost
:到本地的hosts文件中查找是否存在該域名對應的IP地址,查找到是127.0.0.18080
:根據端口找到運行中的Tomcat服務器KrojectDynamicWeb
:在tomcat的webapps目錄下找到KrojectDynamicWeb文件夾HelloServlet
:資源名稱,在KrojectDynamicWeb中的web.xml中查找,是否有匹配url-pattern的內容如果找到匹配的url-pattern
,則使用當前的servlet-name的名稱到web.xml文件中查詢是否有相同名稱的servlet配置如果找到,則取出
對象的servlet配置信息中的servlet-class內容
:net.hackyle.HelloServlet,即一個Java類- 通過
反射,構造HelloServlet對象
,調用該對象裏面的方法 - 執行方法
,Tomcat服務器給瀏覽器做出響應
,顯示在瀏覽器的頁面上
就是這樣,你就看到了頁面上你編寫的內容。
Servlet接口
Servlet接口是已經過時了的開發接口,它的開發步驟是:
- 創建類實現Servlet接口
- 覆蓋尚未實現的方法,如service方法
- 在web.xml進行servlet的配置
在實際開發中,我們不會直接去實現Servlet接口,因爲那樣需要覆蓋的方法太多,我們一般創建類繼承HttpServlet
。但是它以及其裏面的方法任然有學習的價值,因爲HttpServlet是Servlet接口的實現!
SUN公司定義了兩個默認實現類,分別爲:GenericServlet、HttpServlet。
-
HttpServlet類
:能夠處理HTTP請求的servlet,它在原有Servlet 接口上添加了一些與HTTP協議處理方法,它比Servlet接口的功能更爲強大。 -
因此開發人員在編寫Servlet時,通常應繼承這個類,而避免直接去實現Servlet接口
。 -
HttpServlet在實現Servlet接口時,覆寫了service方法,該方法體內的代碼會自動判斷用戶的請求方式;
-
如爲GET請求
,則調用
HttpServlet的doGet方法
; -
如爲Post請求
,則調用doPost方法
。 -
因此,開發人員在編寫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四個生命週期方法
- 構造方法:創建servlet對象的時候調用。默認情況下,
第一次
訪問servlet的時候創建servlet對象只調用1次
。證明servlet對象在tomcat是單實例的。 - init方法:
創建完servlet對象
的時候調用。只調用1次。 - service方法: 每次
發出請求
時調用。調用n次
。 - 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
注意事項:
- 在url-pattern中有兩種固定的格式:一種格式是“*.擴展名”;另一種格式是以正斜槓(/)開頭並以*結尾。
- url-pattern要麼以 / 開頭,要麼以*開頭。
- 不能同時使用兩種模糊匹配,例如 /itcast/*.do是非法路徑
- 當有輸入的URL有多個servlet同時被匹配的情況下:
a) 精確匹配優先。(長的最像優先被匹配)
b) 以後綴名結尾。(*.後綴名)的模糊url-pattern優先級最低!!!
缺省路徑
Tomcat的安裝“config”目錄下的web.xml文件指定了缺省路徑(即當我們輸入的一個URL,在webapps目錄下並沒有找到,於是就把缺省路徑下的一個HTML資源返回。)
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的過程
-
當服務器接收到URL後;
-
經過URL與web.xml中的
url-pattern
進行映射匹配後; -
找到了
servlet-class
的內容,得到了本次URL需要調用的類的全名:net.hackyle.HelloServlet; -
通過
反射
構造該類對象,即構造HelloServlet類的對象;
- 得到字節碼對象:Class class = class.forName("net.hackyle.HelloServlet ");
- 調用無參數的構造方法來構造對象:Object obj = class.newInstance(); (注意:此時servlet的構造方法被調用)
創建ServletConfig對象
,通過反射調用init方法
- 得到方法對象:Method m = class.getDeclareMethod(“init”,ServletConfig.class);
- 調用方法:m.inmoke(obj,config); (注意:此時servlet的init方法被調用)
創建request,response對象
,通過反射調用service方法
- 得到方法對象:Methodm m=class.getDeclareMethod(“service”,HttpServletRequest.class,HttpServletResponse.class);
- 調用方法:m.invoke(obj,request,response); (注意:servlet的service方法被調用)
- 當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()方法。
自動加載機制
出現背景:
- 默認情況下,第一次訪問servlet的時候創建servlet對象。
- 如果servlet的構造方法或init方法中執行了比較多的邏輯代碼,那麼導致用戶第一次訪問sevrlet的時候比較慢。
解決方案:
- 改變servlet創建對象的時機;
- 提前到加載web應用的時候!!! 即在servlet的web.xml配置信息中,加上一個即可!!
- 在中的整數值越大,創建優先級越低!!
- 可以爲多個類創建快速啓動;