在介绍监听器之前,先跟同学们普及一个知识,观察者设计模式。因为所有的监听器都是观察者设计模式的体现。
那什么是观察者设计模式呢?
它是事件驱动的一种体现形式。就好比在做什么事情的时候被人盯着。当对应做到某件事时,触发事件。
观察者模式通常由以下三部分组成:
事件源:触发事件的对象。
事件:触发的动作,里面封装了事件源。
监听器:当事件源触发事件时,要做的事情。一般是一个接口,由使用者来实现。(此处的思想还涉及了一个涉及模式,我们在JDBC的第二天课程中就给同学们讲解,策略模式)
下图描述了观察者设计模式组成:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J8ALkCO8-1602127889250)(assets/观察者模式.jpg)]
此处要跟同学们明确一下,和会话域相关的两个感知型监听器是无需配置的,直接编写代码即可。
在实际开发中,我们可以根据具体情况来从这8个监听器中选择使用。感知型监听器由于无需配置,只需要根据实际需求编写代码,所以此处我们就不再演示了。我们在剩余6个中分别选择一个监听对象创建销毁和对象域中属性发生变化的监听器演示一下。
第一步:创建工程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RQRglltd-1602127889258)(assets/listener_demo1.png)]
第二步:编写监听器
/** * 用于监听ServletContext对象创建和销毁的监听器 * @author 黑马程序员 * @Company http://www.itheima.com */ public class ServletContextListenerDemo implements ServletContextListener { /** * 对象创建时,执行此方法 * @param sce */ @Override public void contextInitialized(ServletContextEvent sce) { System.out.println("监听到了对象的创建"); //1.获取事件源对象 ServletContext servletContext = sce.getServletContext(); System.out.println(servletContext); } /** * 对象销毁时,执行此方法 * @param sce */ @Override public void contextDestroyed(ServletContextEvent sce) { System.out.println("监听到了对象的销毁"); } }第三步:在web.xml中配置监听器
<!--配置监听器--> <listener> <listener-class>com.itheima.web.listener.ServletContextListenerDemo</listener-class> </listener>第四步:测试结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PoJwWZAH-1602127889261)(assets/listener_demo2.png)]
第一步:创建工程
沿用上一个案例的工程
第二步:编写监听器
/** * 监听域中属性发生变化的监听器 * @author 黑马程序员 * @Company http://www.itheima.com */ public class ServletContextAttributeListenerDemo implements ServletContextAttributeListener { /** * 域中添加了数据 * @param scae */ @Override public void attributeAdded(ServletContextAttributeEvent scae) { System.out.println("监听到域中加入了属性"); /** * 由于除了我们往域中添加了数据外,应用在加载时还会自动往域中添加一些属性。 * 我们可以获取域中所有名称的枚举,从而看到域中都有哪些属性 */ //1.获取事件源对象ServletContext ServletContext servletContext = scae.getServletContext(); //2.获取域中所有名称的枚举 Enumeration<String> names = servletContext.getAttributeNames(); //3.遍历名称的枚举 while(names.hasMoreElements()){ //4.获取每个名称 String name = names.nextElement(); //5.获取值 Object value = servletContext.getAttribute(name); //6.输出名称和值 System.out.println("name is "+name+" and value is "+value); } } /** * 域中移除了数据 * @param scae */ @Override public void attributeRemoved(ServletContextAttributeEvent scae) { System.out.println("监听到域中移除了属性"); } /** * 域中属性发生了替换 * @param scae */ @Override public void attributeReplaced(ServletContextAttributeEvent scae) { System.out.println("监听到域中属性发生了替换"); } }同时,我们还需要借助第一个ServletContextListenerDemo监听器,往域中存入数据,替换域中的数据以及从域中移除数据,代码如下:
/** * 用于监听ServletContext对象创建和销毁的监听器 * @author 黑马程序员 * @Company http://www.itheima.com */ public class ServletContextListenerDemo implements ServletContextListener { /** * 对象创建时,执行此方法 * @param sce */ @Override public void contextInitialized(ServletContextEvent sce) { System.out.println("监听到了对象的创建"); //1.获取事件源对象 ServletContext servletContext = sce.getServletContext(); //2.往域中加入属性 servletContext.setAttribute("servletContext","test"); } /** * 对象销毁时,执行此方法 * @param sce */ @Override public void contextDestroyed(ServletContextEvent sce) { //1.取出事件源对象 ServletContext servletContext = sce.getServletContext(); //2.往域中加入属性,但是名称仍采用servletContext,此时就是替换 servletContext.setAttribute("servletContext","demo"); System.out.println("监听到了对象的销毁"); //3.移除属性 servletContext.removeAttribute("servletContext"); } }第三步:在web.xml中配置监听器
<!--配置监听器--> <listener> <listener-class>com.itheima.web.listener.ServletContextListenerDemo</listener-class> </listener> <!--配置监听器--> <listener> <listener-class>com.itheima.web.listener.ServletContextAttributeListenerDemo</listener-class> </listener>第四步:测试结果
