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. coreos ipa image Injection of public key

    查看readme To embed the oem/ directory into a CoreOS pxe image:   Note: In order to have the ability t ...

  2. mongodb 部署

    安装mongodb-3.4 1)将安装包上传至服务器 2)对压缩文件进行解压 tar -zxvf mongodb-linux-x86_64-suse12-v3.4-latest.tar.gz 3)把解 ...

  3. ubuntu wifi连接出现Network service discovery disabled的解决办法

    修改/etc/default/avahi-daemon,将AVAHI_DAEMON_DETECT_LOCAL从1改为0(关闭avahi) ------------------------------- ...

  4. UVALive 5029 字典树

    E - Encoded Barcodes Crawling in process...Crawling failedTime Limit:3000MS    Memory Limit:0KB    6 ...

  5. Access连接字符串

    Access2007没有密码连接: <connectionStrings> <add name="myconn" connectionString="P ...

  6. windows安装 Nodejs,NPM, CNPM

    1, dowload Nodejs from :  http://nodejs.cn/download/ 下载完毕后,可以安装node,建议不要安装在系统盘(本例安装在 D:\vueProject) ...

  7. BZOJ1086 [SCOI2005]王室联邦 【dfs + 贪心】

    题目 "余"人国的国王想重新编制他的国家.他想把他的国家划分成若干个省,每个省都由他们王室联邦的一个成 员来管理.他的国家有n个城市,编号为1..n.一些城市之间有道路相连,任意两 ...

  8. jquery defered的progress方法实现进度条

    效果如图: 实现代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset=&qu ...

  9. 手把手搭建一个完整的javaweb项目

    手把手搭建一个完整的javaweb项目 本案例使用Servlet+jsp制作,用MyEclipse和Mysql数据库进行搭建,详细介绍了搭建过程及知识点. 下载地址:http://download.c ...

  10. freemarker 前端 判读 遍历 取值

    <#if content?length gt 100> ${content[0..100]}... <#else> ${content} </#if> freema ...