listener监听器

前言:以前写了一篇关于Filter的文章:http://tianweili.github.io/blog/2015/01/26/java-filter/,如今再来一篇Listener的,Filter和Listener在项目中是常常用到的,巧妙的使用能够达到事半功倍的效果。故把二者的用法总结一下。html

  原文连接:http://tianweili.github.io/blog/2015/01/27/java-listener/java

一、Listener的定义与做用git

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

  Listener是Servlet的监听器,能够监听客户端的请求,服务端的操做等。web

二、Listener的分类与使用spring

  主要有如下三类:缓存

  一、ServletContext监听tomcat

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

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

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

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

  二、Session监听

  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的销毁有两种状况:

  一、session超时,web.xml配置:

<session-config> <session-timeout>120</session-timeout><!--session120分钟后超时销毁--> </session-config>

  二、手工使session失效

public void invalidate();//使session失效方法。session.invalidate();

  三、Request监听

  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();//取得属性的值
复制代码

  四、在web.xml中配置

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

<listener> <listener-class>com.listener.class</listener-class> </listener>

三、Listener应用实例

  一、利用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); } }
复制代码

  二、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>
复制代码

  三、Spring使用Log4jConfigListener配置Log4j日志

  Spring使用Log4jConfigListener的好处:

  1. 动态的改变记录级别和策略,不须要重启Web应用。
  2. 把log文件定在 /WEB-INF/logs/ 而不须要写绝对路径。由于系统把web目录的路径压入一个叫webapp.root的系统变量。这样写log文件路径时不用写绝对路径了。
  3. 能够把log4j.properties和其余properties一块儿放在/WEB-INF/ ,而不是Class-Path。
  4. 设置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>
复制代码

  四、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://tianweili.github.io/blog/2015/01/27/java-listener/

 
 
分类: 1. Java
相关文章
相关标签/搜索