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. Mysql与Oracle之间的数据类型转换

    MySQL Data Type Oracle Data Type BIGINT NUMBER(19, 0) BIT RAW BLOB BLOB, RAW CHAR CHAR DATE DATE DAT ...

  2. 【转载】Unity插件研究院之自动保存场景

    原文: http://wiki.unity3d.com/index.php?title=AutoSave  最近发现Unity老有自动崩溃的BUG. 每次崩溃的时候由于项目没有保存所以Hierarch ...

  3. 孤荷凌寒自学python第六十四天学习mongoDB的基本操作并进行简单封装3

    孤荷凌寒自学python第六十四天学习mongoDB的基本操作并进行简单封装3 (完整学习过程屏幕记录视频地址在文末) 今天是学习mongoDB数据库的第十天. 今天继续学习mongoDB的简单操作, ...

  4. 孤荷凌寒自学python第十九天python函数嵌套与将函数作为返回对象及闭包与递归

    孤荷凌寒自学python第十九天python函数嵌套与将函数作为返回对象及闭包与递归 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) Python函数非常的灵活,今天学习了python函数的以 ...

  5. 孤荷凌寒自学python第十八天python变量的作用范围

    孤荷凌寒自学python第十八天python函数的形参与变量的范围 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 一.在python的函数中各种不同的形式参数在定义的先后顺序上有规定: 必须 ...

  6. RGB和YUV、YCbCr 以及格式的转换总结

    比较好的文章收集链接: https://www.douban.com/note/76361504/ http://blog.sina.com.cn/s/blog_a85e142101010h8n.ht ...

  7. Python 第一周编程作业

    一.  编程题 1.  结合turtle库使用手册,读懂下列代码,并在jupyter编译器中运行观察结果: 依次分析下代码: 第一行 通过保留字import引用了Python中用于绘制图形的turtl ...

  8. linux误删除恢复

    extundelete 大家基本都知道,在linux上误删除了东西后果是很严重的,尤其是在服务器上误删除了东西,对于字符终端,想要实现恢复删除的数据更是难上加难,对于Linux误删除了重要的东西,虽然 ...

  9. 201621123034 《Java程序设计》第8周学习总结

    作业08-集合 1. 本周学习总结 以你喜欢的方式(思维导图或其他)归纳总结集合相关内容. 2. 书面作业 1. ArrayList代码分析 1.1 解释ArrayList的contains源代码 答 ...

  10. 【Luogu】P2498拯救小云公主(spfa)

    题目链接 我水爆了- - 容易发现可以把两个圆之间连边,左上为起点右下为终点,最小生成树直到起点跟终点连起来,输出边权/2就行. 然后80. 并不理解为什么这可以转化成spfa求最短路,邻接矩阵暴力跑 ...