Servlet相關接口和Servlet的生命周期


創建一個Servlet類最直接的方式是實現javax.servlet.Servlet接口,Servlet接口的定義如下,其中定義了5個方法,Servlet的生命周期就是通過這幾個方法體現的:

 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 . 加載和實例化

首先定義一個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,控制台打印輸出如下:

刷新頁面,再次請求該Servlet,控制台打印如下,可以看到,第二次請求只執行了service(ServletRequest req, ServletResponse res)方法:

當服務器接收到請求時,會通過web.xml中的配置尋找匹配的Servlet,找不到則報404錯誤;找到之后,根據配置的Servlet類的全限定名查找服務器中是否已經存在該Servlet類的實例,若存在則直接使用它來處理本次請求(上面的第二次請求,該Servlet實例已經存在,直接調用該實例的service(ServletRequest req, ServletResponse res)方法。);若不存在,則根據全限定名通過反射創建實例(調用公共無參的構造方法)。從這里可以看出,若沒有提供可訪問的無參構造方法,會報錯:

1 //提供有參構造方法,覆蓋了默認的無參構造方法                     
2 public DemoServlet(String s) {              
3     System.out.println("constructor…");     
4 }                                           

 

服務器通過反射調用Class.newInstance()方法創建實例,找不到可訪問的無參構造方法,自然會報錯。

2 . 初始化

從上面可以看到,在第一次請求,創建Servlet實例的時候,調用了init(ServletConfig config)方法完成初始化。初始化只會在創建實例的時候進行,以后的請求不會再進行初始化,直接調用service()方法處理請求。服務器在進行Servlet初始化的時候,會首先准備一個ServletConfig對象,通過該對象可以從應用程序的配置信息中獲取初始化的參數信息;數據庫連接的建立等任務通常也是在初始化階段完成。

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()方法就不能被執行。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM