zoukankan      html  css  js  c++  java
  • 监听器入门看这篇就够了

    什么是监听器

    监听器就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法将立即被执行。。

    为什么我们要使用监听器?

    监听器可以用来检测网站的在线人数,统计网站的访问量等等

    监听器组件

    监听器涉及三个组件:事件源,事件对象,事件监听器

    当事件源发生某个动作的时候,它会调用事件监听器的方法,并在调用事件监听器方法的时候把事件对象传递进去。

    我们在监听器中就可以通过事件对象获取得到事件源,从而对事件源进行操作!

    这里写图片描述


    模拟监听器

    既然上面已经说了监听器的概念了,监听器涉及三个组件:事件源,事件对象,事件监听器。

    我们就写一个对象,被监听器监听

    监听器

    监听器定义为接口,监听的方法需要事件对象传递进来,从而在监听器上通过事件对象获取得到事件源,对事件源进行修改

    
    	/**
    	 * 事件监听器
    	 *
    	 * 监听Person事件源的eat和sleep方法
    	 */
    	interface PersonListener{
    	
    	    void doEat(Event event);
    	    void doSleep(Event event);
    	}
    
    

    事件源

    事件源是一个Person类,它有eat和sleep()方法。

    事件源需要注册监听器(即在事件源上关联监听器对象)

    如果触发了eat或sleep()方法的时候,会调用监听器的方法,并将事件对象传递进去

    
    
    	/**
    	 *
    	 * 事件源Person
    	 *
    	 * 事件源要提供方法注册监听器(即在事件源上关联监听器对象)
    	 */
    	
    	class Person {
    	
    	    //在成员变量定义一个监听器对象
    	    private PersonListener personListener ;
    	    
    	    //在事件源中定义两个方法
    	    public void Eat() {
    	        
    	        //当事件源调用了Eat方法时,应该触发监听器的方法,调用监听器的方法并把事件对象传递进去
    	        personListener.doEat(new Event(this));
    	    }
    	
    	    public void sleep() {
    	
    	        //当事件源调用了Eat方法时,应该触发监听器的方法,调用监听器的方法并把事件对象传递进去
    	        personListener.doSleep(new Event(this));
    	    }
    	
    	    //注册监听器,该类没有监听器对象啊,那么就传递进来吧。
    	    public void registerLister(PersonListener personListener) {
    	        this.personListener = personListener;
    	    }
    	
    	}
    
    
    

    事件对象

    事件对象封装了事件源。

    监听器可以从事件对象上获取得到事件源的对象(信息)

    
    
    
    	/**
    	 * 事件对象Even
    	 *
    	 * 事件对象封装了事件源
    	 *
    	 * 在监听器上能够通过事件对象获取得到事件源
    	 *
    	 *
    	 */
    	class Event{
    	    private Person person;
    	
    	    public Event() {
    	    }
    	
    	    public Event(Person person) {
    	        this.person = person;
    	    }
    	
    	    public Person getResource() {
    	        return person;
    	    }
    	
    	}
    
    

    测试

    
        public static void main(String[] args) {
    
            Person person = new Person();
    
            //注册监听器()
            person.registerLister(new PersonListener() {
                @Override
                public void doEat(Event event) {
                    Person person1 = event.getResource();
                    System.out.println(person1 + "正在吃饭呢!");
                }
    
                @Override
                public void doSleep(Event event) {
                    Person person1 = event.getResource();
                    System.out.println(person1 + "正在睡觉呢!");
                }
            });
    
    
            //当调用eat方法时,触发事件,将事件对象传递给监听器,最后监听器获得事件源,对事件源进行操作
            person.Eat();
        }
    
    
    

    这里写图片描述

    • 事件源:拥有事件
    • 监听器:监听事件源所拥有的事件(带事件对象参数的)
    • 事件对象:事件对象封装了事件源对象
      • 事件源要与监听器有关系,就得注册监听器【提供方法得到监听器对象】
      • 触发事件源的事件,实际会提交给监听器对象处理,并且把事件对象传递过去给监听器

    Servle监听器

    在Servlet规范中定义了多种类型的监听器,它们用于监听的事件源分别 ServletContext, HttpSession和ServletRequest这三个域对象

    和其它事件监听器略有不同的是,servlet监听器的注册不是直接注册在事件源上,而是由WEB容器负责注册,开发人员只需在web.xml文件中使用<listener>标签配置好监听器

    监听对象的创建和销毁

    HttpSessionListener、ServletContextListener、ServletRequestListener分别监控着Session、Context、Request对象的创建和销毁

    • HttpSessionListener(可以用来收集在线者信息)
    • ServletContextListener(可以获取web.xml里面的参数配置)
    • ServletRequestListener

    测试

    
    
    public class Listener1 implements ServletContextListener,
            HttpSessionListener, ServletRequestListener {
    
        // Public constructor is required by servlet spec
        public Listener1() {
        }
        
        public void contextInitialized(ServletContextEvent sce) {
            System.out.println("容器创建了");
        }
    
        public void contextDestroyed(ServletContextEvent sce) {
    
            System.out.println("容器销毁了");
        }
    
    
        public void sessionCreated(HttpSessionEvent se) {
    
            System.out.println("Session创建了");
        }
    
        public void sessionDestroyed(HttpSessionEvent se) {
            System.out.println("Session销毁了");
        }
    
    
        @Override
        public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
            
        }
    
        @Override
        public void requestInitialized(ServletRequestEvent servletRequestEvent) {
    
        }
    }
    
    
    • 监听器监听到ServletContext的初始化了,Session的创建和ServletContext的销毁。(服务器停掉,不代表Session就被销毁了。Session的创建是在内存中的,所以没看到Session被销毁了)

    这里写图片描述


    监听对象属性变化

    ServletContextAttributeListener、HttpSessionAttributeListener、ServletRequestAttributeListener分别监听着Context、Session、Request对象属性的变化

    这三个接口中都定义了三个方法来处理被监听对象中的属性的增加,删除和替换的事件,同一个事件在这三个接口中对应的方法名称完全相同,只是接受的参数类型不同

    • attributeAdded()
    • attributeRemoved()
    • attributeReplaced()

    测试

    这里我只演示Context对象,其他对象都是以此类推的,就不一一测试了

    • 实现ServletContextAttributeListener接口。
    
    
    	public class Listener1 implements ServletContextAttributeListener {
    	
    	    @Override
    	    public void attributeAdded(ServletContextAttributeEvent servletContextAttributeEvent) {
    	        System.out.println("Context对象增加了属性");
    	    }
    	
    	    @Override
    	    public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) {
    	        System.out.println("Context对象删除了属性");
    	
    	    }
    	
    	    @Override
    	    public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) {
    	        System.out.println("Context对象替换了属性");
    	
    	    }
    	}
    
    
    
    
    • 测试的Servlet
    
    
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
            ServletContext context = this.getServletContext();
    
            context.setAttribute("aa", "123");
            context.setAttribute("aa", "234");
            context.removeAttribute("aa");
            
        }
    
    

    这里写图片描述


    监听Session内的对象

    除了上面的6种Listener,还有两种Linstener监听Session内的对象,分别是HttpSessionBindingListener和HttpSessionActivationListener,实现这两个接口并不需要在web.xml文件中注册

    • 实现HttpSessionBindingListener接口,**JavaBean 对象可以感知自己被绑定到 Session 中和从 Session 中删除的事件【和HttpSessionAttributeListener的作用是差不多的】 **
    • 实现HttpSessionActivationListener接口,JavaBean 对象可以感知自己被活化和钝化的事件(当服务器关闭时,会将Session的内容保存在硬盘上【钝化】,当服务器开启时,会将Session的内容在硬盘式重新加载【活化】) 。。

    想要测试出Session的硬化和钝化,需要修改Tomcat的配置的。在META-INF下的context.xml文件中添加下面的代码:

    
    <Context>
      <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
      <Store className="org.apache.catalina.session.FileStore" directory="zhongfucheng"/>
      </Manager>
    </Context>
    

    这里写图片描述

    测试

    • 监听器和事件源
    
    
    /*
    * 由于涉及到了将内存的Session钝化到硬盘和用硬盘活化到内存中,所以需要实现Serializable接口
    *
    * 该监听器是不需要在web.xml文件中配置的。但监听器要在事件源上实现接口
    * 也就是说,直接用一个类实现HttpSessionBindingListener和HttpSessionActivationListener接口是监听不到Session内对象的变化的。
    * 因为它们是感知自己在Session中的变化!
    * */
    public class User implements HttpSessionBindingListener,HttpSessionActivationListener,Serializable {
    
        private String username ;
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
    
        @Override
        public void sessionWillPassivate(HttpSessionEvent httpSessionEvent) {
    
            HttpSession httpSession = httpSessionEvent.getSession();
    
            System.out.println("钝化了");
    
        }
    
        @Override
        public void sessionDidActivate(HttpSessionEvent httpSessionEvent) {
            HttpSession httpSession = httpSessionEvent.getSession();
            System.out.println("活化了");
    
        }
        @Override
        public void valueBound(HttpSessionBindingEvent httpSessionBindingEvent) {
    
            System.out.println("绑定了对象");
        }
        @Override
        public void valueUnbound(HttpSessionBindingEvent httpSessionBindingEvent) {
            System.out.println("解除了对象");
    
        }
    }
    
    • 测试代码
    
    
            User user = new User();
            request.getSession().setAttribute("aaa", user);
            request.getSession().removeAttribute("aaa");
    
    • 效果:

    这里写图片描述


    如果文章有错的地方欢迎指正,大家互相交流。习惯在微信看技术文章的同学,可以关注微信公众号:Java3y

  • 相关阅读:
    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/Java3y/p/8436237.html
Copyright © 2011-2022 走看看