建立一個Servlet類最直接的方式是實現javax.servlet.Servlet接口,Servlet接口的定義以下,其中定義了5個方法,Servlet的生命週期就是經過這幾個方法體現的:java
1 public interface Servlet { 2 public void init(ServletConfig config) throws ServletException; 3 4 public ServletConfig getServletConfig(); 5 6 public void service(ServletRequest req, ServletResponse res) 7 throws ServletException, IOException; 8 9 public String getServletInfo(); 10 11 public void destroy(); 12 }
1 . 加載和實例化web
首先定義一個DemoServlet實現Servlet接口,覆寫接口中的方法,分別打印各自的方法名,在無參構造方法中也打印一句話:數據庫
1 public class DemoServlet implements Servlet { 2 3 public DemoServlet() { 4 System.out.println("constructor…"); 5 } 6 7 @Override 8 public void destroy() { 9 System.out.println("DemoServlet.destroy()"); 10 } 11 12 @Override 13 public ServletConfig getServletConfig() { 14 System.out.println("DemoServlet.getServletConfig()"); 15 return null; 16 } 17 18 @Override 19 public String getServletInfo() { 20 System.out.println("DemoServlet.getServletInfo()"); 21 return null; 22 } 23 24 @Override 25 public void init(ServletConfig config) throws ServletException { 26 System.out.println("DemoServlet.init()"); 27 } 28 29 @Override 30 public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { 31 System.out.println("DemoServlet.service()"); 32 } 33 34 }
Servlet要被容器所管理,須要在web.xml中進行配置:服務器
1 <servlet> 2 <servlet-name>demo</servlet-name> 3 <servlet-class>servlet.DemoServlet</servlet-classs> 4 </servlet> 5 <servlet-mapping> 6 <servlet-name>demo</servlet-name> 7 <url-pattern>/demo</url-pattern> 8 </servlet-mapping>
啓動服務器,經過「http://localhost:8080/${contextpath}/demo」請求該Servlet,控制檯打印輸出以下:app
刷新頁面,再次請求該Servlet,控制檯打印以下,能夠看到,第二次請求只執行了service(ServletRequest req, ServletResponse res)方法:ide
當服務器接收到請求時,會經過web.xml中的配置尋找匹配的Servlet,找不到則報404錯誤;找到以後,根據配置的Servlet類的全限定名查找服務器中是否已經存在該Servlet類的實例,若存在則直接使用它來處理本次請求(上面的第二次請求,該Servlet實例已經存在,直接調用該實例的service(ServletRequest req, ServletResponse res)方法。);若不存在,則根據全限定名經過反射建立實例(調用公共無參的構造方法)。從這裏能夠看出,若沒有提供可訪問的無參構造方法,會報錯:post
1 //提供有參構造方法,覆蓋了默認的無參構造方法 2 public DemoServlet(String s) { 3 System.out.println("constructor…"); 4 }
服務器經過反射調用Class.newInstance()方法建立實例,找不到可訪問的無參構造方法,天然會報錯。url
2 . 初始化spa
從上面能夠看到,在第一次請求,建立Servlet實例的時候,調用了init(ServletConfig config)方法完成初始化。初始化只會在建立實例的時候進行,之後的請求不會再進行初始化,直接調用service()方法處理請求。服務器在進行Servlet初始化的時候,會首先準備一個ServletConfig對象,經過該對象能夠從應用程序的配置信息中獲取初始化的參數信息;數據庫鏈接的創建等任務一般也是在初始化階段完成。3d
ServletConfig接口中定義了4個方法,用來獲取初始化參數信息:
1 public interface ServletConfig { 2 //獲取Servlet的名字,即在web.xml中<servlet-name>demo</servlet-name>節點配置的信息 3 public String getServletName(); 4 5 //獲取Servlet上下文對象 6 public ServletContext getServletContext(); 7 8 //根據參數名獲取初始化參數值 9 public String getInitParameter(String name); 10 11 //獲取全部初始化參數名 12 public Enumeration<String> getInitParameterNames(); 13 }
初始化參數能夠在web.xml中配置:
1 <servlet> 2 <servlet-name>demo</servlet-name> 3 <servlet-class>servlet.DemoServlet</servlet-class> 4 <init-param> 5 <param-name>username</param-name> 6 <param-value>admin</param-value> 7 </init-param> 8 </servlet> 9 <servlet-mapping> 10 <servlet-name>demo</servlet-name> 11 <url-pattern>/demo</url-pattern> 12 </servlet-mapping>
注意:若是在web.xml中配置了<load-on-startup>1</load-on-startup>,該Servlet會在服務器啓動的時候就完成實例的建立和初始化,而不是在第一次請求的時候:
1 <servlet> 2 <servlet-name>demo</servlet-name> 3 <servlet-class>servlet.DemoServlet</servlet-class> 4 <load-on-startup>1</load-on-startup> 5 </servlet> 6 <servlet-mapping> 7 <servlet-name>demo</servlet-name> 8 <url-pattern>/demo</url-pattern> 9 </servlet-mapping>
3 . 處理請求
服務器調用service(ServletRequest req, ServletResponse res)方法來處理請求。處理請求以前,init()方法必須成功執行。服務器在調用service(ServletRequest req, ServletResponse res)方法以前,已經準備好了ServletRequest對象和ServletResponse對象,並做爲參數傳給service(ServletRequest req, ServletResponse res)方法。
ServletRequest接口和ServletResponse接口中定義了用來處理請求和響應的相關方法:
4 . 銷燬
當容器檢測到一個Servlet實例應該從服務中被移除的時候,容器就會調用實例的destroy()方法,以便讓該實例能夠釋放它所使用的資源,保存數據到持久存儲設備中。當須要釋放內存或者容器關閉時,容器就會調用Servlet實例的destroy()方法。在destroy()方法調用以後,容器會釋放這個Servlet實例,該實例隨後會被Java的垃圾收集器所回收。若是再次須要這個Servlet處理請求,Servlet容器會建立一個新的Servlet實例。
destroy()方法跟init()方法同樣,在Servlet的生命週期中只會被執行一次,但destroy()方法不會老是被執行,如服務器被異常終止時,destroy()方法就不能被執行。