java Web 监听器Listener详解

简介

JavaWeb中的监听器是Servlet规范中定义的一种特殊类,它用于监听web应用程序中的ServletContext、HttpSession和 ServletRequest这三大域对象的创建、销毁事件以及监听这些域对象中的属性发生修改的事件。

监听器是一个专门用于对其他对象身上发生的事件或状态改变进行监听和相应处理的对象,当被监视的对象发生情况时,立即采取相应的行动。监听器其实就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法立即被执行。

相关概念

  事件源:即谁产生的事件
  事件对象:即产生了什么事件
  监听器:监听事件源的动作

监听对象

在Servlet规范中定义了多种类型的监听器(一共8个监听器),它们用于监听的事件源分别为ServletContext,HttpSession和ServletRequest这三个域对象。Servlet规范针对这三个对象上的操作,又把多种类型的监听器划分为三种类型:

1.域对象的生命周期监听:监听域对象自身的创建和销毁。这个监听器需要实现相应的监听器接口:ServletContextListener、HttpSessionListener、ServletRequestListener。

2.域对象的属性监听:监听域对象中属性的增加和删除。这个监听器需要实现的监听器接口为:ServletContextAttributeListener、HttpSessionAttributeListener、ServletRequestAttributeListener。

3.感知监听(都与HttpSession域对象有关):

  绑定和解绑:监听绑定到HttpSession域中的某个JavaBean对象的状态的监听器以及解绑。这个监听器需要实现的监听器接口:HttpSessionBindingListener。

  钝化和活化:监听JaveBean对象随HttpSession序列化到硬盘上(正常关闭服务器,session会钝化到硬盘上)以及从硬盘反序列化到内存中。这个监听器需要实现的监听器接口:HttpSessionActiveationListener、Serializable。

示例:

域对象的生命周期监听

监听request的创建和销毁:

public class MyRequestListener implements ServletRequestListener {

    //创建
    public void requestInitialized(ServletRequestEvent sre)  { 
        System.out.println("监听新的request对象被创建了...");
    }
    //销毁
    public void requestDestroyed(ServletRequestEvent sre)  { 
        System.out.println("监听request对象被销毁了...");
    }
    
}

监听session的创建和销毁:

public class MySessionListener implements HttpSessionListener {

    public void sessionCreated(HttpSessionEvent se)  { 
        // Event 事件: 通过事件对象可以获取被监听对象的引用
        HttpSession session = se.getSession();
        System.out.println(session.getId() + "对应的session被创建了**** **** ");
    }

    public void sessionDestroyed(HttpSessionEvent se)  { 
        HttpSession session = se.getSession();
        System.out.println(session.getId() + "对应的session被销毁了**** **** ");
    }
    
}

监听context的创建和销毁:

public class MyServletContextListner implements ServletContextListener {

    public void contextInitialized(ServletContextEvent sce)  { 
        System.out.println("--------------------------- 监听到项目被创建了....");
    }
    
    public void contextDestroyed(ServletContextEvent sce)  { 
        System.out.println("*********************** 监听到项目被销毁了....");
    }

}

域对象属性变化监听

以request为例:

public class MyRequestAttrChangeListener implements ServletRequestAttributeListener {

    public void attributeAdded(ServletRequestAttributeEvent srae) {
        // 属性 = 属性名 + 属性值
        // 1 获取属性名
        String name = srae.getName();
        // 2 获取属性值:
        // 2.1 获取事件源对象, 指request对象
        ServletRequest request = srae.getServletRequest();
        Object value = request.getAttribute(name);

        System.out.println("*****request 增加属性: " + name + " = " + value);
    }

    public void attributeReplaced(ServletRequestAttributeEvent srae) {
        // 1 获取属性名
        String name = srae.getName();
        // 2 获取属性值:
        // 2.1 获取事件源对象, 指request对象
        ServletRequest request = srae.getServletRequest();
        Object newValue = request.getAttribute(name);
        // 2.2 获取原来的值
        Object oldValue = srae.getValue();

        System.out.println("***** ***** *****request 修改属性 属性名: " + name);
        System.out.println("***** ***** *****request 修改属性 新的属性值: " + newValue);
        System.out.println("***** ***** *****request 修改属性 旧的属性值: " + oldValue);
    }

    public void attributeRemoved(ServletRequestAttributeEvent srae) {
        // 1 获取属性名
        String name = srae.getName();
        
        System.out.println("***** ***** *****request 删除属性 : " + name);
    }

}

感知监听

绑定和解绑:

public class User1 implements HttpSessionBindingListener {
    private int id;
    private String name;
    private int age;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User1 [id=" + id + ", name=" + name + ", age=" + age + "]";
    }

    @Override
    public void valueBound(HttpSessionBindingEvent event) {
        System.out.println(this + "感知自己被放到 session中------------------绑定");
    }

    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {
        System.out.println(this + "感知自己从 session中移除 -----------------解绑");
    }

}

 钝化和活化:

public class User2 implements HttpSessionActivationListener, Serializable {
    private String nickname;
    private String city;

    public String getNickname() {
        return nickname;
    }

    public void setNickname(String nickname) {
        this.nickname = nickname;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    @Override
    public String toString() {
        return "User2 [nickname=" + nickname + ", city=" + city + "]";
    }

    @Override
    public void sessionDidActivate(HttpSessionEvent se) {
        System.out.println(this + "随session活化到内存中 .........");
    }
    
    @Override
    public void sessionWillPassivate(HttpSessionEvent se) {
        System.out.println(this + "随session钝化到硬盘上..........");
    }


}

 由于idea的运行机制问题(重启tomcat的话,会删除tomcat文件夹内的work文件夹再重新创建(同时也就删除了文件夹内的序列化到硬盘上的SESSIONS.SAR文件)),上面这个示例不能被活化到内存中。

原文地址:https://www.cnblogs.com/blazeZzz/p/9247343.html