监听器在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学习总结(11)- 监听器(Listener)在开发中的应用的更多相关文章

  1. JavaWeb学习 (二十七)————监听器(Listener)在开发中的应用

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

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

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

  3. javaweb学习总结二十二(servlet开发中常见的问题汇总)

    一:web应用的映射问题 通常我们从别人那里拷贝来的代码,自己会修改应用的名称,但是web映射的访问路径并没有修改,还是原来的映射. 解决方法: 工程右键--properties--myeclipse ...

  4. javaweb学习总结(四十三)——Filter高级开发

    在filter中可以得到代表用户请求和响应的request.response对象,因此在编程中可以使用Decorator(装饰器)模式对request.response对象进行包装,再把包装对象传给目 ...

  5. JavaWeb学习笔记八 监听器

    监听器Listener jservlet规范包括三个技术点:servlet :listener :filter:监听器就是监听某个对象的的状态变化的组件.监听器的相关概念事件源: 被监听的对象(三个域 ...

  6. ios学习笔记之block在ios开发中的应用

    一.什么是Blocks      Block是一个C级别的语法以及运行时的一个特性,和标准C中的函数(函数指针)类似,但是其运行需要编译器和运行时支持,从ios4.0开始就很好的支持Block. 二. ...

  7. JavaWeb学习总结第四篇--Servlet开发

    Servlet开发 用户在浏览器中输入一个网址并回车,浏览器会向服务器发送一个HTTP请求.服务器端程序接受这个请求,并对请求进行处理,然后发送一个回应.浏览器收到回应,再把回应的内容显示出来.这种请 ...

  8. javaWeb学习之运用myeclipse结合tomcat开发一些简单的jsp和service

    servlet是什么?     servlet是java服务器端编程.不同于我们之前写的一般的java应用程序,Servlet程序是运行在服务器上的,服务器有很多种.....现在只是用过 tomcat ...

  9. JavaWeb学习记录(十九)——开发JSTL自定义标签

    一.防盗链标签 import javax.servlet.http.HttpServletResponse;import javax.servlet.jsp.JspException;import j ...

随机推荐

  1. ajax第三步

    ajaxSend()函数用于设置当AJAX请求即将被发送时执行的回调函数. 这是一个全局AJAX事件函数,用于为任何AJAX请求的ajaxSend事件绑定事件处理函数.当AJAX请求即将被发送时,将触 ...

  2. 重新认识JavaScript里的创建对象(一)

    一.序 面向对象有一个标志,那就是它们都有类的概念,而通过类可以创建任意多个具有相同属性和方法的对象.ECMA-262把对象定义为"无序属性的集合,其属性可以包含基本值.对象或者函数&quo ...

  3. linux环境下安装jdk(本文示例是jdk1.6.0_export JAVA_HOME=/usr/java/jdk1.6.0_45 export PATH=$JAVA_HOME/bin:$PATH export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar45)

    第一步:创建一个文件夹安装jdk(虽说地址一般自定义,但是为了方便查找请按照笔者建议目录 ):/usr/java 将jdk-6u45-linux-x64.bin文件放到   /usr/java 文件夹 ...

  4. 在Centos中yum安装和卸载软件的使用方法

    安装一个软件时 yum -y install httpd 安装多个相类似的软件时 yum -y install httpd* 安装多个非类似软件时 yum -y install httpd php p ...

  5. 记因PHP的内存溢出导致的事故之解决

    如果对您有用记得关注,更多干货. 今天上午刚到公司,就有同事在公司群里反映某个计划任务出现问题了.我就怀着刨根问底的心,去查看了log.发现挺有意思的一个问题,PHP内存溢出导致脚本执行失败.那就一起 ...

  6. 第一章 自定义MVC框架

    第一章  自定义MVC框架1.1 MVC模式设计    组成:Model:模型,用于数据和业务的处理          View :视图,用于数据的显示          Controller:控制器 ...

  7. 在Oracle中添加用户登录名称

    第一步,打开Oracle客户端单击 “帮助”-->"支持信息"-->”TNS名“,加入红色部分.页面如下: 第二步,再次打开Oracle客户端时,就会显示数据库了,只需 ...

  8. css伪类的组合用法

    利用伪类组合,可以用css代替js以达到目的,少些一下js .textarea:empty:before { display: block; content: '请输入'; color: #ababa ...

  9. File Transfer

    本博客的代码的思想和图片参考:好大学慕课浙江大学陈越老师.何钦铭老师的<数据结构> 代码的测试工具PTA File Transfer 1 Question 2 Explain First, ...

  10. html字体问题

    正如咱们在上一章中解说的那样,HTML元素使页面规划者能够对文档的构造进行符号.HTML标准列出了浏览器应该怎么显现这些元素的攻略.例如,您能够合理地保证强元素的内容将显现粗体.此外,您能够非常信赖大 ...