Java基礎面試題(11)----Servlet的理解和生命週期
阿新 • • 發佈:2018-12-13
問題
說說對servlet的理解? 什麼是servlet的生命週期?
回答
Servlet是什麼?
selvet(server applet),全稱Java Servlet,使用Java語言編寫的服務端程式,這些servlet都需要繼承HttpServlet這個抽象類,重寫的doGet()和doPost()這兩個方法,或者主動重寫service()方法。HttpServlet最終實現的是Servlet這個介面。 其主要的功能是在於互動的瀏覽和修改資料,生成動態的web內容,servlet運行於支援Java的應用伺服器中。
servlet是可以單例多執行緒,多個使用者在頁面進行請求的時候,實際只有一個Servlet物件,因為這些操作都是統一的,沒有必要生產多個物件造成資源浪費。具體可以瞭解一下單例模式的相關知識。
Serlvet的生命週期
首先看一下我們自定義的MySerlvet的繼承關係圖 再看一下Servlet介面中定義的方法,這裡實際是定義了servlet的宣告週期
package javax.servlet; import java.io.IOException; public interface Servlet { //初始化方法 void init(ServletConfig var1) throws ServletException; ServletConfig getServletConfig(); //執行方法 void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException; String getServletInfo(); //銷燬的方法 void destroy(); }
執行的過程大致如下:
- servlet啟動時,開始載入servet,生命週期開始,看一下原始碼,兩個被繼承的類在被繼承的時候,都會載入相關的靜態資源,所以自定義的類一旦被建立,就會在編譯器自動載入靜態資源。
public abstract class HttpServlet extends GenericServlet implements Serializable { private static final String METHOD_DELETE = "DELETE"; private static final String METHOD_HEAD = "HEAD"; private static final String METHOD_GET = "GET"; private static final String METHOD_OPTIONS = "OPTIONS"; private static final String METHOD_POST = "POST"; private static final String METHOD_PUT = "PUT"; private static final String METHOD_TRACE = "TRACE"; private static final String HEADER_IFMODSINCE = "If-Modified-Since"; private static final String HEADER_LASTMOD = "Last-Modified"; private static final String LSTRING_FILE = "javax.servlet.http.LocalStrings"; //靜態資源在編譯器就會被載入 private static ResourceBundle lStrings = ResourceBundle.getBundle("javax.servlet.http.LocalStrings"); // GenericServlet類 public abstract class GenericServlet implements Servlet, ServletConfig, Serializable { private static final String LSTRING_FILE = "javax.servlet.LocalStrings"; private static ResourceBundle lStrings = ResourceBundle.getBundle("javax.servlet.LocalStrings"); private transient ServletConfig config;
- servlet被伺服器例項化後,容器執行init()方法,我們可以對init()方法進行自己的實現。 **在一個Servlet的生命週期中,init方法只會被執行一次,**之後無論使用者執行多少次請求,都不會在呼叫該方法。 關於init方法的執行時機,有兩種方式可選,一般的是在伺服器啟動後第一個使用者請求改Servlet是呼叫,你也可以設定該Servlet在伺服器啟動後自動執行。 init方法負責簡單的建立或者載入一些資料,這些資料將用於該Servlet的整個生命週期中。
public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
...................
初始化方法
public void init() throws ServletException {
}
....................
}
- 請求到達時執行其service()方法,service方法自動派遣執行對應的doGet()或者doPost()方法, 每一次請求伺服器都會開啟一個新的執行緒並執行一次service方法。
public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
...................
//在這裡定義抽象的service()方法
public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
....................
//httpServlet類
public abstract class HttpServlet extends GenericServlet implements Serializable {
................
//service方法做了一系列的方法判斷,按照子類的相關資訊給出對應的類
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
long lastModified;
if (method.equals("GET")) {
lastModified = this.getLastModified(req);
if (lastModified == -1L) {
this.doGet(req, resp);
} else {
long ifModifiedSince = req.getDateHeader("If-Modified-Since");
if (ifModifiedSince < lastModified) {
this.maybeSetLastModified(resp, lastModified);
this.doGet(req, resp);
} else {
resp.setStatus(304);
}
}
} else if (method.equals("HEAD")) {
lastModified = this.getLastModified(req);
this.maybeSetLastModified(resp, lastModified);
this.doHead(req, resp);
} else if (method.equals("POST")) {
this.doPost(req, resp);
} else if (method.equals("PUT")) {
this.doPut(req, resp);
} else if (method.equals("DELETE")) {
this.doDelete(req, resp);
} else if (method.equals("OPTIONS")) {
this.doOptions(req, resp);
} else if (method.equals("TRACE")) {
this.doTrace(req, resp);
} else {
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[]{method};
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(501, errMsg);
}
}
...................
}
- 當伺服器伺服器決定將其例項銷燬的時候,會呼叫destroy()方法,這個方法和init()方法的實現位置和型別一樣,父類中定義了空方法,可以自己重寫。該方法在整個生命週期中,也是隻會被呼叫一次,在Servlet物件被銷燬是呼叫,在servlet中,我們可以做一些資源的釋放等操作,執行destory()方法之後的servlet物件,會等待jvm虛擬機器的垃圾回收機制擇時回收。
public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
...................
銷燬的方法
public void destroy() throws ServletException {
}
....................
}