监听器在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. SQLite 安装

    Windows 平台安装 下载地址:https://www.sqlite.org/download.html 下载预编译的安装包 将下载的安装包=解压到一个文件夹,有三个重要文件: sqlite3.e ...

  2. java 线程池简单例子

    package com.hra.riskprice; import com.hra.riskprice.SysEnum.Factor_Type; import com.hra.riskprice.po ...

  3. 把router-link标签渲染成指定的标签

    <router-link>标签默认渲染成 <a>标签,可以通过tag属性把router-link渲染成指定的标签,如: <router-link to="/&q ...

  4. MFC源码解读(一)最原始一个MFC程序,手写不用向导

    从这一篇开始,详细记录一下MFC的源码解读 四个文件,分别为: stdafx.h,stdafx.cpp,hello.h,hello.cpp 代码如下: //stdafx.h #include < ...

  5. 前端之html概述及基本结构

    html概述: HTML是 HyperText Mark-up Language 的首字母简写,意思是超文本标记语言,超文本指的是超链接,标记指的是标签,是一种用来制作网页的语言,这种语言由一个个的标 ...

  6. 《大型网站系统与Java中间件实践》

    读了一下,个人认为最好的部分,就是第四章了. CH04 服务框架 4.2 服务设计与实现 // 获取可用服务地址列表 // 确定调用服务目标机器 // 建立连接(Socket) // 请求序列化 // ...

  7. pgsqls修改表字段长度

    alter table T_RPACT_PROTO_EDIT_RECORD alter column remark type VARCHAR(1024); 需要注意type关键字

  8. DevExpress--TreeList节点添加图片

    这个过程相对来说比较简单,网上也有不少资料,但是自己在做过之后为了记住,算是给自己写一个博客吧. 下面直接上具体的流程 1.前提 控件使用的都是DevExpress和winform的原生控件两种: 2 ...

  9. Alpha代码规范、冲刺任务与计划

    Alpha代码规范.冲刺任务与计划 团队名称: 云打印 作业要求: Alpha代码规范.冲刺任务与计划 作业目标:代码规范.冲刺任务与计划. 团队队员 队员学号 队员姓名 个人博客地址 备注 2216 ...

  10. Linux pwn入门教程(1)——栈溢出基础

    作者:Tangerine@SAINTSEC 原文来自:https://bbs.ichunqiu.com/thread-42241-1-1.html 0×00 函数的进入与返回 要想理解栈溢出,首先必须 ...