Listener监听器笔记1
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的更多相关文章
- listener监听器笔记
listener:三个域对象的监听器,,还有属性的变化. 监听三个域对象的创建和销毁:servletContextListenerservletRequestListenerservletsessio ...
- [Java] JSP笔记 - Listener 监听器
Java Web 开发时,可以使用 Listener 来监听来监听一些事件,从而实现一些功能.实际上这个监听器,原理就是 Delphi 中大家常用的各种事件. 1. 那么,监听器的主要用途用哪些呢: ...
- Java ---Listener监听器
在我们的web容器中,一直不断的触发着各种事件,例如:web应用启动和关闭,request请求到达和结束等.但是这些事件通常对于开发者来说是透明的,我们可以根据这些接口开发符合我们自身需求的功能.在w ...
- Listener监听器和Filter过滤器
Listener监听器 WEB中的监听器 WEB 中的 Listener 和 Filter 是属于 Servlet 规范中的高级的技术.WEB中的监听器共有三类八种(监听三个域对象)* 事件源:Ser ...
- 转-JavaWeb三大组件之Listener监听器
JavaWeb三大组件之Listener监听器一.概述1,它是一个接口,内容由我们来实现 2,它需要注册,例如注册在按钮上 3,监听器中的方法,会在特殊事件发生时被调用 二.JavaWeb中的监听器1 ...
- Servlet3.0的注解自定义原生Listener监听器实战
简介:监听器介绍和Servlet3.0的注解自定义原生Listener监听器实战 自定义Listener(常用的监听器 servletContextListener.httpSessionListen ...
- 【Servlet】Java Serlvet Listener 监听器
Listener监听器 Servlet规范中定义的一种特殊的组件,用来监听Servlet容器产生的事件并进行相应的处理 容器产生的事件分类 - 生命周期相关的事件 - 设置和删除Attribute数据 ...
- 15 Filter过滤器和Listener监听器
1.Filter:过滤器 (1) 概念:生活中的过滤器:净水器,空气净化器,土匪.web中的过滤器:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能.过滤器的作用:一般用于完成通用的 ...
- .jsp文件的使用和理解以及一些小练习和Listener监听器
什么是 jsp,它有什么用? jsp 的全换是 java server pages.Java 的服务器页面.jsp 的主要作用是代替 Servlet 程序回传 html 页面的数据.因为 Servle ...
随机推荐
- Nova 如何统计 OpenStack 资源
1.云计算的本质在于将硬件资源软件化,以达到快速按需交付的效果,最基本的计算.存储和网络基础元素并没有因此改变.就计算而言,CPU.RAM 和 DISK等依旧是必不可少的核心资源. 从源代码和数据库相 ...
- SQLSTATE[HY000] [2003] Can't connect to MySQL server on 'XXX' (13)
SQLSTATE[HY000] [2003] Can't connect to MySQL server on 'XXX' (13) 我可以真见识了 SELinux 的利害了, 这个问题让我找了好长时 ...
- android 在自定义的listview(有刷新加载项)列表中,数据过少时不能铺满整个屏幕时,header和footer同时显示问题
android 在自定义的listview(有刷新加载项)列表中,数据过少时,当刷新时,加载项也会显示,这是很头疼的一个问题,查阅了一些资料,总结了一个比较不错的方法: 原来代码: @Overrid ...
- cmd中神奇的命令 prompt $g
万万没想到还可以这么玩 将java文件编译为class以后可以这样直接运行 java A<1.txt 就相当于把1.txt中的内容以模拟输入的方式输入到java中 java A>1.txt ...
- Win10 WSL Ubuntu18.04 编译安装MySQL5.7
---恢复内容开始--- 在win10 商店中选择 ubuntu18.04 下载地址 http://dev.mysql.com/downloads/mysql/ wget https://cdn.my ...
- Qt-Creator 加入qwt库
qwt是基于Qt的开源图表库 从官网下载qwt的源码 http://sourceforge.jp/projects/sfnet_qwt/downloads/qwt/6.1.0/qwt-6.1.0.ta ...
- NetScaler Active-Active模式
NetScaler Active-Active模式 NetScaler Active-Active模式 (此文档基于版本:NS9.3: Build 55.6 nc) By ShingTan Activ ...
- 【转】百度统计js被劫持用来DDOS Github
原文链接:http://drops.wooyun.org/papers/5398 今天中午刷着全国最大的信息安全从业人员同性交友社区zone.wooyun.org的时候,忽然浏览器每隔2秒就不断的弹窗 ...
- spring in action 学习笔记五:@Autowired这个注解如何理解
@Autowired这个注解的意思就是自动装配.他把一个bean对象自动装配到另一个对象中.下面的案例证明了spring的自动装配. 定义一个Sixi类.代码如下: package com.qls.a ...
- sublime text 3将px换算为rem的插件的安装及使用
标签: rem这个单位对于移动端来说是比较强大的,所以这里给大家介绍sublime text 3将px换算为rem的插件的安装及使用,只要安装了这个插件,输入多少px,sublime就会提示相应的re ...