Listener的简单介绍及使用

一、Listener概述

Listener可以监听容器中某一执行动作,并根据其要求做出相应的响应。   
常用的Web事件的监听接口如下:
ServletContextListener:用于监听Web的启动及关闭
ServletContextAttributeListener:用于监听ServletContext范围内属性的改变
ServletRequestListener:用于监听用户请求
ServletRequestAttributeListener:用于监听ServletRequest范围属性的改变
HttpSessionListener:用于监听用户session的开始及结束
HttpSessionAttributeListener:用于监听HttpSession范围内的属性改变

二、ServletContextListener的使用

1、配置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">
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  <!-- 初始化参数 -->
  <context-param>
      <param-name>driver</param-name>
      <param-value>com.mysql.jdbc.Driver</param-value>
  </context-param>
  <context-param>
       <param-name>url</param-name>
       <param-value>jdbc:mysql://localhost:3306/escshop</param-value>
  </context-param>
  <context-param>
       <param-name>user</param-name>
       <param-value>root</param-value>
  </context-param>
  <context-param>
        <param-name>pass</param-name>
        <param-value></param-value>
  </context-param>
  <!-- 定义Filter -->
  <filter>
     <filter-name>logFilter</filter-name>
     <filter-class>Filter.LogFilter</filter-class>
  </filter>
  <!-- 定义Filter拦截的URL地址 -->
  <filter-mapping>
      <filter-name>logFilter</filter-name>
      <!-- 负责拦截的URL,/*表示拦截所有的请求 -->
      <url-pattern>/*</url-pattern>
  </filter-mapping>
  <!-- 定义AuthorityFilter -->
  <filter>
      <filter-name>authority</filter-name>
      <filter-class>Filter.AuthorityFilter</filter-class>
      <init-param>
          <param-name>encode</param-name>
          <param-value>UTF-8</param-value>
      </init-param>
      <init-param>
          <param-name>indexPage</param-name>
          <param-value>/index.jsp</param-value>
      </init-param>
      <init-param>
           <param-name>shopPage</param-name>
           <param-value>/shop.jsp</param-value>
      </init-param>
  </filter>
  <filter-mapping>
      <filter-name>authority</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>
  <!-- 登录servlet -->
  <servlet>
       <servlet-name>LoginServlet</servlet-name>
       <servlet-class>Login.LoginServlet</servlet-class>
       <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
        <servlet-name>LoginServlet</servlet-name>
        <url-pattern>/login</url-pattern>
  </servlet-mapping>
  <!-- 配置监听Web启动与关闭的Listener -->
  <listener>
      <listener-class>listener.GetConnListener</listener-class>
  </listener>
  <!-- 用于监听ServletContenxt(application)范围的变化 -->
  <listener>
      <listener-class>listener.MyServletContenxtAttributeListener</listener-class>
  </listener>
  <!-- 用于监听用户请求到达 -->
  <listener>
      <listener-class>listener.RequestListener</listener-class>
  </listener>
  <listener>
      <listener-class>listener.OnlineRequestListener</listener-class>
  </listener>
  <!--用户监听用户session创建与销毁  -->
  <listener>
      <listener-class>listener.OnlineListener</listener-class>
  </listener>
</web-app>

2、使用ServletContextListener

package listener;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
/**
 * 监听Web应用启动及关闭
 * @author xieyongxue
 *
 */
public class GetConnListener implements ServletContextListener{
    //应用关闭时,此方法被调用
    public void contextDestroyed(ServletContextEvent sce) {
        // TODO Auto-generated method stub
        ServletContext application=sce.getServletContext();
        Connection conn=(Connection) application.getAttribute("conn");
        if (conn!=null) {
            try {
                conn.close();
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
    //应用启动时,此方法被调用
    public void contextInitialized(ServletContextEvent sce) {
        // TODO Auto-generated method stub
        //获取到该应用的ServletContext的实例
        ServletContext application=sce.getServletContext();
        //获取数据库驱动
        String driver=application.getInitParameter("driver");
        //加载数据库连接URL
        String url=application.getInitParameter("url");
        //获取登录数据库的名称
        String user=application.getInitParameter("user");
        //获取连接数据库的密码
        String pass=application.getInitParameter("pass");
        try {
            try {
                Class.forName(driver);
            } catch (ClassNotFoundException e) {
                // TODO Auto-generated catch block
                System.out.println("加载数据库驱动失败!"+e.toString());
                e.printStackTrace();
            }
            Connection conn= DriverManager.getConnection(url, user, pass);
            //将数据库连接设置成application的属性
            application.setAttribute("conn", conn);
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            System.out.println("连接数据库失败!"+e.toString());
            e.printStackTrace();
        }
    }
}

3、使用ServletContextAttributeListener

package listener;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
public class MyServletContenxtAttributeListener implements ServletContextAttributeListener{
    //当程序向application范围新增属性时触发此方法
    public void attributeAdded(ServletContextAttributeEvent scab) {
        // TODO Auto-generated method stub
        ServletContext application=scab.getServletContext();
        //获取新增的属性名与值
        String name=scab.getName();
        Object value=scab.getValue();
        System.out.println(application+"范围内新增了name值为="+name+"value值="+value);
    }
     //当程序向application范围移除属性时触发此方法
    public void attributeRemoved(ServletContextAttributeEvent scab) {
        // TODO Auto-generated method stub
        ServletContext application=scab.getServletContext();
        //获取移除的属性名与值
        String name=scab.getName();
        Object value=scab.getValue();
        System.out.println(application+"范围内移除了name值为="+name+"value值="+value);

    }
    //当程序向application范围替换属性时触发此方法
    public void attributeReplaced(ServletContextAttributeEvent scab) {
        // TODO Auto-generated method stub
        ServletContext application=scab.getServletContext();
        //获取替换的属性名与值
        String name=scab.getName();
        Object value=scab.getValue();
        System.out.println(application+"范围内替换了name值为="+name+"value值="+value);
    }
}

4、测试例子

<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
application.setAttribute("addAttrName","addAttrValue");
application.removeAttribute("addAttrName");
application.setAttribute("newAttrName","newAttrValue");
application.setAttribute("newAttrName","1234567");
request.setAttribute("requestName1","requestValue1");
request.removeAttribute("requestName1");
request.setAttribute("requestName2","requestValue2");
request.setAttribute("requestName2","requestValue23");
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    <title>Login</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
  </head>
  <body>
    ${tip}<br>
    <form action="login?action=service" method="post">
                    名称:<input type="text" name="user"><br>
                    密码:<input type="text" name="pass"><br/>
      <input type="submit" value="登录"><input type="reset" value="重置">
    </form>
  </body>
</html>

二、使用HttpSessionListener统计用户在线人数

1、实现HttpSessionListener监听器
package listener;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class OnlineListener implements HttpSessionListener{
    //当用户与服务器开始session时触发该方法
    public void sessionCreated(HttpSessionEvent se) {
        // TODO Auto-generated method stub
        HttpSession session=se.getSession();
        ServletContext application=session.getServletContext();
        //获取sessionId
        String sessionId=session.getId();
        session.setMaxInactiveInterval(15);
        //如果是新连接
        if(session.isNew()){
            Map<String,String> online=(Map<String, String>) application.getAttribute("online");
            String user=(String) session.getAttribute("user");
            user=(user==null?"游客":user);
            if(online==null){
                online=new HashMap<String, String>();
            }
            online.put(sessionId, user);
            application.setAttribute("online", online);
        }   
    }
    //当用户与服务器断开session时触发该方法
    public void sessionDestroyed(HttpSessionEvent se) {
        // TODO Auto-generated method stub
        HttpSession session=se.getSession();
        ServletContext application=session.getServletContext();
        String sessionId=session.getId();
        System.out.println("sessionId:"+sessionId);
        HashMap<String,String> online=(HashMap<String, String>) application.getAttribute("online");
        if(online!=null){
            online.remove(sessionId);
        }
        application.setAttribute("online",online);
    }
}

2、登录控制器
package Login;
import java.io.IOException;
import java.util.HashMap;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
public class LoginServlet extends HttpServlet{
    public void service(HttpServletRequest request,HttpServletResponse response)throws ServletException,IOException{
        String user=request.getParameter("user");
        String pass=request.getParameter("pass");
        HttpSession session=request.getSession();
        //session.setMaxInactiveInterval(3);
        session.setAttribute("user", user);
        session.setAttribute("pass", pass);
        ServletContext application=session.getServletContext();
        HashMap<String,String> dataMap=(HashMap<String, String>) application.getAttribute("online");
        if(dataMap==null){
            dataMap=new HashMap<String, String>();
        }
        dataMap.put(session.getId(),user);
        application.setAttribute("online", dataMap);
        try {
            //转发
            //request.getRequestDispatcher("/shop.jsp").forward(request, response);
            //重定向
            System.out.println("user1:"+session.getAttribute("user"));
            response.sendRedirect("/webPrj/shop.jsp");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

3、登录界面
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
application.setAttribute("addAttrName","addAttrValue");
application.removeAttribute("addAttrName");
application.setAttribute("newAttrName","newAttrValue");
application.setAttribute("newAttrName","1234567");
request.setAttribute("requestName1","requestValue1");
request.removeAttribute("requestName1");
request.setAttribute("requestName2","requestValue2");
request.setAttribute("requestName2","requestValue23");
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    <title>Login</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
  </head>
  <body>
    ${tip}<br>
    <form action="login?action=service" method="post">
                    名称:<input type="text" name="user"><br>
                    密码:<input type="text" name="pass"><br/>
      <input type="submit" value="登录"><input type="reset" value="重置">
    </form>
  </body>
</html>
4、在线用户显示
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    <title>My JSP 'shop.jsp' starting page</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
    <!--
    <link rel="stylesheet" type="text/css" href="styles.css">
    -->
  </head>
  <body>
    <form action="buy.jsp">
              书籍:<input type="checkbox" name="item" value="book">
              电脑:<input type="checkbox" name="item" value="computer">
              汽车:<input type="checkbox" name="item" value="car">
     <input type="submit" value="提交">
    </form>
    <h1>在线用户:</h1>
    <table>
       <tr>
          <td>ID</td>
          <td>名称</td>
       </tr>
       <%
          HashMap<String,String> online=(HashMap<String,String>)application.getAttribute("online");
          for(String sessionId:online.keySet()){
        %> 
        <tr>
           <td><%=sessionId%></td>
           <td><%=online.get(sessionId)%></td>
        </tr>
        <%
          }
       %>
    </table>
  </body>
</html>

三、使用RequestListener更精确监控用户在线状态

1、实现ServletRequestListener
package listener;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.servlet.ServletContext;
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import dao.DbDao;
public class RequestListener implements ServletRequestListener,ServletRequestAttributeListener{
    //当请求销毁时触发该方法
    public void requestDestroyed(ServletRequestEvent sre) {
        // TODO Auto-generated method stub
        HttpServletRequest request=(HttpServletRequest)sre.getServletRequest();
        System.out.println("----发向"+request.getRequestURI()+"被销毁");

    }
    //当请求初始化时触发该方法
    public void requestInitialized(ServletRequestEvent sre) {
        // TODO Auto-generated method stub
        HttpServletRequest request=(HttpServletRequest)sre.getServletRequest();
        System.out.println("---发向"+request.getRequestURI()+"被初始化");
        HttpSession session=request.getSession();
        //获取sessionId
        String sessionId=session.getId();
        //获取IP与地址
        String ip=request.getRemoteAddr();
        //获取正在访问的页面
        String page=request.getRequestURI();
        //获取用户名称
        String user=(String)session.getAttribute("user");
        user=(user==null)?"游客":user;
        DbDao db=new DbDao("com.mysql.jdbc.Driver","jdbc:mysql://localhost:3306/escshop", "root", "");
        ResultSet rs=db.query("SELECT * FROM online_information WHERE sessionId=?", true, sessionId);
        try {
            if(rs.next()) {
                 rs.updateString(4, page);
                 rs.updateString(5,String.valueOf(System.currentTimeMillis()));
                 rs.updateRow();
                 rs.close();
            }else{
                db.insert(sessionId, user, ip, page, String.valueOf(System.currentTimeMillis()));
            }
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
    //当新增属性时触发该方法
    public void attributeAdded(ServletRequestAttributeEvent srae) {
        // TODO Auto-generated method stub
        ServletContext request=srae.getServletContext();
        String name=srae.getName();
        Object value=srae.getValue();
        System.out.println(request+"范围内新增了属性名为name="+name+"\t"+"属性值为value="+value);
    }
    //当移除属性时触发该方法
    public void attributeRemoved(ServletRequestAttributeEvent srae) {
        // TODO Auto-generated method stub
        ServletContext request=srae.getServletContext();
        String name=srae.getName();
        Object value=srae.getValue();
        System.out.println(request+"范围内移除了属性名为name="+name+"\t"+"属性值为value="+value);
    }
    //当替换属性时触发该方法
    public void attributeReplaced(ServletRequestAttributeEvent srae) {
        // TODO Auto-generated method stub
        ServletContext request=srae.getServletContext();
        String name=srae.getName();
        Object value=srae.getValue();
        System.out.println(request+"范围内替换了属性名为name="+name+"\t"+"属性值为value="+value);
    }
}

2、实现ServletContextListener监听器
package listener;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.swing.Timer;

import dao.DbDao;

public class OnlineRequestListener implements ServletContextListener{
    //超过10分钟没访问则判断已经离线
    public final int MAX_MILLITS=10*60*1000;
    //应用销毁时执行此方法
    public void contextDestroyed(ServletContextEvent arg0) {
        // TODO Auto-generated method stub

    }
    //应用启动时执行此方法
    public void contextInitialized(ServletContextEvent arg0) {
        // TODO Auto-generated method stub
        //每5秒检查一次啊
        new Timer(1000*5, new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                // TODO Auto-generated method stub
                DbDao db=new DbDao("com.mysql.jdbc.Driver","jdbc:mysql://localhost:3306/escshop", "root", "");
                ResultSet rs=db.query("SELECT * FROM online_information");
                StringBuffer buff=new StringBuffer("(");
                try {
                    while (rs.next()) {
                        //如果距离时间超过上次访问时间
                        if(System.currentTimeMillis()-Long.parseLong(rs.getString("time"))>MAX_MILLITS){
                            buff.append("'");
                            buff.append(rs.getString(1));
                            buff.append("' ,");
                        }
                    }
                    System.out.println("buff:"+buff);
                    //有删除的记录
                    if(buff.length()>3){
                        buff.setLength(buff.length()-3);
                        buff.append("')");
                        //删除所有在指定时间内未访问的用户信息
                        String sql="delete from online_information where sessionId in"+buff.toString();
                        System.out.println("sql:"+sql);
                        db.delete(sql);
                    }
                } catch (SQLException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
            }
        }).start();
    }
}

3、数据库操作
package dao;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class DbDao {
    private String driver;
    private String url;
    private String user;
    private String password;
    //构造方法
    public  DbDao(String driver,String url,String user,String password){
        this.driver=driver;
        this.url=url;
        this.user=user;
        this.password=password;
    }
    //查询指定ID信息
    public ResultSet query(String sql,boolean flag,String id){
        ResultSet rs=null;
        try {
            Class.forName(driver);
            try {
                Connection conn=DriverManager.getConnection(url, user, password);
                Statement smt=conn.createStatement();
                if(flag){
                    sql=sql.replace("?","'"+id+"'");
                }
                rs=smt.executeQuery(sql);
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return rs;
    }
    //查询所有信息
    public ResultSet query(String sql){
        ResultSet rs=null;
        try {
            Class.forName(driver);
            try {
                Connection conn=DriverManager.getConnection(url, user, password);
                Statement smt=conn.createStatement();
                rs=smt.executeQuery(sql);
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return rs;
    }
    //插入信息
    public boolean insert(String sessionId,String userName,String ip,String page,String time){
        boolean flag=false;
        try {
            Class.forName(driver);
            try {
                Connection conn=DriverManager.getConnection(url, user,password);
                Statement smt=conn.createStatement();
                String sql="INSERT INTO online_information(sessionId,USER,ip,page,TIME)"
                          +"VALUES('"+sessionId+"','"+userName+"','"+ip+"','"+page+"','"+time+"')";
                System.out.println("SQL:"+sql);
                flag=smt.executeUpdate(sql)>0?true:false;
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return flag;
    }
    //删除指定的目录
    public boolean delete(String sql){
        boolean flag=false;
        try {
            Class.forName(driver);
            try {
                Connection conn=DriverManager.getConnection(url, user,password);
                Statement smt=conn.createStatement();
                flag=smt.executeUpdate(sql)>0?true:false;
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return flag;
    }
}


4、显示在线人员状态的JSP
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
<%@page import="dao.DbDao"%>
<%@page import="java.sql.ResultSet"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">

    <title>online在线人数</title>

    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
  </head>
  <body>
    <h1>当前在线人员:</h1>
    <table>
    <%
       DbDao db=new DbDao("com.mysql.jdbc.Driver","jdbc:mysql://localhost:3306/escshop", "root", "");
       ResultSet rs= db.query("SELECT * FROM online_information");
       while(rs.next()){
    %>
      <tr>
         <td><%=rs.getString(1)%></td>
         <td><%=rs.getString(2)%></td>
         <td><%=rs.getString(3)%></td>
         <td><%=rs.getString(4)%></td>
         <td><%=rs.getString(5)%></td>
      </tr>
    <%} %>
    </table>
  </body>
</html>

  • 5
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

为你写诗_xue

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值