java中servletContextListener、httpSessionListener和servletRequestListener使用整理
在java web应用中,listener监听器似乎是必不可少的,常常用来监听servletContext、httpSession、servletRequest等域对象的创建、销毁以及属性的变化等等,可以在这些事件动作前后进行一定的逻辑处理。
比较常用的应用场景是利用监听器来初始化一些数据、统计在线人数、统计web应用浏览量等等。
这里所说的监听器实际上是servlet规范中定义的一种特殊类,需要实现特定的接口。
而我暂时先说其中三个用来监听域对象的,分别是servletContextListener、httpSessionListener、servletRequestListener。
这三个接口写法上实际是差不多的,都有两个分别代表了该域对象创建时调用和销毁时调用的方法,据我的理解,这三个对象最大的区别应该就是作用域不一样。
servletContext在整个应用启动到结束中生效,启动系统时创建这个对象,整个过程中这个对象是唯一的。
httpSession则是在一个session会话中生效,在一个session被创建直到失效的过程中都起作用,不过一个启动的应用中httpSession对象可以有多个,比如同一台电脑两个浏览器访问,就会创建两个httpSession对象。
而servletRequest是在一个request请求被创建和销毁的过程中生效,每发起一次请求就会创建一个新的servletRequest对象,比如刷新浏览器页面、点击应用的内链等等。
这三个监听器的写法基本如下伪代码所示:
首先创建一个监听器类实现相应的接口及方法:
package packageName;
public class ListenerName implements *Listener {
@Override
public void 对象创建时被调用的方法(相应的事件 arg0) {
}
@Override
public void 对象销毁时被调用的方法(相应的事件 arg0) {
}
}
然后在web.xml中注册:
<listener>
<listener-class>packageName.ListenerName</listener-class>
</listener>
到这里,基本上这个监听器在启动web服务器以后就可以正常跑了,只是有时候我们还会在注册监听器的时候配置一些其他的。
比如配置servletContextListener的时候,可能会加上context-param参数:
<context-param>
<param-name>paramName</param-name>
<param-value>paramValue</param-value>
</context-param>
配置httpSessionListener的时候,可能会加上session超时:
<session-config>
<session-timeout>1</session-timeout>
</session-config>
我感觉经过这样一整理后,就会发现起始监听器写起来还是很简单的,于是便模拟简单的实现了在线用户统计和应用访问量,基本代码如下:
首先是实现了servletContext
package webTest;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Date;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
public class ListenerTest1 implements ServletContextListener {
@Override
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("contextDestroyed" + "," + new Date());
Object count = arg0.getServletContext().getAttribute("count");
File file = new File("count.txt");
try {
FileOutputStream fileOutputStream = new FileOutputStream(file);
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "utf-8");
BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
bufferedWriter.write(count.toString());
bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void contextInitialized(ServletContextEvent arg0) {
System.out.println("contextInitialized" + "," + new Date());
File file = new File("count.txt");
if (file.exists()) {
try {
FileInputStream fileInputStream = new FileInputStream(file);
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "utf-8");
BufferedReader bReader = new BufferedReader(inputStreamReader);
String count = bReader.readLine();
System.out.println("历史访问次数:" + count);
arg0.getServletContext().setAttribute("count", count);
bReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
这里我把访问次数存在一个txt文件中,以便于持久化保存,当项目启动的时候,也就是创建servletContext对象的时候调用加载方法,从txt文件中读取历史访问量,然后使用setAttribute方法把这个数据存入到内存中。
之后当应用被关闭,servletContext对象被销毁的时候把内存中新的访问量数据覆盖写入到txt文件,以便于下次启动应用后继续读取之前的访问量。
然后使用servletRequestListener来实现web浏览量的变化,当然了,这里只是简单的实现,如果是要实现那种同一个用户刷新页面不增加浏览量的功能,还需要做更多的处理。
package webTest;
import java.util.Date;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
public class ListenerTest3 implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent arg0) {
System.out.println("requestDestroyed" + "," + new Date());
System.out.println("当前访问次数:" + arg0.getServletContext().getAttribute("count"));
}
@Override
public void requestInitialized(ServletRequestEvent arg0) {
System.out.println("requestInitialized" + "," + new Date());
Object count = arg0.getServletContext().getAttribute("count");
Integer cInteger = 0;
if (count != null) {
cInteger = Integer.valueOf(count.toString());
}
System.out.println("历史访问次数::" + count);
cInteger++;
arg0.getServletContext().setAttribute("count", cInteger);
}
}
这里同样是两个方法,在servletRequest对象被建立的时候调用初始化方法,从内存中读取servletContext对象的count属性,而后输出历史访问量。
同时在此基础上加一重新设置servletContext对象的count属性的内容,当servletRequest对象被销毁的时候调用销毁时的方法打印出当前浏览量,这样就简单的实现了web浏览的量的累加计数。
然后就是利用httpSessionListener来实现在线人数的统计:
package webTest;
import java.util.Date;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class ListenerTest2 implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent arg0) {
System.out.println("sessionCreated" + "," + new Date());
Object lineCount = arg0.getSession().getServletContext().getAttribute("lineCount");
Integer count = 0;
if (lineCount == null) {
lineCount = "0";
}
count = Integer.valueOf(lineCount.toString());
count++;
System.out.println("新上线一人,历史在线人数:" + lineCount + "个,当前在线人数有: " + count + " 个");
arg0.getSession().getServletContext().setAttribute("lineCount", count);
}
@Override
public void sessionDestroyed(HttpSessionEvent arg0) {
System.out.println("sessionDestroyed" + "," + new Date());
Object lineCount = arg0.getSession().getServletContext().getAttribute("lineCount");
Integer count = Integer.valueOf(lineCount.toString());
count--;
System.out.println("一人下线,历史在线人数:" + lineCount + "个,当前在线人数: " + count + " 个");
arg0.getSession().getServletContext().setAttribute("lineCount", count);
}
}
这里的代码都很简单,我想应该没有太多必要解释,需要说明的是,我这里把lineCount存放在servletContext对象中并不是唯一的方式,有兴趣的朋友可以尝试其他的方式,例如使用类属性。
这里的示例也已打包上传,需要的朋友可以自行下载运行。
链接:http://pan.baidu.com/s/1bZ2vx0
密码:ekb9
java中servletContextListener、httpSessionListener和servletRequestListener使用整理的更多相关文章
- 沉淀再出发:java中的CAS和ABA问题整理
沉淀再出发:java中的CAS和ABA问题整理 一.前言 在多并发程序设计之中,我们不得不面对并发.互斥.竞争.死锁.资源抢占等等问题,归根到底就是读写的问题,有了读写才有了增删改查,才有了所有的一切 ...
- <Listener>servletContextListener、httpSessionListener和servletRequestListener使用整理
在java web应用中,listener监听器似乎是不可缺少的.经常常使用来监听servletContext.httpSession.servletRequest等域对象的创建.销毁以及属性的变化等 ...
- Java中的Collections类
转载:https://blog.csdn.net/yangxingpa/article/details/80515963 从[Java]Java中的Collections类——Java中升级版的数据结 ...
- JAVA中去掉空格经典整理
JAVA中去掉空格经典整理 JAVA中去掉空格 1. String.trim() --------------trim()是去掉首尾空格 2.str.replac ...
- Java中实现多线程关键词整理
Java中的Runable,Callable,Future,FutureTask,ExecutorService,Excetor,Excutors,ThreadPoolExcetor在这里对这些关键词 ...
- 各大公司Java面试题收录含答案(整理版)持续中....
本文分为17个模块,分别是:Java基础.容器.多线程.反射.对象拷贝.Java web.异常.网络.设计模式.算法.Spring/Spring MVC.Spring Boot/Spring Clou ...
- java中的字符串相关知识整理
字符串为什么这么重要 写了多年java的开发应该对String不陌生,但是我却越发觉得它陌生.每学一门编程语言就会与字符串这个关键词打不少交道.看来它真的很重要. 字符串就是一系列的字符组合的串,如果 ...
- java中的IO整理
写在前面:本文章基本覆盖了java IO的全部内容,java新IO没有涉及,因为我想和这个分开,以突出那个的重要性,新IO哪一篇文章还没有开始写,估计很快就能和大家见面.照旧,文章依旧以例子为主,因为 ...
- java中反射学习整理
转载请注明:http://blog.csdn.net/j903829182/article/details/38405735 反射主要是指程序能够訪问.检測和改动它本身的状态或行为的一种能力. jav ...
随机推荐
- 主函数特别之处:public static void main(String[] args)
public static void main(String[] args) public class Test_java {//主函数特殊之处 public static void main(Str ...
- Nginx Https配置不带www跳转www
把 morethink.cn和www.morethink.cn合并到一个server上去,使用301永久重定向. 然后将 https://morethink.cn 转到 https://www.mor ...
- 多线程编程学习笔记——编写一个异步的HTTP服务器和客户端
接上文 多线程编程学习笔记——使用异步IO 二. 编写一个异步的HTTP服务器和客户端 本节展示了如何编写一个简单的异步HTTP服务器. 1.程序代码如下. using System; using ...
- ABP官方文档翻译 5.1 Web API控制器
ASP.NET Web API控制器 介绍 AbpApiController基类 本地化 其他 过滤器 审计日志 授权 反伪造过滤器 工作单元 结果包装和异常处理 结果缓存 校验 模型绑定器 介绍 A ...
- GreenDao 兼容升级,保留旧数据的---全方面解决方案
作者:林冠宏 / 指尖下的幽灵 掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8 博客:http://www.cnblogs.com/linguan ...
- 利用QuickCHM制作chm
CHM是一种常见的帮助文件格式,也是电子书的一种格式. 下面是使用QuickCHM制作chm的步骤: 1.先将所有的word文档存储为mht格式,点击,文件--另存为网页,如下 2.确保所有的word ...
- 洛谷 [P2766] 最长不下降子序列问题
啊啊啊,再把MAXN和MAXM搞反我就退役 层次图求不相交路径数 第一问简单DP 第二问想办法把每一个不上升子序列转化成DAG上的一条路径,就转换成了求不相交路径数 因为每一个数只能用一次,所以要拆点 ...
- CF 716E. Digit Tree [点分治]
题意:一棵树,边上有一个个位数字,走一条路径会得到一个数字,求有多少路径得到的数字可以整除\(P\) 路径统计一般就是点分治了 \[ a*10^{deep} + b \ \equiv \pmod P\ ...
- iPad Pro 10.5+Apple Pencil之专注文献阅读与笔记效率的App综述
先谈谈我对笔记类App的几点要求--原则是取其精华,略其糟粕,毕竟开发者们还在,App就会不断地被改进: 增删快捷方便:如完美支持Apple Pencil,特定场景下强大的录音功能,单词或短句涂改即可 ...
- SDN第四次上机作业
1.建立以下拓扑,并连接上ODL控制器. 2.利用ODL下发流表,使得h3在10s内ping不通h1,10s后恢复. 3.借助Postman通过ODL的北向接口下发流表,再利用ODL北向接口查看已下发 ...