一、什麼是servlet ?
Servlet本質上就是一個Java語言定義的接口,廣義的Servlet就是指實作了這個Servlet接口的類。一般指的就是後者。
Servlet執行個體的主要功能就是根據用戶端的請求,找到并調用服務端相關java代碼,完成對請求的處理和運算。
Servlet執行個體遵循了伺服器能夠識别的規則,伺服器會根據請求調用對應的servlet進行請求處理。
(1)Servlet執行個體,由Servlet容器建立,通常這個容器就是tomcat。
(2)Servlet是一個接口:位于javax.servlet包中。
二、Servlet實作步驟
具體實作一個Servlet的步驟如下:
- 建立普通的java類,并實作Servlet接口
- 重寫service方法,添加業務邏輯代碼
- 在webRoot下的WEB-INF檔案夾下的web.xml中配置Servlet及其映射
// 普通Java類實作Servlet接口
public class MyServlet implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
// 添加業務邏輯代碼
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("MyServlet 的 service()方法");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
<servlet-name>是指servlet的名稱,<servlet>标簽和<servlet-mapping>标簽中的<servlet-name>必須一緻。<servlet-class>是目前servlet的全限定類名,<url-pattern>是映射servlet的url。
三、Servlet生命周期
Servlet生命周期是指servlet執行個體的建立、初始化、服務執行、銷毀的整個過程。
這些流程都是web伺服器負責調用執行,程式員無法控制整個流程,但是程式員可以擷取到這些Servlet生命周期的時間點,在這些時間點上可以做些業務相關的操作。
了解Servlet的生命周期還要看下Servlet的源碼,源碼中對其生命周期中的主要節點都有相應的方法:
整個方法調用的流程圖如下:
當一個用戶端請求過來的時候,tomcat伺服器首先解析這個url,首先找到對應的應用app,然後根據/xxx去web.xml中根據配置資訊去找對應的servlet,找到對應的servlet後,若還沒有建立servlet執行個體就會建立一個該servlet執行個體,然後執行init()方法,service()方法,然後響應用戶端;若該servlet執行個體已存在,就隻會執行service()方法。當應用解除安裝的時候,會執行destory()方法銷毀這個servlet執行個體。
我們來示範一下:
public class MyServlet implements Servlet {
public MyServlet(){
System.out.println("create servlet !");
}
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("initialize Servlet !");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("MyServlet's service() method");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
System.out.println("destroy servlet!");
}
}
浏覽器輸入位址:
檢視日志:
create servlet !
initialize Servlet !
MyServlet's service() method
可以看出執行順序符合上面流程圖定義的順序,無參構造--》初始化--》service方法,但是沒有直接執行destroy銷毀方法,一個servlet執行個體隻會在服務停止時調用一次該方法。無參構造和初始化也隻會執行一次,若現在再次刷頁面,隻會執行service方法:
create servlet !
initialize Servlet !
MyServlet's service() method
MyServlet's service() method
MyServlet's service() method
總結一下servlet的特征:
- servlet是單例多線程的,單例是指servlet的執行個體隻有一個,多線程是指每次用戶端的請求,web伺服器都會從線程池中配置設定一個工作線程去執行servlet的service()方法,線程安全。
- 預設情況下,servlet不會在服務啟動時執行個體化,即一個servlet執行個體的無參構造和初始化也隻會執行一次,且不會在服務啟動時執行,而是在第一次請求時執行,是以接到請求時會先檢查servlet執行個體是否已經存在
- 每次請求隻會執行一個service方法
- 一個servlet執行個體隻會在服務停止時調用一次該方法
四、HttpServlet
現在我們的請求都是基于HTTP協定的,是以應該專門為HTTP請求寫一個Servlet做為通用父類。
HttpServlet的工作流程如下:
- 1.Web客戶向Servlet容器發出Http請求
- 2.Servlet容器解析Web客戶的Http請求
- 3.Servlet容器建立一個HttpRequest對象,在這個對象中封裝Http請求資訊
- 4.Servlet容器建立一個HttpResponse對象
- 5.Servlet容器調用HttpServlet的service方法,把HttpRequest和HttpResponse對象作為service方法的參數傳給HttpServlet對象,service()方法會判斷來自客服端的請求方式,根據不同請求方式調用不同方法,如果是get請求,則調用doGet()方法,如果是post請求,則調用doPost()方法
- 6.HttpServlet調用HttpRequest的有關方法,擷取HTTP請求資訊
- 7.HttpServlet調用HttpResponse的有關方法,生成響應資料
- 8.Servlet容器把HttpServlet的響應結果傳給Web客戶
補充一:
JSP和Servlet有哪些相同點和不同點,他們之間的聯系是什麼?
JSP (JavaServer Pages)是Servlet技術的擴充,本質上是Servlet的簡易方式,更強調應用的外表表達。JSP編譯後是"類servlet"。Servlet和JSP最主要的不同點在于,Servlet的應用邏輯是在Java檔案中,并且完全從表示層中的HTML裡分離開來。而JSP的情況是Java和HTML可以組合成一個擴充名為.jsp的檔案。JSP側重于視圖,Servlet主要用于控制邏輯。
補充二:
- genericservlet類提供了servlet接口的基本實作;
- HttpServlet是GenericServlet的子類,又是在GenericServlet的基礎上做了增強;
補充三:
請求轉發與重定向差別
servlet API中forward() 與redirect()的差別?
前者僅是容器中控制權的轉向,在用戶端浏覽器位址欄中不會顯示出轉向後的位址;後者則是完全的跳轉,浏覽器将會得到跳轉的位址,并重新發送請求連結。這樣,從浏覽器的位址欄中可以看到跳轉後的連結位址。是以,前者更加高效,在前者可以滿足需要時,盡量使用 forward()方法,并且,這樣也有助于隐藏實際的連結。在有些情況下,比如,需要跳轉到一個其它伺服器上的資源,則必須使用 sendRedirect()方法。從資料共享來說:forward 共享 request 中的資料,redirect 不能。forward - 一般用于使用者登陸的時候,根據角色轉發到相應的子產品, redirect - 一般用于使用者登出登陸時傳回首頁面和跳轉到其它的網址等;
補充四:Servlet與線程安全
- 1.不要在Servlet中建立成員!建立局部變量即可!
- 2.可以建立無狀态成員!無狀态表示不可變
- 3.可以建立有狀态的成員,但狀态必須為隻讀的!