转自:https://blog.csdn.net/zhaozheng7758/article/details/6103700

在 Servlet API 中有一个 ServletContextListener 接口,它能够监听 ServletContext 对象的生命周期,实际上就是监听 Web 应用的生命周期。

当Servlet 容器启动或终止Web 应用时,会触发ServletContextEvent 事件,该事件由ServletContextListener 来处理。在 ServletContextListener 接口中定义了处理ServletContextEvent 事件的两个方法。

Java代码  收藏代码
  1. /** 
  2.  * 当Servlet 容器启动Web 应用时调用该方法。在调用完该方法之后,容器再对Filter 初始化, 
  3.  * 并且对那些在Web 应用启动时就需要被初始化的Servlet 进行初始化。 
  4.  */  
  5. contextInitialized(ServletContextEvent sce)   
  6.   
  7.   
  8. /** 
  9.  * 当Servlet 容器终止Web 应用时调用该方法。在调用该方法之前,容器会先销毁所有的Servlet 和Filter 过滤器。 
  10.  */  
  11. contextDestroyed(ServletContextEvent sce)  
 

 下面通过两个具体的例子来介绍 ServletContextListener 的用法。

 

例一:在服务启动时,将数据库中的数据加载进内存,并将其赋值给一个属性名,其它的 Servlet 就可以通过 getAttribute 进行属性值的访问。

 

有如下两个步骤:

 

1 : ServletContext 对象是一个为整个 web 应用提供共享的内存,任何请求都可以访问里面的内容  

 

2 :如何实现在服务启动的时候就动态的加入到里面的内容:我们需要做的有:  

1 ) 实现 servletContextListerner 接口 并将要共享的通过 setAttribute ( name,data )方法提交到内存中去   ;

2 )应用项目通过 getAttribute(name) 将数据取到 。

 

Java代码  收藏代码
 1     public class ServletContextLTest implements ServletContextListener{   
 2       
 3         // 实现其中的销毁函数  
 4           
 5         public void contextDestroyed(ServletContextEvent sce) {   
 6       
 7             System.out.println("this is last destroyeed");      
 8       
 9         }   
10       
11         // 实现其中的初始化函数,当有事件发生时即触发  
12       
13         public void contextInitialized(ServletContextEvent sce) {   
14       
15             ServletContext sct=sce.getServletContext();   
16       
17             Map<Integer,String> depts=new HashMap<Integer,String>();   
18       
19             Connection connection=null;   
20       
21             PreparedStatement pstm=null;   
22       
23             ResultSet rs=null;   
24       
25                
26       
27             try{   
28       
29                 connection=ConnectTool.getConnection();   
30       
31                 String sql="select deptNo,dname from dept";   
32       
33                 pstm=connection.prepareStatement(sql);   
34       
35                 rs=pstm.executeQuery();   
36       
37                 while(rs.next()){   
38       
39                     depts.put(rs.getInt(1), rs.getString(2));   
40       
41                 }   
42       
43                 // 将所取到的值存放到一个属性键值对中  
44       
45                 sct.setAttribute("dept", depts);   
46       
47                 System.out.println("======listener test is beginning=========");   
48       
49             }catch(Exception e){   
50       
51                 e.printStackTrace();   
52       
53             }finally{   
54       
55                 ConnectTool.releasersc(rs, pstm, connection);   
56       
57             }   
58       
59         }   
60       
61     }  

 

 

 1 public class ServletContextLTest implements ServletContextListener{   
 2 
 3         // 实现其中的销毁函数  
 4         public void contextDestroyed(ServletContextEvent sce) {   
 5             System.out.println("this is last destroyeed");      
 6         }   
 7         // 实现其中的初始化函数,当有事件发生时即触发  
 8         public void contextInitialized(ServletContextEvent sce) {   
 9             ServletContext sct=sce.getServletContext();   
10             Map<Integer,String> depts=new HashMap<Integer,String>();   
11             Connection connection=null;   
12             PreparedStatement pstm=null;   
13             ResultSet rs=null;   
14             try{   
15                 connection=ConnectTool.getConnection();   
16                 String sql="select deptNo,dname from dept";   
17                 pstm=connection.prepareStatement(sql);   
18                 rs=pstm.executeQuery();   
19                 while(rs.next()){   
20                     depts.put(rs.getInt(1), rs.getString(2));   
21                 }   
22                 // 将所取到的值存放到一个属性键值对中  
23                 sct.setAttribute("dept", depts);   
24                 System.out.println("======listener test is beginning=========");   
25             }catch(Exception e){   
26                 e.printStackTrace();   
27             }finally{   
28                 ConnectTool.releasersc(rs, pstm, connection);   
29             }   
30         }   
31     }  

 

 

在完成上述编码后,仍需在 web.xml 中进行如下配置,以使得该监听器可以起作用。

 

Xml代码  收藏代码
 1 <listener> 2
3 <listener-class>ServletContextTest.ServletContextLTest</listener-class>
4 5 </listener>  

 

在完成上述配置后, web 服务器在启动时,会直接加载该监听器,通过以下的应用程序就可以进行数据的访问。

 

Java代码  收藏代码
 1     public class CreateEmployee extends HttpServlet{   
 2       
 3         @Override   
 4       
 5         protected void service(HttpServletRequest request, HttpServletResponse response)   
 6       
 7                 throws ServletException, IOException {   
 8       
 9             ServletContext sct=getServletConfig().getServletContext();   
10       
11             // 从上下文环境中通过属性名获取属性值  
12       
13             Map<Integer,String> dept=(Map<Integer,String>)sct.getAttribute("dept");   
14       
15             Set<Integer> key=dept.keySet();   
16       
17             response.setContentType("text/html;charset=utf-8");   
18       
19             PrintWriter out=response.getWriter();   
20       
21             out.println("<html>");   
22       
23             out.println("<body>");   
24       
25             out.println("<form action='/register' action='post'>");   
26       
27             out.println("<table alignb='center'>");   
28       
29             out.println("<tr>");   
30       
31             out.println("<td>");   
32       
33             out.println("username:");   
34       
35             out.println("</td>");   
36       
37             out.println("<td>");   
38       
39             out.println("<input type='text' name='username'");   
40       
41             out.println("</tr>");   
42       
43             out.println("<tr>");   
44       
45             out.println("<td>");   
46       
47             out.println("city:");   
48       
49             out.println("</td>");   
50       
51             out.println("<td>");   
52       
53             out.println("<select name='dept'");   
54       
55             for(Integer i:key){   
56       
57                 out.println("<option value='"+i+"'>"+dept.get(i)+"</option>");   
58       
59             }   
60       
61             out.println("</select>");   
62       
63             out.println("</td>");   
64       
65             out.println("<tr>");   
66       
67             out.println("</table>");   
68       
69             out.println("</form>");   
70       
71             out.println("</body>");   
72       
73             out.println("</html>");   
74       
75             out.flush();   
76       
77         }   
78       
79     }  

 

 1 public class CreateEmployee extends HttpServlet{   
 2 
 3         @Override   
 4         protected void service(HttpServletRequest request, HttpServletResponse response)   
 5                 throws ServletException, IOException {   
 6             ServletContext sct=getServletConfig().getServletContext();   
 7             // 从上下文环境中通过属性名获取属性值  
 8             Map<Integer,String> dept=(Map<Integer,String>)sct.getAttribute("dept");   
 9             Set<Integer> key=dept.keySet();   
10             response.setContentType("text/html;charset=utf-8");   
11             PrintWriter out=response.getWriter();   
12             out.println("<html>");   
13             out.println("<body>");   
14             out.println("<form action='/register' action='post'>");   
15             out.println("<table alignb='center'>");   
16             out.println("<tr>");   
17             out.println("<td>");   
18             out.println("username:");   
19             out.println("</td>");   
20             out.println("<td>");   
21             out.println("<input type='text' name='username'");   
22             out.println("</tr>");   
23             out.println("<tr>");   
24             out.println("<td>");   
25             out.println("city:");   
26             out.println("</td>");   
27             out.println("<td>");   
28             out.println("<select name='dept'");   
29             for(Integer i:key){   
30                 out.println("<option value='"+i+"'>"+dept.get(i)+"</option>");   
31             }   
32             out.println("</select>");   
33             out.println("</td>");   
34             out.println("<tr>");   
35             out.println("</table>");   
36             out.println("</form>");   
37             out.println("</body>");   
38             out.println("</html>");   
39             out.flush();   
40         }   
41     }  

 

 

例二:书写一个类用于统计当Web 应用启动后,网页被客户端访问的次数。如果重新启动Web 应用,计数器不会重新从1 开始统计访问次数,而是从上次统计的结果上进行累加。

 

在实际应用中,往往需要统计自Web 应用被发布后网页被客户端访问的次数,这就要求当Web 应用被终止时,计数器的数值被永久存储在一个文件中或者数据库中,等到Web 应用重新启动时,先从文件或数据库中读取计数器的初始值,然后在此基础上继续计数。

 

向文件中写入或读取计数器的数值的功能可以由自定义的 MyServletContextListener 类来完成,它具有以下功能:

 

1 、在 Web 应用启动时从文件中读取计数器的数值,并把表示计数器的 Counter 对象存放到 Web应用范围内。存放计数器的文件的路径为helloapp/count/count.txt 。

2 、在Web 应用终止时把Web 应用范围内的计数器的数值保存到count.txt 文件中。

Java代码  收藏代码
 1     public class MyServletContextListener implements ServletContextListener{  
 2       
 3       public void contextInitialized(ServletContextEvent sce){  
 4       
 5         System.out.println("helloapp application is Initialized.");  
 6       
 7         // 获取 ServletContext 对象  
 8       
 9         ServletContext context=sce.getServletContext();  
10       
11         try{  
12       
13            // 从文件中读取计数器的数值  
14       
15            BufferedReader reader=new BufferedReader(  
16       
17                new InputStreamReader(context.  
18       
19                getResourceAsStream("/count/count.txt")));  
20       
21            int count=Integer.parseInt(reader.readLine());  
22       
23            reader.close();  
24       
25            // 创建计数器对象  
26       
27            Counter counter=new Counter(count);  
28       
29            // 把计数器对象保存到 Web 应用范围  
30       
31            context.setAttribute("counter",counter);  
32       
33            } catch(IOException e) {  
34       
35               e.printStackTrace();  
36       
37            }  
38       
39        }  
40       
41        public void contextDestroyed(ServletContextEvent sce){  
42       
43            System.out.println("helloapp application is Destroyed.");  
44       
45            // 获取 ServletContext 对象  
46       
47            ServletContext context=sce.getServletContext();  
48       
49            // 从 Web 应用范围获得计数器对象  
50       
51            Counter counter=(Counter)context.getAttribute("counter");  
52       
53            if(counter!=null){  
54       
55            try{  
56       
57               // 把计数器的数值写到 count.txt 文件中  
58       
59               String filepath=context.getRealPath("/count");  
60       
61               filepath=filepath+"/count.txt";  
62       
63               PrintWriter pw=new PrintWriter(filepath);  
64       
65               pw.println(counter.getCount());  
66       
67               pw.close();  
68       
69              } catch(IOException e) {  
70       
71                  e.printStackTrace();  
72       
73              }  
74       
75          }  
76       
77        }  
78       
79     }   

 

 

将用户自定义的 MyServletContextListener 监听器在 Servlet 容器进行注册, Servlet 容器会在启动或终止 Web 应用时,会调用该监听器的相关方法。在 web.xml 文件中, <listener> 元素用于向容器注册监听器:

Xml代码  收藏代码
 1 <listener> 2 <listener-class> ServletContextTest .MyServletContextListener<listener-class /> 3 </listener>  

 

通过上述两个例子,即可以非常清楚的了解到 ServletContextListener 接口的使用方法及技巧。

 

在Container 加载Web 应用程序时(例如启动 Container 之后),会呼叫contextInitialized() ,而当容器移除Web 应用程序时,会呼叫contextDestroyed () 方法。

 

通过 Tomcat 控制台的打印结果的先后顺序,会发现当 Web 应用启动时,Servlet 容器先调用contextInitialized() 方法,再调用lifeInit 的init() 方法;

当Web 应用终止时,Servlet 容器先调用lifeInit 的destroy() 方法,再调用contextDestroyed() 方法。

 

由此可见,在Web 应用的生命周期中,ServletContext 对象最早被创建,最晚被销毁。

 

原文地址:http://blog.csdn.net/zhaozheng7758/archive/2010/12/28/6103700.aspx


posted on 2017-10-24 16:13  Sharpest  阅读(4863)  评论(0编辑  收藏  举报