Listener简介
Listener监听器就是监听某个对象的的状态变化的组件。
监听器的相关概念事件源:
- 被监听的对象(三个域对象 request,session,servletContext)
- 监听器:监听事件源对象, 事件源对象的状态的变化都会触发监听器 。
- 注册监听器:将监听器与事件源进行绑定。
- 响应行为:监听器监听到事件源的状态变化时,所涉及的功能代码(程序员编写代码)
按照被监听的对象划分:ServletRequest域 ;HttpSession域 ;ServletContext域。
按照监听的内容分:监听域对象的创建与销毁的; 监听域对象的属性变化的。
三大域对象的创建与销毁的监听器
ServletContextListener
监听ServletContext域的创建与销毁的监听器,Servlet域的生命周期:在服务器启动创建,服务器关闭时销毁;监听器的编写步骤:
- 编写一个监听器类去实现监听器接口
- 重写监听器的方法
- 需要在web.xml中进行配置(注册)
1、监听的方法:
2、配置文件:
ServletContextListener监听器的主要作用:
- 初始化的工作:初始化对象;初始化数据。比如加载数据库驱动,对连接池的初始化。
- 加载一些初始化的配置文件;比如spring的配置文件。
- 任务调度(定时器Timer/TimerTask)
举个?子:
1 package com.boss.listener; 2 3 import java.text.SimpleDateFormat; 4 import java.util.Date; 5 import java.util.Timer; 6 import java.util.TimerTask; 7 8 import javax.servlet.ServletContextEvent; 9 import javax.servlet.ServletContextListener; 10 11 public class MyServletContextListener implements ServletContextListener { 12 13 @Override 14 //监听context域对象的创建 15 public void contextInitialized(ServletContextEvent sce) { 16 //就是被监听的对象---ServletContext 17 //ServletContext servletContext = sce.getServletContext(); 18 //getSource就是被监听的对象 是通用的方法 19 //ServletContext source = (ServletContext) sce.getSource(); 20 //System.out.println("context创建了...."); 21 22 //开启一个银行计息任务调度,每天晚上12点计息一次 23 //1.起始时间:晚上12点 24 //2.间隔时间:24小时 25 try { 26 Timer timer = new Timer(); 27 28 SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"); 29 String currentTime = "2017-08-10 00:00:00"; 30 Date parse = df.parse(currentTime); 31 32 //task:任务 firstTime:第一次执行时间 period:间隔执行时间 33 //timer.scheduleAtFixedRate(task, firstTime, period); 34 timer.scheduleAtFixedRate(new TimerTask() { 35 @Override 36 public void run() { 37 System.out.println("银行计息了....."); 38 } 39 }, parse, 24 * 60 * 60 * 1000); 40 } catch (Exception e) { 41 e.printStackTrace(); 42 } 43 } 44 45 //监听context域对象的销毁 46 @Override 47 public void contextDestroyed(ServletContextEvent sce) { 48 System.out.println("context销毁了...."); 49 50 } 51 52 }
web.xml
1 <listener> 2 <listener-class>com.boss.listener.MyServletContextListener</listener-class> 3 </listener>
HttpSessionListener
监听Httpsession域的创建与销毁的监听器。
HttpSession对象的生命周期:第一次调用request.getSession时创建;销毁有以下几种情况(服务器关闭、session过期、 手动销毁)
监听的方法:
1 package com.boss.listener; 2 3 import javax.servlet.http.HttpSessionEvent; 4 import javax.servlet.http.HttpSessionListener; 5 6 public class MyHttpSessionListener implements HttpSessionListener { 7 8 @Override 9 public void sessionCreated(HttpSessionEvent httpSessionEvent) { 10 System.out.println("session创建" + httpSessionEvent.getSession().getId()); 11 } 12 13 @Override 14 public void sessionDestroyed(HttpSessionEvent httpSessionEvent) { 15 System.out.println("session销毁"); 16 } 17 18 }
web.xml:
1 <listener> 2 <listener-class>com.boss.listener.MyHttpSessionListener</listener-class> 3 </listener>
测试代码:
1 package com.boss.servlet; 2 3 import java.io.IOException; 4 5 import javax.servlet.ServletException; 6 import javax.servlet.http.HttpServlet; 7 import javax.servlet.http.HttpServletRequest; 8 import javax.servlet.http.HttpServletResponse; 9 10 public class HttpSessionListenerServlet extends HttpServlet { 11 12 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, 13 IOException { 14 //1.生成验证码 15 String code = "ABCD"; 16 //2.将验证码保存到session中 17 request.getSession().setAttribute("code", code); 18 //3.设置session失效时间,单位:秒 19 request.getSession().setMaxInactiveInterval(5); 20 } 21 22 public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, 23 IOException { 24 doGet(request, response); 25 } 26 }
当创建session时,监听器中的代码将执行。
ServletRequestListener
监听ServletRequest域创建与销毁的监听器。
ServletRequest的生命周期:每一次请求都会创建request,请求结束则销毁。
监听的方法:
1 package com.boss.listener; 2 3 import javax.servlet.ServletRequestEvent; 4 import javax.servlet.ServletRequestListener; 5 6 public class MyServletRequestListener implements ServletRequestListener { 7 @Override 8 public void requestDestroyed(ServletRequestEvent servletRequestEvent) { 9 System.out.println("request被销毁了"); 10 } 11 12 @Override 13 public void requestInitialized(ServletRequestEvent servletRequestEvent) { 14 System.out.println("request被创建了"); 15 } 16 17 }
web.xml:
1 <listener> 2 <listener-class>com.boss.listener.MyServletRequestListener</listener-class> 3 </listener>
只要客户端发起请求,监听器中的代码就会被执行。
监听三大域对象的属性变化的
域对象的通用的方法
setAttribute(name,value):触发添加属性的监听器的方法
getAttribute(name):触发修改属性的监听器的方法
removeAttribute(name):触发删除属性的监听器的方法
ServletContextAttibuteListener
监听的方法:
1 package com.boss.listener; 2 3 import javax.servlet.ServletContextAttributeEvent; 4 import javax.servlet.ServletContextAttributeListener; 5 6 public class MyServletContextAttributeListener implements ServletContextAttributeListener { 7 @Override 8 public void attributeAdded(ServletContextAttributeEvent scab) { 9 //放到域中的属性 10 System.out.println(scab.getName());//放到域中的name 11 System.out.println(scab.getValue());//放到域中的value 12 } 13 14 @Override 15 public void attributeRemoved(ServletContextAttributeEvent scab) { 16 System.out.println(scab.getName());//删除的域中的name 17 System.out.println(scab.getValue());//删除的域中的value 18 } 19 20 @Override 21 public void attributeReplaced(ServletContextAttributeEvent scab) { 22 System.out.println(scab.getName());//获得修改前的name 23 System.out.println(scab.getValue());//获得修改前的value 24 } 25 26 }
web.xml:
1 <listener> 2 <listener-class>com.boss.listener.MyServletContextAttributeListener</listener-class> 3 </listener>
测试代码:
1 package com.boss.servlet; 2 3 import java.io.IOException; 4 5 import javax.servlet.ServletContext; 6 import javax.servlet.ServletException; 7 import javax.servlet.http.HttpServlet; 8 import javax.servlet.http.HttpServletRequest; 9 import javax.servlet.http.HttpServletResponse; 10 11 public class ServletContextAttributeListenerServlet extends HttpServlet { 12 13 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, 14 IOException { 15 ServletContext context = this.getServletContext(); 16 context.setAttribute("name", "tom");//添加属性 17 context.setAttribute("name", "lucy");//修改属性 18 context.removeAttribute("name");//删除属性 19 } 20 21 public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, 22 IOException { 23 doGet(request, response); 24 } 25 }
HttpSessionAttributeListener监听器(同上)
ServletRequestAriibuteListenr监听器(同上)
与session中的绑定的对象相关的监听器(对象感知监听器)
将要被绑定到session中的对象有几种状态
- 绑定状态:就一个对象被放到session域中
- 解绑状态:就是这个对象从session域中移除了
- 钝化状态:是将session内存中的对象持久化(序列化)到磁盘
- 活化状态:就是将磁盘上的对象再次恢复到session内存中
对象感知监听器不用在web.xml中配置。
面试题:当用户很多时,怎样对服务器进行优化?
绑定与解绑的监听器HttpSessionBindingListener
1 package com.boss.domain; 2 3 import javax.servlet.http.HttpSessionBindingEvent; 4 import javax.servlet.http.HttpSessionBindingListener; 5 6 public class Person implements HttpSessionBindingListener { 7 8 private String id; 9 10 private String name; 11 12 public String getId() { 13 return id; 14 } 15 16 public void setId(String id) { 17 this.id = id; 18 } 19 20 public String getName() { 21 return name; 22 } 23 24 public void setName(String name) { 25 this.name = name; 26 } 27 28 @Override 29 //绑定的方法 30 public void valueBound(HttpSessionBindingEvent event) { 31 System.out.println("person被绑定了"); 32 } 33 34 @Override 35 //解绑方法 36 public void valueUnbound(HttpSessionBindingEvent event) { 37 System.out.println("person被解绑了"); 38 } 39 }
测试代码:
1 package com.boss.servlet; 2 3 import java.io.IOException; 4 5 import javax.servlet.ServletException; 6 import javax.servlet.http.HttpServlet; 7 import javax.servlet.http.HttpServletRequest; 8 import javax.servlet.http.HttpServletResponse; 9 import javax.servlet.http.HttpSession; 10 11 import com.boss.domain.Person; 12 13 public class HttpSessionBindingListenerServlet extends HttpServlet { 14 15 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, 16 IOException { 17 18 Person p = new Person(); 19 p.setId("10"); 20 p.setName("tom"); 21 22 HttpSession session = request.getSession(); 23 //将person对象绑到session中 24 session.setAttribute("person", p); 25 //将person对象从session中解绑 26 session.removeAttribute("person"); 27 } 28 29 public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, 30 IOException { 31 doGet(request, response); 32 } 33 }
钝化与活化的监听器HttpSessionActivationListener
1 package com.boss.domain; 2 3 import java.io.Serializable; 4 5 import javax.servlet.http.HttpSessionActivationListener; 6 import javax.servlet.http.HttpSessionEvent; 7 8 public class Customer implements HttpSessionActivationListener, Serializable { 9 10 private String id; 11 12 private String name; 13 14 public String getId() { 15 return id; 16 } 17 18 public void setId(String id) { 19 this.id = id; 20 } 21 22 public String getName() { 23 return name; 24 } 25 26 public void setName(String name) { 27 this.name = name; 28 } 29 30 @Override 31 //钝化 32 public void sessionWillPassivate(HttpSessionEvent se) { 33 System.out.println("customer被钝化了"); 34 } 35 36 @Override 37 //活化 38 public void sessionDidActivate(HttpSessionEvent se) { 39 System.out.println("customer被活化了"); 40 } 41 42 }
测试代码:
1 package com.boss.servlet; 2 3 import java.io.IOException; 4 5 import javax.servlet.ServletException; 6 import javax.servlet.http.HttpServlet; 7 import javax.servlet.http.HttpServletRequest; 8 import javax.servlet.http.HttpServletResponse; 9 import javax.servlet.http.HttpSession; 10 11 import com.boss.domain.Customer; 12 13 public class HttpSessionActivationListenerServlet extends HttpServlet { 14 15 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, 16 IOException { 17 18 Customer customer = new Customer(); 19 customer.setId("20"); 20 customer.setName("lucy"); 21 22 HttpSession session = request.getSession(); 23 //将customer放到session中 24 session.setAttribute("customer", customer); 25 System.out.println("customer被放到session域中了"); 26 } 27 28 public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, 29 IOException { 30 doGet(request, response); 31 } 32 }
当访问HttpSessionActivationListenerServlet之后,停止服务,customer就会被钝化,钝化的文件存在tomcat的work文件夹下。
测试代码:
1 package com.boss.servlet; 2 3 import java.io.IOException; 4 5 import javax.servlet.ServletException; 6 import javax.servlet.http.HttpServlet; 7 import javax.servlet.http.HttpServletRequest; 8 import javax.servlet.http.HttpServletResponse; 9 import javax.servlet.http.HttpSession; 10 11 import com.boss.domain.Customer; 12 13 public class HttpSessionActivationListenerServlet2 extends HttpServlet { 14 15 public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, 16 IOException { 17 //从session域中获得customer 18 HttpSession session = request.getSession(); 19 Customer customer = (Customer) session.getAttribute("customer"); 20 System.out.println(customer.getName()); 21 } 22 23 public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, 24 IOException { 25 doGet(request, response); 26 } 27 }
服务再次启动,访问HttpSessionActivationListenerServlet2之后,customer就会被活化。
可以通过配置文件,指定对象钝化时间(对象多长时间不用被钝化)
在META-INF下创建一个context.xml
<?xml version="1.0" encoding="UTF-8"?> <Context> <!-- maxIdleSwap:session中的对象多长时间(分钟)不使用就钝化 --> <!-- directory:配置钝化后的对象的文件写到磁盘的哪个目录下,配置钝化的对象文件在 work/catalina/localhost/项目名/钝化文件 --> <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1"> <Store className="org.apache.catalina.session.FileStore" directory="zhanglei" /> </Manager> </Context>