监听器在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)在开发中的应用的更多相关文章

  1. javaweb学习总结(四十七)——监听器(Listener)在开发中的应用

    监听器在JavaWeb开发中用得比较多,下面说一下监听器(Listener)在开发中的常见应用 一.统计当前在线人数 在JavaWeb应用开发中,有时候我们需要统计当前在线的用户数,此时就可以使用监听 ...

  2. javaWeb学习总结(11)- 监听器(Listener)在开发中的应用

    监听器在JavaWeb开发中用得比较多,下面说一下监听器(Listener)在开发中的常见应用 一.统计当前在线人数 在JavaWeb应用开发中,有时候我们需要统计当前在线的用户数,此时就可以使用监听 ...

  3. VMware vSphere 服务器虚拟化之二十七桌面虚拟化之View中使用Thinapp软件虚拟化

    VMware vSphere 服务器虚拟化之二十七桌面虚拟化之View中使用Thinapp软件虚拟化 VMware ThinApp 应用程序虚拟化软件是无代理解决方案,通过将应用程序隔离并封装为EXE ...

  4. JavaWeb学习 (二十六)————监听器(Listener)学习(二)

    一.监听域对象中属性的变更的监听器 域对象中属性的变更的事件监听器就是用来监听 ServletContext, HttpSession, HttpServletRequest 这三个对象中的属性变更信 ...

  5. JavaWeb学习 (二十五)————监听器(Listener)

    一.监听器介绍 1.1.监听器的概念

  6. JavaWeb学习 (二十一)————基于Servlet+JSP+JavaBean开发模式的用户登录注册

    一.Servlet+JSP+JavaBean开发模式(MVC)介绍 Servlet+JSP+JavaBean模式(MVC)适合开发复杂的web应用,在这种模式下,servlet负责处理用户请求,jsp ...

  7. JavaWeb学习 (二十)————JavaWeb的两种开发模式

    一.JSP+JavaBean开发模式 1.1.jsp+javabean开发模式架构 jsp+javabean开发模式的架构图如下图(图1-1)所示

  8. Java开发学习(二十七)----SpringMVC之Rest风格解析及快速开发

    一.REST简介 REST(Representational State Transfer),表现形式状态转换,它是一种软件架构风格 当我们想表示一个网络资源的时候,可以使用两种方式: 传统风格资源描 ...

  9. javaweb学习总结十七(web应用组织结构、web.xml作用以及配置虚拟主机搭建网站)

    一:web应用组织结构 1:web应用组成结构 2:安装web组成机构手动创建一个web应用程序目录 a:在webapps下创建目录web b:在web目录下创建html.jsp.css.js.WEB ...

随机推荐

  1. Java多线程系列1 线程创建以及状态切换

    我们知道线程线程有三种创建方式 1实现Runnable接口 2 继承Thread类 3使用Callable和Future接口创建线程.具体是创建Callable接口的实现类,并实现clall()方法. ...

  2. PyCharm选择性忽略PEP8代码风格警告信息

    用了几天的PyCharm,发现确实在编写Python代码上非常好用,但有一点体验不太好,就是代码编写时要按照PEP8代码风格编写,不然会有波浪线的警告信息.解决方法如下: 方法一: 将鼠标移到提示的地 ...

  3. JNI 记

    Java Native Interface(JNI)从零开始详细教程  ================================================================ ...

  4. 别人的Linux私房菜(5)首次CentOS7与帮助等

    ctrl alt F1-F6切换终端tty1-6,其中,F1的终端带有用户界面. 在终端登录后,输入startx启动个人图形界面.(启动有一些条件限制,如没有其他的X Window启用,已经安装,并具 ...

  5. boost--内存池

    boost的内存池实现了一个快速.紧凑的内存分配和管理器,使用它可以完全不用考虑delete释放问题.常用的boost内存池有pool.object_pool.singleton_pool. 1.po ...

  6. 03-jQuery动画效果

    Query提供的一组网页中常见的动画效果,这些动画是标准的.有规律的效果:同时还提供给我们了自定义动画的功能. 显示动画 方式一: $("div").show(); 解释:无参数, ...

  7. python20分钟入门

    原子类型 # 内建函数名不可以做变量名如sum,ord abs(-1) # 1 d = dict() # d = {}空字典的构造 l = list() # l = [] s = set(list) ...

  8. Mac Terminal open app with a file opened

    open -a /Applications/Sublime Text.app test.cpp

  9. [算法专题] 深度优先搜索&回溯剪枝

    1. Palindrome Partitioning https://leetcode.com/problems/palindrome-partitioning/ Given a string s, ...

  10. Linux下Redis安装使用教程

    https://redis.io/download 第一步:安装redis需要在有c语言的编译环境下,执行命令安装c语言环境: yum install gcc-c++ https://blog.csd ...