• 监听器


    1、Listener的定义与作用

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

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

    2、Listener的分类与使用

      主要有以下三类:

      1、ServletContext监听

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

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

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

      2、手工使session失效

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

      3、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();//取得属性的值

      4、在web.xml中配置

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

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

    3、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的好处:

    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>

      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应用的生命周期适当时机生效。

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

    <!-- memory clean -->
    <listener>
        <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
    </listener>
  • 相关阅读:
    JavaScript中的闭包
    SQL 备忘
    SqlServer 2005 升级至SP2过程中出现"身份验证"无法通过的问题
    unable to start debugging on the web server iis does not list an application that matches the launched url
    Freebsd 编译内核
    Freebsd 6.2中关于无线网络的设定
    【Oracle】ORA01219
    【Linux】Windows到Linux的文件复制
    【Web】jar命令行生成jar包
    【Linux】CIFS挂载Windows共享
  • 原文地址:https://www.cnblogs.com/cdeelen/p/11290977.html
Copyright © 2020-2023  润新知