1.常用的Web事件监听器接口:

    1.ServletContextListener:用于监听Web应用的启动和关闭。

    2.ServletContextAttributeListener:用于监听ServletContext(application)范围内属性的改变。

    3.ServletRequestListener:用于监听用户的请求。 

    4.ServletRequestAttributeListener:用于监听ServletRequest范围(request)内属性的改变。

    5.HttpSessionListener:用于监听用户session的开始和结束。

    6.HttpSessionAttributeListener:用于监听HttpSession范围(session)内属性的改变。


2.配置Listener
  1.使用@WebListener修饰Listener实现类即可;或者在web.xml中使用<listener.../>元素进行配置。

3.使用HttpSessionListener示例:
  监听系统的在线用户:实现HttpSessionListener接口的监听器,可以监听每个用户会话的开始和断开,因此可以通过该监听器监听系统的在线用户

  后台监听器代码:

/**
* Description:监听在线用户
* Author: Eleven
* Date: 2018/1/8 11:17
*/
@WebListener
public class OnlineListener implements HttpSessionListener{ //当用户与服务器之间开始session的时候触发该方法
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) { HttpSession session = httpSessionEvent.getSession();
//设置session有效时间为60秒
session.setMaxInactiveInterval(60);
System.out.println("创建"+session.getId()+",当前时间:"+System.currentTimeMillis());
ServletContext application = session.getServletContext();
//如果是一次新的会话
if(session.isNew()){
//获取session中的用户
String user = (String) session.getAttribute("user");
user = (user == null) ? "游客":user; Map<String,String> online = (Map<String, String>) application.getAttribute("online");
if(online == null){
online = new Hashtable<String,String>();
}
//将用户在线信息放入map中
online.put(session.getId(),user);
application.setAttribute("online",online);
}
} //当用户与服务器之间session断开时触发该方法
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) { System.out.println("用户与服务器之间session结束"); HttpSession session = httpSessionEvent.getSession();
System.out.println("销毁"+session.getId()+",当前时间:"+System.currentTimeMillis()); ServletContext application = session.getServletContext(); Map<String,String> online = (Map<String, String>) application.getAttribute("online");
if(online != null){
//删除该用户在线信息
online.remove(session.getId());
} application.setAttribute("online",online); }
}

 页面jsp

<%@ page import="java.util.Map" %><%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2018/1/4
Time: 16:46
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>用户在线信息</title>
</head>
<body> 在线用户:
<table width="400" border="1">
<%
//获取application中的map
Map<String,String> online = (Map<String, String>) application.getAttribute("online");
for(String sessionId:online.keySet()){
%>
<tr>
<td><%=sessionId%></td>
<td><%=online.get(sessionId)%></td>
</tr>
<%
}
%>
</table>
</body>
</html>

  接下来,在本机启动两个不同的浏览器来模拟三个用户访问该项目,访问online.jsp页面会看到有三个游客在线,如下图:

  至于为什么只用一个浏览器访问该项目的不同资源,却还是只有一个session,而打开不同的浏览器,就会创建session?这个问题,就留着之后在session中去解决哦~~

  虽然通过实现HttpSessionListener接口可以做到监听在线用户信息,但是这样比较粗糙,只能监听到多少人在线,如果要监听每个用户停留在哪个页面,用户访问的ip等信息,则应该使用HttpServletRequest来实现。

4.使用ServletRequestListener+ServletContextListener示例:

  具体的做法思路:

  写一个类实现ServletRequestListener,这个监听器就负责监听用户的每次请求,当用户请求到达时,将用户请求的sessionId,用户名,用户IP,正在访问的资源,访问时间记录下来。

  写一个类实现ServletContextListener,随web应用的启动而启动,然后在程序里另开一条线程,这个线程每隔一段时间就去检查每条在线的记录,看每条记录的访问时间与当前时间的差是否超过了一个指定值,如果超过了,就将这条在线记录删掉。

  监听用户请求的代码:

/**
* Description:监听用户的每次请求
* Author: Eleven
* Date: 2018/1/8 15:33
*/
@WebListener
public class RequestListener implements ServletRequestListener{ //当用户请求到达,被初始化时触发该方法
@Override
public void requestInitialized(ServletRequestEvent servletRequestEvent) { HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest();
//session会话被创建
HttpSession session = request.getSession();
String sessionId = session.getId();
//获取访问的ip和访问的页面
String ip = request.getRemoteAddr(); String page = request.getRequestURI();
System.out.println("当前会话:"+sessionId+",访问ip:"+ip+",访问页面:"+page);
//获取用户
String user = (String) session.getAttribute("user");
//未登录,设为游客
user = (user == null) ? "游客":user; //从数据库中查询该sessionId所对应的用户信息
try {
DbDao dd = new DbDao("com.mysql.jdbc.Driver","jdbc:mysql://localhost:3306/test","root","123456"); ResultSet rs = dd.query2("select * from online where sessionId = '"+sessionId+"' ");
//存在当前sessionId的用户信息,则表明是旧的会话
if(rs.next()){
//修改访问的page以及当前的时间
rs.updateString(4,page);
rs.updateLong(5,System.currentTimeMillis());
rs.updateRow();
rs.close();
}else{
//不存在,则存进数据库
dd.insert("insert into online values(?,?,?,?,?)",sessionId,user,ip,page,System.currentTimeMillis());
} rs.close(); } catch (Exception e) {
e.printStackTrace();
}
} //当用户请求结束,被销毁时触发该方法
@Override
public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
HttpServletRequest request = (HttpServletRequest) servletRequestEvent.getServletRequest();
String page = request.getRequestURI();
System.out.println("访问结束"+page);
}
}

  随web应用而启动,用于检测每条在线记录的监听器代码:

/**
* Description: 随web项目启动而启动,然后另开一条线程去判断用户是否已经离线
* Author: Eleven
* Date: 2018/1/12 16:45
*/
@WebListener
public class TimeListener implements ServletContextListener{ //超过该时间没有访问本站,即认为已经离线
public final int MAX_MILLIS = 1000*10*2;//2分钟 @Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
//每1分钟检查一次
new Timer(1000*60*1,new ActionListener(){ @Override
public void actionPerformed(ActionEvent e) {
try {
//从数据库中查询出所有的用户信息
DbDao dd = new DbDao("com.mysql.jdbc.Driver","jdbc:mysql://localhost:3306/test","root","123456");
ResultSet rs = dd.query("select * from online ");
StringBuffer sb = new StringBuffer();
sb.append("(");
while(rs.next()){
if(System.currentTimeMillis()-rs.getLong(5)>MAX_MILLIS){
//超过了10分钟
sb.append("'");
sb.append(rs.getString(1));
sb.append("',");
}
}
System.out.println("aa"+sb.toString());
//如果有需要删除的记录
if(sb.length()>1){
sb.setLength(sb.length()-1);
sb.append(")");
System.out.println(sb.toString());
dd.modify("delete from online where sessionId in " +sb.toString());
//删除超时的记录
}
System.out.println("需要移除的"+sb.toString());
rs.close();
dd.closeConn(); } catch (Exception e1) {
e1.printStackTrace();
}
}
}).start();
} @Override
public void contextDestroyed(ServletContextEvent servletContextEvent) { }
}

  涉及到的数据库的操作的DbDao的代码:

/**
* Description:数据库操作
* Author: Eleven
* Date: 2018/1/6 9:27
*/
public class DbDao {
private Connection conn;
private String driver;
private String url;
private String name;
private String psw; public DbDao() {
} public DbDao( String driver, String url, String name, String psw) {
this.driver = driver;
this.url = url;
this.name = name;
this.psw = psw;
} //获取数据库连接
public Connection getConnection() throws Exception{ if(conn == null){
//注册驱动
Class.forName(driver);
//获取连接
conn = DriverManager.getConnection(url,name,psw);
}
return conn;
} //查询1 动态查询
public ResultSet query(String sql,Object... args) throws Exception{ //创建Statement
PreparedStatement pstmt = getConnection().prepareStatement(sql);
//设置参数
for(int i=0;i<args.length;i++){
pstmt.setObject(i+1,args[i]);
}
return pstmt.executeQuery();
} //查询2
public ResultSet query2(String sql) throws Exception{
Statement st = getConnection().createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); return st.executeQuery(sql);
} //插入
public boolean insert(String sql,Object... args) throws Exception{
PreparedStatement pstmt = getConnection().prepareStatement(sql);
for(int i=0;i<args.length;i++){
pstmt.setObject(i+1,args[i]);
} if(pstmt.executeUpdate() != 1){
return false;
}
return true;
} //修改或删除
public void modify(String sql,Object... args) throws Exception{
PreparedStatement pstmt = getConnection().prepareStatement(sql);
for(int i=0;i<args.length;i++){
pstmt.setObject(i+1,args[i]);
}
pstmt.executeUpdate();
pstmt.close();
} //关闭数据库连接
public void closeConn() throws Exception{
if(conn != null && !conn.isClosed()){
conn.close();
}
} public Connection getConn() {
return conn;
} public void setConn(Connection conn) {
this.conn = conn;
} public String getDriver() {
return driver;
} public void setDriver(String driver) {
this.driver = driver;
} public String getUrl() {
return url;
} public void setUrl(String url) {
this.url = url;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getPsw() {
return psw;
} public void setPsw(String psw) {
this.psw = psw;
}
}

  页面jsp代码:

<%@ page import="java.sql.ResultSet" %>
<%@ page import="servlet.DbDao" %><%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2018/1/4
Time: 16:46
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>用户在线信息</title>
</head>
<body> 在线用户:
<table width="400" border="1">
<%
//从数据库总查询出所有的记录
DbDao dd = new DbDao("com.mysql.jdbc.Driver","jdbc:mysql://localhost:3306/test","root","123456");
ResultSet rs = dd.query("select * from online");
while(rs.next()){
%>
<tr>
<td><%=rs.getString(1)%></td>
<td><%=rs.getString(2)%></td>
<td><%=rs.getString(3)%></td>
<td><%=rs.getString(4)%></td>
</tr>
<%
}
%>
</table>
</body>
</html>

  最后打开不同的浏览器去访问该项目的不同页面,然后再去访问online2.jsp,可以看到如下图的效果:

Listener监听器笔记1的更多相关文章

  1. listener监听器笔记

    listener:三个域对象的监听器,,还有属性的变化. 监听三个域对象的创建和销毁:servletContextListenerservletRequestListenerservletsessio ...

  2. [Java] JSP笔记 - Listener 监听器

    Java Web 开发时,可以使用 Listener 来监听来监听一些事件,从而实现一些功能.实际上这个监听器,原理就是 Delphi 中大家常用的各种事件. 1. 那么,监听器的主要用途用哪些呢: ...

  3. Java ---Listener监听器

    在我们的web容器中,一直不断的触发着各种事件,例如:web应用启动和关闭,request请求到达和结束等.但是这些事件通常对于开发者来说是透明的,我们可以根据这些接口开发符合我们自身需求的功能.在w ...

  4. Listener监听器和Filter过滤器

    Listener监听器 WEB中的监听器 WEB 中的 Listener 和 Filter 是属于 Servlet 规范中的高级的技术.WEB中的监听器共有三类八种(监听三个域对象)* 事件源:Ser ...

  5. 转-JavaWeb三大组件之Listener监听器

    JavaWeb三大组件之Listener监听器一.概述1,它是一个接口,内容由我们来实现 2,它需要注册,例如注册在按钮上 3,监听器中的方法,会在特殊事件发生时被调用 二.JavaWeb中的监听器1 ...

  6. Servlet3.0的注解自定义原生Listener监听器实战

    简介:监听器介绍和Servlet3.0的注解自定义原生Listener监听器实战 自定义Listener(常用的监听器 servletContextListener.httpSessionListen ...

  7. 【Servlet】Java Serlvet Listener 监听器

    Listener监听器 Servlet规范中定义的一种特殊的组件,用来监听Servlet容器产生的事件并进行相应的处理 容器产生的事件分类 - 生命周期相关的事件 - 设置和删除Attribute数据 ...

  8. 15 Filter过滤器和Listener监听器

    1.Filter:过滤器 (1) 概念:生活中的过滤器:净水器,空气净化器,土匪.web中的过滤器:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能.过滤器的作用:一般用于完成通用的 ...

  9. .jsp文件的使用和理解以及一些小练习和Listener监听器

    什么是 jsp,它有什么用? jsp 的全换是 java server pages.Java 的服务器页面.jsp 的主要作用是代替 Servlet 程序回传 html 页面的数据.因为 Servle ...

随机推荐

  1. Python网络编程(weekly summary1)

    网络的目的是什么?     用于信息传输.接受  能把各个点.面.体的信息链接到一起 实现资源的共享 OSI模型:     应用层:提供程序服务     表示层:数据加密.优化.压缩     会话层: ...

  2. (原)Skeletal With DirectX12

    @author: 白袍小道 @来源: Advanced Animation with DirectX, 游戏引擎架构         (暗影不解释连招)     引言: 3D模型动画的基本原理是让模型 ...

  3. springboot08 jdbc

    一.JDBC&连接池 1. jdbc介绍 ​ JDBC(Java DataBase Connectivity ,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数 ...

  4. SpringBoot Rabbitmq发送消息

    官方文档:https://docs.spring.io/spring-boot/docs/2.1.3.RELEASE/reference/htmlsingle/#boot-features-amqp ...

  5. BATCH梯度下降,单变量线性回归

  6. 使AD域控服务器Administrator的密码永不过期方法。

    在安装完AD域后,管理员密码会42天就要更新一次,这样对测试比较不方便, 如果要让域控管理员账号密码永远不过期,就照着下面的方法执行: open a Command Prompt as the adm ...

  7. js得到时间戳(10位数)

    //从1970年开始的毫秒数然后截取10位变成 从1970年开始的秒数 function timest() { var tmp = Date.parse( new Date() ).toString( ...

  8. Javascript时间差计算函数代码实例

    Javascript时间差计算函数代码实例 <script language="javascript"> Date.prototype.dateDiff = funct ...

  9. [hdu1695] GCD ——欧拉函数+容斥原理

    题目 给定两个区间[1, b], [1, d],统计数对的个数(x, y)满足: \(x \in [1, b]\), \(y \in [1, d]\) ; \(gcd(x, y) = k\) HDU1 ...

  10. 让JavaScript像C#一样支持Region

    问题 Web Essentials 是非常给力的js插件,具体的介绍,大家请看这里,最锋利的Visual Studio Web开发工具扩展:Web Essentials详解 . 不过在使用的过程中,让 ...