监听器就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法将立即被执行。
监听器典型案例:监听window窗口的事件监听器
1 事件三要素
a)事件源:操作事件的对象,例如:窗体Frame
b)事件监听器:事件监听器监听事件源,例如WindowListner,它是一个接口
c)事件,例如:单击事件,通过事件,可以取得事件源
import java.awt.Frame; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; public class Demo1 { public static void main(String[] args) { Frame frame = new Frame(); frame.setSize(550, 400); frame.setLocation(250, 250); frame.setVisible(true); // 添加监听事件【事件监听器监听事件源】 frame.addWindowListener(new WindowAdapter() {//3、内部类 public void windowClosing(WindowEvent e) { //super.windowClosing(e); System.exit(0); } }); } } // 2、继承WindowAdapter--适配器 /*class MyWindowListener extends WindowAdapter{ @Override public void windowClosing(WindowEvent e) { //super.windowClosing(e); System.exit(0); } }*/ //1、实现接口-- WindowListener-事件监听器 /*class MyWindowListener implements WindowListener{ public void windowOpened(WindowEvent e) { } public void windowClosing(WindowEvent e) { // 取得事件源 Frame frame = (Frame) e.getSource(); // 将事件源隐藏 // frame.setVisible(false); // 将jvm强行终止 System.exit(0);//0表示正常终止,1表示强行终止 System.out.println("windowClosing()..."); } public void windowClosed(WindowEvent e) { System.out.println("windowClosed()"); } public void windowIconified(WindowEvent e) { } public void windowDeiconified(WindowEvent e) { } public void windowActivated(WindowEvent e) { } public void windowDeactivated(WindowEvent e) { } }*/
适配器模式
a)当一个接口有较多的方法时,而实现类只需对其中少数几个实现,此时可以使用适配器模式
b)适配器模式常用于GUI编程
Servlet监听器
在Servlet规范中定义了多种类型的监听器,它们用于监听的事件源分别为 ServletContext, HttpSession 和 ServletRequest 这三个域对象
Servlet规范针对这三个对象上的操作,又把这多种类型的监听器划分为三种类型。
•监听三个域对象创建和销毁的事件监听器
•监听域对象中属性的增加和删除的事件监听器
•监听绑定到HttpSession 域中的某个对象的状态的事件监听器。(查看API文档)
1、监听ServletContext域对象创建和销毁
ServletContextListener接口用于监听 ServletContext对象的创建和销毁事件。
当 ServletContext对象被创建时,激发contextInitialized (ServletContextEventsce)方法
当 ServletContext对象被销毁时,激发contextDestroyed(ServletContextEventsce)方法。
ServletContext域对象何时创建和销毁?
•创建:服务器启动针对每一个web应用创建ServletContext
•销毁:服务器关闭前先关闭代表每一个web应用的ServletContext
监听器的工作过程和生命周期
和编写其它事件监听器一样,编写servlet监听器也需要实现一个特定的接口,并针对相应动作覆盖接口中的相应方法。
和其它事件监听器略有不同的是,servlet监听器的注册不是直接注册在事件源上,而是由web容器负责注册,开发人员只需在web.xml文件中使用<listener>标签配置好监听器,web容器就会自动把监听器注册到事件源中。
一个 web.xml 文件中可以配置多个 Servlet 事件监听器,web 服务器按照它们在 web.xml 文件中的注册顺序来加载和注册这些 Serlvet 事件监听器。
开发过程:
a)写一个普通类实现对应的接口,即事件监听器
import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; //事件监听器[用于监听ServletContext对象产生和销毁] public class MyServletContextListener implements ServletContextListener{ public MyServletContextListener(){ System.out.println("空参构造"); System.out.println(this.hashCode()); } //产生 public void contextInitialized(ServletContextEvent sce) { System.out.println("ServletContext产生"); System.out.println(this.hashCode()); } //销毁 public void contextDestroyed(ServletContextEvent sce) { System.out.println("ServletContext销毁"); System.out.println(this.hashCode()); } }
b)在web.xml文件中注册事件监听器
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!--事件源注册事件监听器--> <listener> <listener-class>cn.zengfansheng.web.listener.MyServletContextListener</listener-class> </listener> </web-app>
练习:
创建系统的所有表结构和数据,即初始化工作-每x秒向数据库中插入一条记录
1)写一个普通类实现对应的接口,即事件监听器
import java.util.Timer; import java.util.TimerTask; import java.util.UUID; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import cn.itcast.web.dao.SystemDao; public class SystemListener implements ServletContextListener { private Timer timer = new Timer(); public void contextInitialized(ServletContextEvent sce) { try { SystemDao systemDao = new SystemDao(); systemDao.createTable("systemInit"); timer.schedule(new SystemTask(),0,5*1000); } catch (Exception e) { } } public void contextDestroyed(ServletContextEvent sce) { try { SystemDao systemDao = new SystemDao(); systemDao.dropTable("systemInit"); //中止定时器 timer.cancel(); } catch (Exception e) { } } } //任务类 class SystemTask extends TimerTask{ public void run() { try { SystemDao systemDao = new SystemDao(); systemDao.init("systemInit",UUID.randomUUID().toString()); } catch (Exception e) { } } }
import java.sql.SQLException; import org.apache.commons.dbutils.QueryRunner; import cn.itcast.web.util.JdbcUtil; public class SystemDao { //删除表 public void dropTable(String tableName) throws SQLException{ QueryRunner runner = new QueryRunner(JdbcUtil.getDataSource()); String sql = "drop table if exists " + tableName; runner.update(sql); } //创建表 public void createTable(String tableName) throws SQLException{ QueryRunner runner = new QueryRunner(JdbcUtil.getDataSource()); String sql = "create table if not exists "+tableName+"(id varchar(40) primary key,curr_time timestamp not null)"; runner.update(sql); } //初始化数据 public void init(String tableName,String id) throws SQLException{ QueryRunner runner = new QueryRunner(JdbcUtil.getDataSource()); String sql = "insert into "+tableName+"(id) values(?)"; runner.update(sql,id); } }
2)在web.xml文件中注册事件监听器
<listener> <listener-class>cn.zengfansheng.web.listener.SystemListener</listener-class> </listener>
c3p0-config.xml
<?xml version="1.0" encoding="UTF-8"?> <c3p0-config> <default-config> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="user">root</property> <property name="password">123456</property> <property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/mydb3</property> </default-config> </c3p0-config>
2、监听ServletRequest域对象创建和销毁
ServletRequestListener接口用于监听ServletRequest对象的创建和销毁。
Request 对象被创建时,监听器的requestInitialized方法将会被调用。
Request对象被销毁时,监听器的requestDestroyed方法将会被调用。
servletRequest域对象创建和销毁的时机:
•创建:用户每一次访问,都会创建一个reqeust
•销毁:当前访问结束,request对象就会销毁