Java中的Listener监听器

来源:互联网 发布:软件版权声明 编辑:程序博客网 时间:2024/05/20 11:23

一.Servlet监听器的概念

监听器Listener就是在application,session,request三个对象创建、销毁或者往其中添加修改删除属性时自动执行代码的功能组件。

Listener是Servlet的监听器,可以监听客户端的请求和服务端的操作等。

二.监听器的基本使用

创建步骤:

1、创建一个实现监听器接口的类

2、配置web.xml文件,注册监听器

<listener>    <listener-class>完整类名</listener-class></listener>

监听器的启动顺序:按照web.xml的配置顺序来启动

加载顺序:监听器>过滤器>Servlet

Listener配置信息必须在Filter和Servlet配置之前,Listener的初始化(ServletContentListener初始化)比Servlet和Filter都优先,而销毁比Servlet和Filter都慢。

三.Listener的分类与使用

3.1 按照监听的对象划分

1.ServletContext

用于监听应用程序环境对象(ServletContext)的事件监听器,实现ServletContextListener、ServletContextAttributeListener接口

ServletContextListener:用于对Servlet整个上下文进行监听(创建、销毁)。

public void contextInitialized(ServletContextEvent sce);//上下文初始化public void contextDestroyed(ServletContextEvent sce);//上下文销毁public ServletContext getServletContext();//ServletContextEvent事件:取得一个ServletContext(application)对象

ServletContextAttributeListener:对Servlet上下文属性的监听(增删改属性)。

public void attributeAdded(ServletContextAttributeEvent scab);//增加属性public void attributeRemoved(ServletContextAttributeEvent scab);//属性删除public void attributeRepalced(ServletContextAttributeEvent scab);//属性替换(第二次设置同一属性)//ServletContextAttributeEvent事件:能取得设置属性的名称与内容public String getName();//得到属性名称public Object getValue();//取得属性的值

2.HttpSeesion

用于监听用户会话对象(HttpSeesion)的事件监听器,实现HttpSessionListener、HttpSessionAttributeListener接口
Session属于http协议下的内容,接口位于javax.servlet.http.*包下。

HttpSessionListener接口:对Session的整体状态的监听。

public void sessionCreated(HttpSessionEvent se);//session创建public void sessionDestroyed(HttpSessionEvent se);//session销毁//HttpSessionEvent事件:public HttpSession getSession();//取得当前操作的session

HttpSessionAttributeListener接口:对session的属性监听。

public void attributeAdded(HttpSessionBindingEvent se);//增加属性public void attributeRemoved(HttpSessionBindingEvent se);//删除属性public void attributeReplaced(HttpSessionBindingEvent se);//替换属性//HttpSessionBindingEvent事件:public String getName();//取得属性的名称public Object getValue();//取得属性的值public HttpSession getSession();//取得当前的session

session的销毁有两种情况:

<!--1.session超时,web.xml配置:--><session-config>    <session-timeout>120</session-timeout><!--session120分钟后超时销毁--></session-config>  //2.手工使session失效public void invalidate();//使session失效方法。session.invalidate();

3.ServletRequest

用于监听请求消息对象(ServletRequest)的事件监听器,实现ServletRequestListener、ServletRequestAttributeListener接口

ServletRequestListener:用于对Request请求进行监听(创建、销毁)。

public void requestInitialized(ServletRequestEvent sre);//request初始化public void requestDestroyed(ServletRequestEvent sre);//request销毁//ServletRequestEvent事件:public ServletRequest getServletRequest();//取得一个ServletRequest对象public ServletContext getServletContext();//取得一个ServletContext(application)对象

ServletRequestAttributeListener:对Request属性的监听(增删改属性)。

public void attributeAdded(ServletRequestAttributeEvent srae);//增加属性public void attributeRemoved(ServletRequestAttributeEvent srae);//属性删除public void attributeReplaced(ServletRequestAttributeEvent srae);//属性替换(第二次设置同一属性)//ServletRequestAttributeEvent事件:能取得设置属性的名称与内容public String getName();//得到属性名称public Object getValue();//取得属性的值

3.2按照监听事件划分

1、监听域对象自身的创建和销毁的事件监听器

根据监听对象不同分别实现ServletContextListener、HttpSessionListener、ServletRequestListener接口。

①ServletContext的创建和销毁:contextInitialized方法和contextDestroyed方法

public void contextInitialized(ServletContextEvent sce)//ServletContext创建时调用public void contextDestroyed(ServletContextEvent sce)//ServletContext销毁时调用

主要用途:作为定时器、加载全局属性对象、创建全局数据库连接、加载缓存信息等

实例:

在web.xml中可以配置项目初始化信息,在contextInitialized方法中进行启动

<context-param>    <param-name>属性名</param-name>    <param-value>属性值</param-value></context-param>
public class MyFirstListener implements ServletContextListener{    public void contextInitialized(ServletContextEvent sce){        //获取web.xml中配置的属性        String value=sce.getServletContext().getInitParameter("属性名");        System.out.println(value);  }    public void contextDestroyed(ServletContextEvent sce){        //关闭时操作  }}

②HttpSession的创建和销毁:sessionCreated和sessionDestroyed方法

public void sessionCreated(HttpSessionEvent se)//session创建时调用public void sessionDestroyed(HttpSessionEvent se)//session销毁时调用

主要用途:统计在线人数、记录访问日志等

<!--web.xml配置session超时参数,单位:分,session超时的时间并不是精确的--><session-config>    <session-timeout>10</session-timeout></session-config>

③ServletRequest的创建和销毁:requestInitialized和requestDestroyed方法

public void requestInitialized(ServletRequestEvent sre)//request创建时调用public void requestDestroyed(ServletRequestEvent sre)//request销毁时调用

主要用途:读取request参数,记录访问历史

实例:

public class MySRequestListener implements SevletRequestListener{    public void requestInitialized(ServletRequestEvent sre){        String value=sre.getServletRequest().getParameter("key");//获取request中的参数        System.out.println(value);    }    public void requestDestroyed(ServletRequestEvent sre){          System.out.println("request destroyed");    }}   

2、监听域对象中的属性的增加和删除的事件监听器

  根据监听对象不同分别实现ServletContextAttributeListener、HttpSessionAttributeListener、ServletRequestAttributeListener接口。

  实现方法:attributeAdded、attributeRemoved、attributeReplaced


3、监听绑定到HttpSeesion域中的某个对象的状态的事件监听器(创建普通JavaBean)

  HttpSession中的对象状态:绑定→解除绑定;钝化→活化

  实现接口及方法:HttpSessionBindingListener接口(valueBound和valueUnbound方法)、HttpSessionActivationListener接口(sessionWillPassivate和sessionDidActivate方法)

四.Listener应用实例

1.利用HttpSessionListener统计最多在线用户人数

import java.text.DateFormat;import java.text.SimpleDateFormat;import java.util.Date;import javax.servlet.ServletContext;import javax.servlet.http.HttpSessionEvent;import javax.servlet.http.HttpSessionListener;public class HttpSessionListenerImpl implements HttpSessionListener {    public void sessionCreated(HttpSessionEvent event) {        ServletContext app = event.getSession().getServletContext();        int count = Integer.parseInt(app.getAttribute("onLineCount").toString());        count++;        app.setAttribute("onLineCount", count);        int maxOnLineCount = Integer.parseInt(app.getAttribute("maxOnLineCount").toString());        if (count > maxOnLineCount) {            //记录最多人数是多少            app.setAttribute("maxOnLineCount", count);            DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");            //记录在那个时刻达到上限            app.setAttribute("date", df.format(new Date()));        }    }    //session注销、超时时候调用,停止tomcat不会调用    public void sessionDestroyed(HttpSessionEvent event) {        ServletContext app = event.getSession().getServletContext();        int count = Integer.parseInt(app.getAttribute("onLineCount").toString());        count--;        app.setAttribute("onLineCount", count);        }}

2.Spring使用ContextLoaderListener加载ApplicationContext配置信息

ContextLoaderListener的作用就是启动Web容器时,自动装配ApplicationContext的配置信息。因为它实现了ServletContextListener这个接口,在web.xml配置这个监听器,启动容器时,就会默认执行它实现的方法。

ContextLoaderListener如何查找applicationContext.xml的配置位置以及配置多个xml:
如果在web.xml中不写任何参数配置信息,默认的路径是”/WEB-INF/applicationContext.xml”,在WEB-INF目录下创建的xml文件的名称必须是applicationContext.xml(在MyEclipse中把xml文件放置在src目录下)。
如果是要自定义文件名可以在web.xml里加入contextConfigLocation这个context参数。

<context-param>    <param-name>contextConfigLocation</param-name>    <param-value>classpath:spring/applicationContext-*.xml</param-value><!-- 采用的是通配符方式,查找WEB-INF/spring目录下xml文件。如有多个xml文件,以“,”分隔。 --></context-param><listener>    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>

3.Spring使用Log4jConfigListener配置Log4j日志

Spring使用Log4jConfigListener的好处:

动态的改变记录级别和策略,不需要重启Web应用。

把log文件定在 /WEB-INF/logs/ 而不需要写绝对路径。因为系统把web目录的路径压入一个叫webapp.root的系统变量。这样写log文件路径时不用写绝对路径了。

可以把log4j.properties和其他properties一起放在/WEB-INF/ ,而不是Class-Path。

设置log4jRefreshInterval时间,开一条watchdog线程每隔段时间扫描一下配置文件的变化。

<context-param>    <param-name>webAppRootKey</param-name>    <param-value>project.root</param-value><!-- 用于定位log文件输出位置在web应用根目录下,log4j配置文件中写输出位置:log4j.appender.FILE.File=${project.root}/logs/project.log --></context-param><context-param>    <param-name>log4jConfigLocation</param-name>    <param-value>classpath:log4j.properties</param-value><!-- 载入log4j配置文件 --></context-param><context-param>    <param-name>log4jRefreshInterval</param-name>    <param-value>60000</param-value><!--Spring刷新Log4j配置文件的间隔60秒,单位为millisecond--></context-param><listener>    <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class></listener>

4.Spring使用IntrospectorCleanupListener清理缓存

这个监听器的作用是在web应用关闭时刷新JDK的JavaBeans的Introspector缓存,以确保Web应用程序的类加载器以及其加载的类正确的释放资源。

如果JavaBeans的Introspector已被用来分析应用程序类,系统级的Introspector缓存将持有这些类的一个硬引用。因此,这些类和Web应用程序的类加载器在Web应用程序关闭时将不会被垃圾收集器回收!而IntrospectorCleanupListener则会对其进行适当的清理,已使其能够被垃圾收集器回收。

唯一能够清理Introspector的方法是刷新整个Introspector缓存,没有其他办法来确切指定应用程序所引用的类。这将删除所有其他应用程序在服务器的缓存的Introspector结果。

在使用Spring内部的bean机制时,不需要使用此监听器,因为Spring自己的introspection results cache将会立即刷新被分析过的JavaBeans Introspector cache,而仅仅会在应用程序自己的ClassLoader里面持有一个cache。虽然Spring本身不产生泄漏,注意,即使在Spring框架的类本身驻留在一个“共同”类加载器(如系统的ClassLoader)的情况下,也仍然应该使用IntrospectorCleanupListener。在这种情况下,这个IntrospectorCleanupListener将会妥善清理Spring的introspection cache。

应用程序类,几乎不需要直接使用JavaBeans Introspector,所以,通常都不是Introspector resource造成内存泄露。相反,许多库和框架,不清理Introspector,例如: Struts和Quartz。

需要注意的是一个简单Introspector泄漏将会导致整个Web应用程序的类加载器不会被回收!这样做的结果,将会是在web应用程序关闭时,该应用程序所有的静态类资源(比如:单实例对象)都没有得到释放。而导致内存泄露的根本原因其实并不是这些未被回收的类!

注意:IntrospectorCleanupListener应该注册为web.xml中的第一个Listener,在任何其他Listener之前注册,比如在Spring’s ContextLoaderListener注册之前,才能确保IntrospectorCleanupListener在Web应用的生命周期的适当时机生效。

<!-- memory clean --><listener>    <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class></listener>

[转载自] (http://www.cnblogs.com/coderland/p/5902874.html)
[转载自] (http://www.cnblogs.com/sherryueda/p/4273169.html)

0 0