javaweb学习总结(四十七)——监听器(Listener)在开发中的应用
监听器在JavaWeb开发中用得比较多,下面说一下监听器(Listener)在开发中的常见应用
一、统计当前在线人数
在JavaWeb应用开发中,有时候我们需要统计当前在线的用户数,此时就可以使用监听器技术来实现这个功能了。
1 package me.gacl.web.listener;
2
3 import javax.servlet.ServletContext;
4 import javax.servlet.http.HttpSessionEvent;
5 import javax.servlet.http.HttpSessionListener;
6
7 /**
8 * @ClassName: OnLineCountListener
9 * @Description: 统计当前在线用户个数
10 * @author: 孤傲苍狼
11 * @date: 2014-9-10 下午10:01:26
12 *
13 */
14 public class OnLineCountListener implements HttpSessionListener {
15
16 @Override
17 public void sessionCreated(HttpSessionEvent se) {
18 ServletContext context = se.getSession().getServletContext();
19 Integer onLineCount = (Integer) context.getAttribute("onLineCount");
20 if(onLineCount==null){
21 context.setAttribute("onLineCount", 1);
22 }else{
23 onLineCount++;
24 context.setAttribute("onLineCount", onLineCount);
25 }
26 }
27
28 @Override
29 public void sessionDestroyed(HttpSessionEvent se) {
30 ServletContext context = se.getSession().getServletContext();
31 Integer onLineCount = (Integer) context.getAttribute("onLineCount");
32 if(onLineCount==null){
33 context.setAttribute("onLineCount", 1);
34 }else{
35 onLineCount--;
36 context.setAttribute("onLineCount", onLineCount);
37 }
38 }
39 }
二、自定义Session扫描器
当一个Web应用创建的Session很多时,为了避免Session占用太多的内存,我们可以选择手动将这些内存中的session销毁,那么此时也可以借助监听器技术来实现。
1 package me.gacl.web.listener;
2
3 import java.util.Collections;
4 import java.util.LinkedList;
5 import java.util.List;
6 import java.util.ListIterator;
7 import java.util.Timer;
8 import java.util.TimerTask;
9 import javax.servlet.ServletContextEvent;
10 import javax.servlet.ServletContextListener;
11 import javax.servlet.http.HttpSession;
12 import javax.servlet.http.HttpSessionEvent;
13 import javax.servlet.http.HttpSessionListener;
14
15 /**
16 * @ClassName: SessionScanerListener
17 * @Description: 自定义session扫描器
18 * @author: 孤傲苍狼
19 * @date: 2014-9-10 下午10:16:42
20 *
21 */
22 public class SessionScanerListener implements HttpSessionListener,ServletContextListener {
23
24 /**
25 * @Field: list
26 * 定义一个集合存储服务器创建的HttpSession
27 * LinkedList不是一个线程安全的集合
28 */
29 /**
30 * private List<HttpSession> list = new LinkedList<HttpSession>();
31 * 这样写涉及到线程安全问题,SessionScanerListener对象在内存中只有一个
32 * sessionCreated可能会被多个人同时调用,
33 * 当有多个人并发访问站点时,服务器同时为这些并发访问的人创建session
34 * 那么sessionCreated方法在某一时刻内会被几个线程同时调用,几个线程并发调用sessionCreated方法
35 * sessionCreated方法的内部处理是往一个集合中添加创建好的session,那么在加session的时候就会
36 * 涉及到几个Session同时抢夺集合中一个位置的情况,所以往集合中添加session时,一定要保证集合是线程安全的才行
37 * 如何把一个集合做成线程安全的集合呢?
38 * 可以使用使用 Collections.synchronizedList(List<T> list)方法将不是线程安全的list集合包装线程安全的list集合
39 */
40 //使用 Collections.synchronizedList(List<T> list)方法将LinkedList包装成一个线程安全的集合
41 private List<HttpSession> list = Collections.synchronizedList(new LinkedList<HttpSession>());
42 //定义一个对象,让这个对象充当一把锁,用这把锁来保证往list集合添加的新的session和遍历list集合中的session这两个操作达到同步
43 private Object lock = new Object();
44
45 @Override
46 public void sessionCreated(HttpSessionEvent se) {
47 System.out.println("session被创建了!!");
48 HttpSession session = se.getSession();
49
50 synchronized (lock){
51 /**
52 *将该操作加锁进行锁定,当有一个thread-1(线程1)在调用这段代码时,会先拿到lock这把锁,然后往集合中添加session,
53 *在添加session的这个过程中假设有另外一个thread-2(线程2)来访问了,thread-2可能是执行定时器任务的,
54 *当thread-2要调用run方法遍历list集合中的session时,结果发现遍历list集合中的session的那段代码被锁住了,
55 *而这把锁正在被往集合中添加session的那个thread-1占用着,因此thread-2只能等待thread-1操作完成之后才能够进行操作
56 *当thread-1添加完session之后,就把lock放开了,此时thread-2拿到lock,就可以执行遍历list集合中的session的那段代码了
57 *通过这把锁就保证了往集合中添加session和变量集合中的session这两步操作不能同时进行,必须按照先来后到的顺序来进行。
58 */
59 list.add(session);
60 }
61 }
62
63 @Override
64 public void sessionDestroyed(HttpSessionEvent se) {
65 System.out.println("session被销毁了了!!");
66 }
67
68 /* Web应用启动时触发这个事件
69 * @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent)
70 */
71 @Override
72 public void contextInitialized(ServletContextEvent sce) {
73 System.out.println("web应用初始化");
74 //创建定时器
75 Timer timer = new Timer();
76 //每隔30秒就定时执行任务
77 timer.schedule(new MyTask(list,lock), 0, 1000*30);
78 }
79
80 @Override
81 public void contextDestroyed(ServletContextEvent sce) {
82 System.out.println("web应用关闭");
83 }
84 }
85
86 /**
87 * @ClassName: MyTask
88 * @Description:定时器要定时执行的任务
89 * @author: 孤傲苍狼
90 * @date: 2014-9-11 上午12:02:36
91 *
92 */
93 class MyTask extends TimerTask {
94
95 //存储HttpSession的list集合
96 private List<HttpSession> list;
97 //存储传递过来的锁
98 private Object lock;
99 public MyTask(List<HttpSession> list,Object lock){
100 this.list = list;
101 this.lock = lock;
102 }
103 /* run方法指明了任务要做的事情
104 * @see java.util.TimerTask#run()
105 */
106 @Override
107 public void run() {
108 //将该操作加锁进行锁定
109 synchronized (lock) {
110 System.out.println("定时器执行!!");
111 ListIterator<HttpSession> it = list.listIterator();
112 /**
113 * 迭代list集合中的session,在迭代list集合中的session的过程中可能有别的用户来访问,
114 * 用户一访问,服务器就会为该用户创建一个session,此时就会调用sessionCreated往list集合中添加新的session,
115 * 然而定时器在定时执行扫描遍历list集合中的session时是无法知道正在遍历的list集合又添加的新的session进来了,
116 * 这样就导致了往list集合添加的新的session和遍历list集合中的session这两个操作无法达到同步
117 * 那么解决的办法就是把"list.add(session)和while(it.hasNext()){//迭代list集合}"这两段代码做成同步,
118 * 保证当有一个线程在访问"list.add(session)"这段代码时,另一个线程就不能访问"while(it.hasNext()){//迭代list集合}"这段代码
119 * 为了能够将这两段不相干的代码做成同步,只能定义一把锁(Object lock),然后给这两步操作加上同一把锁,
120 * 用这把锁来保证往list集合添加的新的session和遍历list集合中的session这两个操作达到同步
121 * 当在执行往list集合添加的新的session操作时,就必须等添加完成之后才能够对list集合进行迭代操作,
122 * 当在执行对list集合进行迭代操作时,那么必须等到迭代操作结束之后才能够往往list集合添加的新的session
123 */
124 while(it.hasNext()){
125 HttpSession session = (HttpSession) it.next();
126 /**
127 * 如果当前时间-session的最后访问时间>1000*15(15秒)
128 * session.getLastAccessedTime()获取session的最后访问时间
129 */
130 if(System.currentTimeMillis()-session.getLastAccessedTime()>1000*30){
131 //手动销毁session
132 session.invalidate();
133 //移除集合中已经被销毁的session
134 it.remove();
135 }
136 }
137 }
138 }
139 }
以上就是监听器的两个简单应用场景。
javaweb学习总结(四十七)——监听器(Listener)在开发中的应用的更多相关文章
- JavaWeb学习 (二十七)————监听器(Listener)在开发中的应用
监听器在JavaWeb开发中用得比较多,下面说一下监听器(Listener)在开发中的常见应用 一.统计当前在线人数 在JavaWeb应用开发中,有时候我们需要统计当前在线的用户数,此时就可以使用监听 ...
- javaWeb学习总结(11)- 监听器(Listener)在开发中的应用
监听器在JavaWeb开发中用得比较多,下面说一下监听器(Listener)在开发中的常见应用 一.统计当前在线人数 在JavaWeb应用开发中,有时候我们需要统计当前在线的用户数,此时就可以使用监听 ...
- JavaWeb学习 (二十六)————监听器(Listener)学习(二)
一.监听域对象中属性的变更的监听器 域对象中属性的变更的事件监听器就是用来监听 ServletContext, HttpSession, HttpServletRequest 这三个对象中的属性变更信 ...
- JavaWeb学习 (二十五)————监听器(Listener)
一.监听器介绍 1.1.监听器的概念
- javaweb学习总结(二十七)——jsp简单标签开发案例和打包
一.开发标签库 1.1.开发防盗链标签 1.编写标签处理器类:RefererTag.java 1 package me.gacl.web.simpletag; 2 3 import java.io.I ...
- Android源码浅析(四)——我在Android开发中常用到的adb命令,Linux命令,源码编译命令
Android源码浅析(四)--我在Android开发中常用到的adb命令,Linux命令,源码编译命令 我自己平时开发的时候积累的一些命令,希望对你有所帮助 adb是什么?: adb的全称为Andr ...
- javaweb学习总结(四十五)——监听器(Listener)学习二
一.监听域对象中属性的变更的监听器 域对象中属性的变更的事件监听器就是用来监听 ServletContext, HttpSession, HttpServletRequest 这三个对象中的属性变更信 ...
- javaweb学习总结(四十四)——监听器(Listener)学习
一.监听器介绍 1.1.监听器的概念
- javaweb学习总结(四十一)——Apache的DBUtils框架学习
一.commons-dbutils简介 commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化 ...
随机推荐
- javascript 中的 call
Javascript中call的使用 Javascript中call的使用自己感觉蛮纠结的,根据文档很好理解,其实很难确定你是否真正的理解. call 方法应用于:Function 对象调用一个对象的 ...
- template_1
0: 模板是一些为多种类型而编写的函数和类,而且这些类型都没有指定.当使用模板的时候,只需要把所希望的类型作为一个(显示或隐示的)实参传递给模板.模板是语言本身所具有的特效,她完全支持类型检查和作用域 ...
- c++ primer (5)1
第一章 1.包含来自标准库的头文件用<>,不属于标准库用"". 2.默认情况,读cin会刷新cout:程序非正常终止时也会刷新cout. 3.默认情况,cerr不缓冲, ...
- C# 代理HTTP请求
目的: 应该有不少人需要去某些网站不停爬取数据,有时会使用HTTPRequest一直请求某个网站的某个网址.有的网站比如 QQ空间,赶集网(这是我测试的网站),不停刷新会提醒你的账号异常,可能会查封你 ...
- bzoj 1040 骑士
这题真不爽,各种WA,写个题解浏览器还挂了,真不爽. 所以不多说了,就说关于判断是否是父节点的问题,不能直接判,会有重边,这种情况只能用编号判,传进去入边的编号,(k^1) != fa,这样就可以了. ...
- Java中的堆内存、栈内存、静态存储区
一.栈 栈的优势是,存取速度比堆要快,仅次于直接位于CPU中的寄存器,当超过变量的作用域后,java会自动释放掉为该变量分配的内存空间,该内存空间可以立刻被另作他用.但缺点是,存在栈中的数据大小与生存 ...
- This bison version is not supported for regeneration of the Zend/PHP parsers
在 mac 中编译 php-src.git 报错: configure: WARNING: This bison version is not supported , excluded: ). con ...
- ES6学习笔记(九)
1.概述 ES5的对象属性名都是字符串,这容易造成属性名的冲突.比如,你使用了一个他人提供的对象,但又想为这个对象添加新的方法(mixin模式),新方法的名字就有可能与现有方法产生冲突.如果有一种机制 ...
- 添加打印机的时候怎样说windows没法连接到打印机毛病为0x00000002
把PrinterExtensionsandNotifications这个服务启动1下试试 PrintSpooler服务停止然后再启用试试
- dell inspiorn 14vr 1616b ubuntu 无线网卡的问题
找到两个解决方法: 1 找 网卡驱动下载: 用命令 以下 from :http://zhidao.baidu.com/link?url=k6QNIdJlbRyZJSEW1cVUs_1p4Jv-73c8 ...