所谓监听器就是一个java类,用来监听其他java类的状态变化。
监听器的术语:
事件源:指被监听的对象(汽车)
监听器:监听的对象(报警器)
事件源与监听器的绑定:(就是在汽车上安装报警器)
事件:事件源的改变(踹汽车一脚)--事件是用来获得事件源的。
监听器的用途:
一:用来监听其他对象的状态变化;
二:主要应用在图形化界面中比较多;
GUI、Android
1 package test; 2 import java.awt.event.WindowEvent; 3 import java.awt.event.WindowListener; 4 import javax.swing.JFrame; 5 public class MyFrame extends JFrame { 6 public static void main(String[] args) { 7 //创建一个窗口对象(事件源) 8 MyFrame mf = new MyFrame(); 9 //设置窗口的大小 10 mf.setBounds(0, 0, 200, 200); 11 //设置窗口时显示的 12 mf.setVisible(true); 13 //给这个窗口设置监听器(事件源和监听器的绑定) 14 mf.addWindowListener(new MyWindowListener()); 15 } 16 } 17 /** 18 * 监听器 19 */ 20 class MyWindowListener implements WindowListener{ 21 @Override 22 public void windowOpened(WindowEvent e) { 23 } 24 //当关闭窗口的时候触发(改变事件源) 25 @Override 26 public void windowClosing(WindowEvent e) { 27 System.out.println("窗口正在关闭。。。"); 28 System.exit(0);//关闭程序 29 } 30 @Override 31 public void windowClosed(WindowEvent e) { 32 } 33 @Override 34 public void windowIconified(WindowEvent e) { 35 } 36 @Override 37 public void windowDeiconified(WindowEvent e) { 38 } 39 @Override 40 public void windowActivated(WindowEvent e) { 41 } 42 @Override 43 public void windowDeactivated(WindowEvent e) { 44 } 45 }
WEB中的监听器:
事件源:servlet中的三个域对象:ServletContext,HttpSession,ServletRequest.
监听器:自定义类实现8个接口。
事件源和监听器的绑定:配置
WEB中的监听器共有三类八种(监听三个域对象)
一类:监听三个域对象的创建和销毁;
ServletContextListener
HttpSessionListener
ServletRequestListener
二类:监听三个域对象的属性变更(属性添加,移除,替换);
ServletContextAttributeListener
HttpSessioinAttributeListener
ServletRequestAttributeListener
三类:监听HttpSession中JavaBean的状态改变(绑定,解除绑定,钝化,活化);
HttpSessionBindingListener (监听绑定,解除绑定)绑定就是把javabean存入session域中,解除就是把javabean移除或用其他值(非javabean值)替换。
HttpSessionActivationListener (监听钝化,活化) 钝化即序列化 活化即反序列化
注意:第三类监听器很特殊,不需要进行配置,作用在JavaBean上的监听器,JavaBean可以自己感知在Session中的状态;
让需要被监听的javabean implements HttpSessionBindingListener/HttpSessionActivationListener,然后重写里面的方法即可。
当需要监听某个javabean的钝化或活化时,该javabean需要实现序列化接口Serializable,否则会报错。(当正常关闭服务器session域就会发生钝化情况,或者通过配置session钝化时间)
WEB中监听器的使用:
步骤1:编写一个类实现监听器的接口;
步骤2:通过配置文件配置监听器;
<listener> <listener-class>自定义监听器类的全路径</listener-class> </listener>
两种监听器在企业中的应用:
ServletContextListener
因为该监听器是监听ServletContext对象的,由于该对象的创建和生命周期的特性可以用来做加载文件或执行定时任务。
作用一:加载框架的配置文件;eg:Spring框架 ContextLoaderListener implements ServletContextListener
作用二:执行定时任务调度(Timer,TimerTask):(在服务器启动的时候,定时去执行任务)
Timer API: | |
void scheduleAtFixedRate(TimerTask task, Date firstTime, long period) | 安排指定的任务在指定的时间开始进行重复的固定速率执行 |
void scheduleAtFixedRate(TimerTask task, long delay, long period) | 安排指定的任务在指定的延迟后开始进行重复的固定速率执行。 |
1 package listener; 2 3 import java.util.Calendar; 4 import java.util.Timer; 5 import java.util.TimerTask; 6 7 import javax.naming.NamingException; 8 import javax.servlet.ServletContext; 9 import javax.servlet.ServletContextEvent; 10 import javax.servlet.ServletContextListener; 11 12 import org.apache.naming.SelectorContext; 13 14 public class MyServletContextListener implements ServletContextListener { 15 @Override 16 public void contextInitialized(ServletContextEvent sce) { 17 // 通过事件来获得事件源 18 ServletContext source = (ServletContext) sce.getSource(); 19 System.out.println(source.getServletContextName()); 20 // 任务调度示例 21 Timer timer = new Timer(); 22 Calendar calendar = Calendar.getInstance(); 23 calendar.set(2018, 7, 24, 10, 47, 59);//设置一个时间点 24 //设置服务器启动后按指定的calendar.getTime()时间执行run(),然后接下来每间隔5s执行一次. 25 timer.scheduleAtFixedRate(new TimerTask() { 26 @Override 27 public void run() { 28 System.out.println("发送邮件。。。"); 29 } 30 }, calendar.getTime(), 5000); 31 } 32 33 // ServletContext对象销毁的时候触发 34 @Override 35 public void contextDestroyed(ServletContextEvent sce) { 36 37 } 38 39 }
1 package listener; 2 3 import java.util.Calendar; 4 import java.util.Timer; 5 import java.util.TimerTask; 6 7 import javax.naming.NamingException; 8 import javax.servlet.ServletContext; 9 import javax.servlet.ServletContextEvent; 10 import javax.servlet.ServletContextListener; 11 12 import org.apache.naming.SelectorContext; 13 14 public class MyServletContextListener implements ServletContextListener { 15 @Override 16 public void contextInitialized(ServletContextEvent sce) { 17 // 通过事件来获得事件源 18 ServletContext source = (ServletContext) sce.getSource(); 19 System.out.println(source.getServletContextName()); 20 // 任务调度示例 21 Timer timer = new Timer(); 22 // 设置服务器启动后延迟10s后执行run(),然后接下来每间隔2s执行一次 23 timer.scheduleAtFixedRate(new TimerTask() { 24 @Override 25 public void run() { 26 System.out.println("发送邮件。。。"); 27 } 28 }, 10000, 2000); 29 } 30 31 // ServletContext对象销毁的时候触发 32 @Override 33 public void contextDestroyed(ServletContextEvent sce) { 34 35 } 36 37 }
HttpSessionActivationListener
作用:优化session
当并发访问过大的时候,因为过多的session对象对服务器内存造成巨大的浪费导致性能的下降,我们可以使用该监听器让规定一定时长后不使用的session序列化到硬盘,然后再等用的时候反序列化回来,这样大大节省了内存,提高了性能。但是我们又不能依赖于服务器的关闭和启动来实现序列化session,那么我们可以通过配置一个<Context>标签定时序列化session。
<Context>配置的三种路径:(放到不同的路径中对session的作用范围不同)
一:在tomcat/conf/context.xml中配置一个<Context>; //在tomcat中所有虚拟主机和虚拟路径都会按照这个配置执行。
二:在tomcat/conf/Catalina/localhost/context.xml配置<Context>; //在tomcat中的localhost虚拟主机中的所有虚拟路径按照这个配置执行。
三:在当前工程下的META-INF/context.xml配置<Context>; //当前这个工程按照配置执行。
<Context>的配置文档:
1 <Context> 2 <!-- 3 maxIdleSwap:1 表示session1分钟不用的话就会被自动序列化到硬盘 4 directory:hello 表示序列化后文件存储的文件夹名称为hello(work\Catalina\localhost/ProjectName/hello) 5 --> 6 <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1"> 7 <Store className="org.apache.catalina.session.FileStore" directory="hello"/> 8 </Manager> 9 </Context>