Listener的简单介绍及使用

来源:互联网 发布:音乐相册制作软件排名 编辑:程序博客网 时间:2024/06/07 14:37

一、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、实现ServletRequestListenerpackage 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>