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 ...
随机推荐
- Mysql与Oracle之间的数据类型转换
MySQL Data Type Oracle Data Type BIGINT NUMBER(19, 0) BIT RAW BLOB BLOB, RAW CHAR CHAR DATE DATE DAT ...
- 【转载】Unity插件研究院之自动保存场景
原文: http://wiki.unity3d.com/index.php?title=AutoSave 最近发现Unity老有自动崩溃的BUG. 每次崩溃的时候由于项目没有保存所以Hierarch ...
- 孤荷凌寒自学python第六十四天学习mongoDB的基本操作并进行简单封装3
孤荷凌寒自学python第六十四天学习mongoDB的基本操作并进行简单封装3 (完整学习过程屏幕记录视频地址在文末) 今天是学习mongoDB数据库的第十天. 今天继续学习mongoDB的简单操作, ...
- 孤荷凌寒自学python第十九天python函数嵌套与将函数作为返回对象及闭包与递归
孤荷凌寒自学python第十九天python函数嵌套与将函数作为返回对象及闭包与递归 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) Python函数非常的灵活,今天学习了python函数的以 ...
- 孤荷凌寒自学python第十八天python变量的作用范围
孤荷凌寒自学python第十八天python函数的形参与变量的范围 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 一.在python的函数中各种不同的形式参数在定义的先后顺序上有规定: 必须 ...
- RGB和YUV、YCbCr 以及格式的转换总结
比较好的文章收集链接: https://www.douban.com/note/76361504/ http://blog.sina.com.cn/s/blog_a85e142101010h8n.ht ...
- Python 第一周编程作业
一. 编程题 1. 结合turtle库使用手册,读懂下列代码,并在jupyter编译器中运行观察结果: 依次分析下代码: 第一行 通过保留字import引用了Python中用于绘制图形的turtl ...
- linux误删除恢复
extundelete 大家基本都知道,在linux上误删除了东西后果是很严重的,尤其是在服务器上误删除了东西,对于字符终端,想要实现恢复删除的数据更是难上加难,对于Linux误删除了重要的东西,虽然 ...
- 201621123034 《Java程序设计》第8周学习总结
作业08-集合 1. 本周学习总结 以你喜欢的方式(思维导图或其他)归纳总结集合相关内容. 2. 书面作业 1. ArrayList代码分析 1.1 解释ArrayList的contains源代码 答 ...
- 【Luogu】P2498拯救小云公主(spfa)
题目链接 我水爆了- - 容易发现可以把两个圆之间连边,左上为起点右下为终点,最小生成树直到起点跟终点连起来,输出边权/2就行. 然后80. 并不理解为什么这可以转化成spfa求最短路,邻接矩阵暴力跑 ...