监听器

监听器

web的事件编程

  • 事件源: ServletContext对象,ServletRequest对象,HttpSession对象(域对象)
  • 事件: ServletContextEvent,ServletRequestEvent,xxx(创建或销毁对象,对象的属性修改)
  • 事件监听器(接口): ServletContextListener,ServletRequestListener …

web监听器:是一些实现了特定接口的java程序,用于监听web开发中常用的对象(ServletContext对象,ServletRequest对象,HttpSession对象)的创建和销毁行为,以及这些对象的属性修改行为(setAttribute,removeAttribute)

事件源事件对象web监听器
ServletContext对象ServletContextEvent(创建和销毁)ServletContextListener接口
ServletContext对象的属性ServletContextAttributeEvent(增加,修改,删除)ServletContextAttributeListener接口
ServletRequest对象ServletRequestEvent(创建和销毁)ServletRequestListener接口
ServletRequest对象的属性ServletRequestAttributeEvent(增加,修改,删除)ServletRequestAttributeListener接口
HttpSession对象HttpSessionEvent(创建和销毁)HttpSessionListener接口
HttpSession对象的属性HttpSessionBindingEvent(增加,修改,删除)HttpSessionAttributeListener接口

ServletContextListener

用于监听ServletContext对象的创建和销毁行为

ServletContext对象

  • 创建:加载当前的web项目的时候
  • 销毁:关闭服务器或者重新部署web项目

例子:初始化时创建表,销毁时清除表

mysql-connector驱动包—用于连接mysql
c3p0包—数据库连接池
commons-dbutils—对数据库的二次封装简化

c3p0-config.xml配置文件,配置信息如下:

<c3p0-config>
  <!-- 使用默认的配置读取连接池对象 -->
  <default-config>
    <!--  连接参数 -->
    <property name="driverClass">com.mysql.jdbc.Driver</property>
    <property name="jdbcUrl">jdbc:mysql://localhost:3306/day21</property>
    <property name="user">root</property>
    <property name="password">123</property>

    <!-- 连接池参数 -->
    <property name="initialPoolSize">5</property>
    <property name="maxPoolSize">8</property>
    <property name="checkoutTimeout">3000</property>
  </default-config>
</c3p0-config>

JdbcUtil 工具类用于获得数据库连接池,这里使用单例模式
数据库连接池采用单例模式的原因:
数据库连接是一种数据库资源。软件系统中使用数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损耗, 当然,使用数据库连接池还有很多其它的好处,可以屏蔽不同数据数据库之间的差异,实现系统对数据库的低度耦合,也可以被多个系统同时使用,具有高可复用性,还能方便对数据库连接的管理等等。数据库连接池属于重量级资源,一个应用中只需要保留一份即可,既节省了资源又方便管理。所以数据库连接池采用单例模式进行设计会是一个非常好的选择。

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class JdbcUtil {

    private JdbcUtil() {
    }

    private static ComboPooledDataSource ds = new ComboPooledDataSource();
    //用于获得数据库连接池的数据源
    public static DataSource getDataSource() {
        return ds;
    }
}

dao层的编写,创建表以及清除表

import java.sql.SQLException;

import org.apache.commons.dbutils.QueryRunner;

public class SystemDao {
    // 初始化表(创建表)
    public void initTable() {
        QueryRunner qr = new QueryRunner(JdbcUtil.getDataSource());
        try {
            qr.update("create table student(id int primary key,name varchar(20),gender varchar(20))");
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    // 清除表
    public void clearTable() {
        QueryRunner qr = new QueryRunner(JdbcUtil.getDataSource());
        try {
            qr.update("drop table student");
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
}

核心:自定义监听器的编写,需要实现响应的接口

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

//需求:1在启动的时候,初始化表;2在项目结束的时候,删除表
public class MyContextListener implements ServletContextListener {
    SystemDao dao = new SystemDao();

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        // System.out.println("Context对象创建");
        // 初始表
        dao.initTable();
        System.out.println("初始成功");
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        // System.out.println("Context对象销毁");
        dao.clearTable();
        System.out.println("清除成功");
    }
}

<!-- web.xml中注册监听器 -->
<listener>
    <listener-class>cn.itcast.context.MyContextListener</listener-class>
</listener>

ServletContextAttributeListener

ServletContextAttributeListener用于监听ServletContext对象的属性操作(增加属性,修改属性,删除属性)

  • 增加属性: setAttribute(name,Object); 第一次就是增加属性
  • 修改属性: setAttribute(name,Object); 如果前面有增加了同名的属性,则修改。
  • 删除属性: removeAttribute(name);

首先我们创建一个context.jsp,编写脚本用来实现增加修改删除属性的操作

 <%
        application.setAttribute("name", "james");   //增加
        application.setAttribute("name", "wesbrook");//修改
        application.removeAttribute("name");//刪除
 %>

然后我们对先前的MyContextListener类之后实现ServletContextAttributeListener,此时会出现三个需要实现的方法
这样就可以对属性的相关操作得到监听的作用

@Override
    public void attributeAdded(ServletContextAttributeEvent event) {
        // System.out.println("属性增加");
        // 得到属性名
        String name = event.getName();
        // 得到属性值
        Object value = event.getValue();
        System.out.println("属性增加:" + name + "=" + value);
    }

    @Override
    public void attributeReplaced(ServletContextAttributeEvent event) {
        // System.out.println("属性修改");
        // 得到属性名
        String name = event.getName();
        // 得到修改前的属性值
        // Object value = event.getValue();

        // 得到修改后的属性值,需要从ServletContext事件源对象再次获取属性,才可以得到最新的属性值
        ServletContext servletContext = event.getServletContext();
        Object value = servletContext.getAttribute(name);
        System.out.println("属性修改:" + name + "=" + value);
    }

    @Override
    public void attributeRemoved(ServletContextAttributeEvent event) {
        // System.out.println("属性删除");
        // 得到属性名
        String name = event.getName();
        // 得到属性值
        Object value = event.getValue();
        System.out.println("属性删除:" + name + "=" + value);
    }

ServletRequestListener

ServletRequestListener用于监听ServletRequest对象的创建和销毁。
ServletRequest对象:封装请求信息

  • 创建:每次发出请求时
  • 销毁:请求完毕后

例子:监听一个网页请求,并获得客户的ip,打印在界面上

MyRequestListener的编写,实现ServletRequestListener接口

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

public class MyRequestListener implements ServletRequestListener {

    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        // System.out.println("一个请求被创建了");
        // 得到请求相关的信息
        HttpServletRequest request = (HttpServletRequest) sre
                .getServletRequest();
        // 得到客户的ip
        String ip = request.getRemoteHost();
        // 共享数据到页面中
        HttpSession session = request.getSession();
        session.setAttribute("ip", ip);
    }

    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        System.out.println("一个请求对象被销毁了");
    }
}

web.xml中注册监听器

<listener>
    <listener-class>cn.itcast.request.MyRequestListener</listener-class>
</listener>

request.jsp页面的编写

 <body>
    客户的ip地址是 ${sessionScope.ip }
 </body>

ServletRequestAttributeListener

ServletRequestAttributeListener用于监听ServletRequest属性操作

  • 增加属性: setAttribute(name,Object); 第一次就是增加属性
  • 修改属性: setAttribute(name,Object); 如果前面有增加了同名的属性,则修改
  • 删除属性: removeAttribute(name);

代码与ServletContextAttributeListener类似,不再赘述

HttpSessionListener

HttpSessionListener用于监听HttpSession对象的创建和销毁
HttpSession对象:

  • 创建:调用request.getSession(true)方法
  • 销毁:
    1)默认情况下,30分钟服务器自动回收
    2)设置有效时长: session.setMaxActiveInterval(秒)
    3)手动销毁: session.invalidate()方法
    4)web.xml配置全局的过期时间
<session-config>
    <session-timeout>分钟</session-timeout>
</session-config>   

例子:统计当前网站的访问数量

这里的统计不是实时统计,因为销毁需要一段时间,所以只是粗略统计

首先编写一个MySessionListener来监听在线人数,这里用到线程同步来避免统计错误,注意这里用上下文来保存count在线人数

import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

public class MySessionListener implements HttpSessionListener {
    // 用于存储当前网站的访客人数
    private int count = 0;

    // 用于监听HttpSession对象的创建
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        // System.out.println("一个session对象被创建了" + se.getSession());

        ServletContext context = se.getSession().getServletContext();
        // 使用代码同步避免多个用户同时访问的并发问题
        synchronized (MySessionListener.class) {// 注意:锁对象必须是唯一的,类对象就是唯一的
            count++;
            // 把count通过context域对象共享到jsp页面
            // 可以通过session对象获取到
            context.setAttribute("onLine", count);
        }
    }

    // 当用户对应的session对象销毁了,代表访客离线
    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        // System.out.println("一个session对象被销毁了" + se.getSession());
        ServletContext context = se.getSession().getServletContext();
        synchronized (MySessionListener.class) {
            count--;
            context.setAttribute("onLine", count);
        }
    }
}

在web.xml中配置监听器,这里省略
编写一个前端session.jsp来展现当前在线人数

<body>
  <%
  //修改session的过期时间
    session.setMaxInactiveInterval(20);
  %>
    当前网站的在线访客人数为:${applicationScope.onLine }
</body>

HttpSessionAttributeLisener

HttpSessionAttributeLisener用于监听HttpSession的属性操作

  • 增加属性: setAttribute(name,Object); 第一次就是增加属性
  • 修改属性: setAttribute(name,Object); 如果前面有增加了同名的属性,则修改。
  • 删除属性: removeAttribute(name);

例子:统计当前网站的登录用户信息

1)提供用户登录的功能,提供注销功能。
2)显示当前网站的所有登录用户信息
3)管理员可以踢除指定的登录用户。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值