2019独角兽企业重金招聘Python工程师标准>>>

从第一篇已经讲解过了监听器的基本概念,以及Servlet各种的监听器。这篇博文主要讲解的是监听器的应用。

统计网站在线人数

分析

我们在网站中一般使用Session来标识某用户是否登陆了,如果登陆了,就在Session域中保存相对应的属性。如果没有登陆,那么Session的属性就应该为空。

现在,我们想要统计的是网站的在线人数。我们应该这样做:我们监听是否有新的Session创建了,如果新创建了Sesssion,那么在线人数就应该+1。这个在线人数是整个站点的,所以应该有Context对象保存。

大致思路:

  • 监听Session是否被创建了
  • 如果Session被创建了,那么在Context的域对象的值就应该+1
  • 如果Session从内存中移除了,那么在Context的域对象的值就应该-1.

代码

  • 监听器代码:
  public class CountOnline implements HttpSessionListener {public void sessionCreated(HttpSessionEvent se) {//获取得到Context对象,使用Context域对象保存用户在线的个数ServletContext context = se.getSession().getServletContext();//直接判断Context对象是否存在这个域,如果存在就人数+1,如果不存在,那么就将属性设置到Context域中Integer num = (Integer) context.getAttribute("num");if (num == null) {context.setAttribute("num", 1);} else {num++;context.setAttribute("num", num);}}public void sessionDestroyed(HttpSessionEvent se) {ServletContext context = se.getSession().getServletContext();Integer num = (Integer) se.getSession().getAttribute("num");if (num == null) {context.setAttribute("num", 1);} else {num--;context.setAttribute("num", num);}}}
  • 显示页面代码:

在线人数:${num}

测试

我们每使用一个浏览器访问服务器,都会新创建一个Session。那么网站的在线人数就会+1。

使用同一个页面刷新,还是使用的是那个Sesssion,所以网站的在线人数是不会变的。

自定义Session扫描器

我们都知道Session是保存在内存中的,如果Session过多,服务器的压力就会非常大。

但是呢,Session的默认失效时间是30分钟(30分钟没人用才会失效),这造成Seesion可能会过多(没人用也存在内存中,这不是明显浪费吗?)

当然啦,我们可以在web.xml文件中配置Session的生命周期。但是呢,这是由服务器来做的,我嫌它的时间不够准确。(有时候我配置了3分钟,它用4分钟才帮我移除掉Session)

所以,我决定自己用程序手工移除那些长时间没人用的Session。

分析

要想移除长时间没人用的Session,肯定要先拿到全部的Session啦。所以我们使用一个容器来装载站点所有的Session。。

只要Sesssion一创建了,就把Session添加到容器里边。毫无疑问的,我们需要监听Session了。

接着,我们要做的就是隔一段时间就去扫描一下全部Session,如果有Session长时间没使用了,我们就把它从内存中移除。隔一段时间去做某事,这肯定是定时器的任务呀。

定时器应该在服务器一启动的时候,就应该被创建了。因此还需要监听Context

最后,我们还要考虑到并发的问题,如果有人同时访问站点,那么监听Session创建的方法就会被并发访问了定时器扫描容器的时候,可能是获取不到所有的Session的

这需要我们做同步

于是乎,我们已经有大致的思路了

  • 监听Session和Context的创建
  • 使用一个容器来装载Session
  • 定时去扫描Session,如果它长时间没有使用到了,就把该Session从内存中移除。
  • 并发访问的问题

代码

  • 监听器代码:
public class Listener1 implements ServletContextListener,HttpSessionListener {//服务器一启动,就应该创建容器。我们使用的是LinkList(涉及到增删)。容器也应该是线程安全的。List<HttpSession> list = Collections.synchronizedList(new LinkedList<HttpSession>());//定义一把锁(Session添加到容器和扫描容器这两个操作应该同步起来)private Object lock = 1;public void contextInitialized(ServletContextEvent sce) {Timer timer = new Timer();//执行我想要的任务,0秒延时,每10秒执行一次timer.schedule(new MyTask(list, lock), 0, 10 * 1000);}public void sessionCreated(HttpSessionEvent se) {//只要Session一创建了,就应该添加到容器中synchronized (lock) {list.add(se.getSession());}System.out.println("Session被创建啦");}public void sessionDestroyed(HttpSessionEvent se) {System.out.println("Session被销毁啦。");}public void contextDestroyed(ServletContextEvent sce) {}}
  • 任务代码:
/** 在任务中应该扫描容器,容器在监听器上,只能传递进来了。** 要想得到在监听器上的锁,也只能是传递进来** */class MyTask extends TimerTask {private List<HttpSession> sessions;private Object lock;public MyTask(List<HttpSession> sessions, Object lock) {this.sessions = sessions;this.lock = lock;}@Overridepublic void run() {synchronized (lock) {//遍历容器for (HttpSession session : sessions) {//只要15秒没人使用,我就移除它啦if (System.currentTimeMillis() - session.getLastAccessedTime() > (1000 * 15)) {session.invalidate();sessions.remove(session);}}}}}
  • 测试:

15秒如果Session没有活跃,那么就被删除!

  • 使用集合来装载我们所有的Session
  • 使用定时器来扫描session的声明周期【由于定时器没有session,我们传进去就好了】
  • 关于并发访问的问题,我们在扫描和检测session添加的时候,同步起来就好了【当然,定时器的锁也是要外面传递进来的】

踢人小案列

列出所有的在线用户,后台管理者拥有踢人的权利,点击踢人的超链接,该用户就被注销了。

分析

首先,怎么能列出所有的在线用户呢??一般我们在线用户都是用Session来标记的**,所有的在线用户就应该用一个容器来装载所有的Session。。**

我们监听Session的是否有属性添加(监听Session的属性有添加、修改、删除三个方法。如果监听到Session添加了,那么这个肯定是个在线用户!)。

装载Session的容器应该是在Context里边的【属于全站点】,并且容器应该使用Map集合【待会还要通过用户的名字来把用户踢了】

思路:

  • 写监听器,监听是否有属性添加在Session里边了
  • 写简单的登陆页面。
  • 列出所有的在线用户
  • 实现踢人功能(也就是摧毁Session)

代码

  • 监听器
public class KickPerson implements HttpSessionAttributeListener {// Public constructor is required by servlet specpublic KickPerson() {}public void attributeAdded(HttpSessionBindingEvent sbe) {//得到context对象,看看context对象是否有容器装载SessionServletContext context = sbe.getSession().getServletContext();//如果没有,就创建一个呗Map map = (Map) context.getAttribute("map");if (map == null) {map = new HashMap();context.setAttribute("map", map);}//---------------------------------------------------------------------------------------//得到Session属性的值Object o = sbe.getValue();//判断属性的内容是否是User对象if (o instanceof User) {User user = (User) o;map.put(user.getUsername(), sbe.getSession());}}public void attributeRemoved(HttpSessionBindingEvent sbe) {/* This method is called when an attributeis removed from a session.*/}public void attributeReplaced(HttpSessionBindingEvent sbe) {/* This method is invoked when an attibuteis replaced in a session.*/}
}
  • 登陆页面

<form action="${pageContext.request.contextPath }/LoginServlet" method="post">用户名:<input type="text" name="username"><input type="submit" value="登陆">
</form>
  • 处理登陆Servlet
//得到传递过来的数据String username = request.getParameter("username");User user = new User();user.setUsername(username);//标记该用户登陆了!request.getSession().setAttribute("user", user);//提供界面,告诉用户登陆是否成功request.setAttribute("message", "恭喜你,登陆成功了!");request.getRequestDispatcher("/message.jsp").forward(request, response);
  • 列出在线用户
<c:forEach items="${map}" var="me">${me.key} <a href="${pageContext.request.contextPath}/KickPersonServlet?username=${me.key}">踢了他吧</a><br>
</c:forEach>
  • 处理踢人的Servlet
String username = request.getParameter("username");//得到装载所有的Session的容器Map map = (Map) this.getServletContext().getAttribute("map");//通过名字得到SessionHttpSession httpSession = (HttpSession) map.get(username);httpSession.invalidate();map.remove(username);//摧毁完Session后,返回列出在线用户页面request.getRequestDispatcher("/listUser.jsp").forward(request, response);

测试

使用多个浏览器登陆来模拟在线用户(同一个浏览器使用的都是同一个Session)

监听Seesion的创建和监听Session属性的变化有啥区别???

  • Session的创建只代表着浏览器给服务器发送了请求。会话建立
  • Session属性的变化就不一样了,登记的是具体用户是否做了某事(登陆、购买了某商品)

如果文章有错的地方欢迎指正,大家互相交流。习惯在微信看技术文章的同学,可以关注微信公众号:Java3y

转载于:https://my.oschina.net/u/3777556/blog/1621072

监听器应用【统计网站人数、自定义session扫描器、踢人小案例】相关推荐

  1. java扫描所有用户信息_监听器实现案例----自定义session扫描器和统计在线用户人数及用户信息...

    一.案例一:自定义Session扫描器 1.案例说明 当一个Web应用创建的Session很多时,为了避免Session占用太多的内存,我们可以选择手动将这些内存中的session销毁,那么此时也可以 ...

  2. Javaweb Listener监听器的简单应用:统计网站在线人数

    Listener监听器实现统计网站在线人数 开发环境: IntelliJ IDEA 一.什么是监听器 是指专门用于对其他对象身上发生的事件或状态改变进行监听和相应处理的对象,当被监视的对象发生变化时, ...

  3. 监听器(统计在线人数)

    监听器(统计在线人数) 监听器是GUI中常用的功能,Javaweb中使用场景不是很多,可以使用监听器实现统计网站访问人数: 实现原理: 服务器回味每个客户端创建一个session,通过监听服务器中se ...

  4. 12-监听器实现统计网站当前在线人数

    在 javaweb 项目中,利用监听器,实现统计网站当前在线人数 1.新建一个实现 HttpSessionListener 接口的实现类 OnlineCountListener.java packag ...

  5. html网站统计来访人数,实现网站访问人数统计

    首先我需要一个能访问网站人数的功能,那莫具体来讲就是需要一个能全局存储的,在 java web 中 为啥不用session 因为他代表的试一次会话是一种局部存储, 所以用 servletContext ...

  6. 利用Servlet监听器实现简单网站访问量和在线人数统计

    转自 http://blog.sina.com.cn/s/blog_621a42970100gblw.html Servlet监听器主要有三种,在ServletContext(上下文对象).Sessi ...

  7. day28:检测磁盘io|自定义时段查看tomcat 日记|打印城市名字|代码上线|统计网站并发量...

    2019独角兽企业重金招聘Python工程师标准>>> 1.有一台阿里云的机器,接到反映说服务器的磁盘 io 很高,登录服务器查看,并没有发现问题,怀疑是间歇性的,看到造成磁盘 io ...

  8. JSP 统计网站访问人数

    统计访问人数1 <%@ page language="java" import="java.util.*" pageEncoding="UTF- ...

  9. php实现服务器访问统计,服务器端统计网站总访问人数

    上篇日志是关于,如何在客户端实现用cookie保存个人用户访问网站的次数的.这篇日志是讲,在服务器端统计访问网站的总人数. 实现方法有两种:1.当用户访问网站时,记录用户的ip,存入到数据库中,然后用 ...

最新文章

  1. 推荐一些算法方面的好书
  2. 一份简单的在 Linux下编译及调试 C 代码的指南
  3. oracle job 时间间隔,关于job的时间间隔的一个问题
  4. ML之MIC:利用某数据集计算机最大信息系数MIC并可视化MIC矩阵热图及其代码实现
  5. 【干货】2014年值得仔细研究的十大神级文案
  6. c语言中的fock方法输出hello,涉及fork()的C程序输出的说明
  7. Windows——Windows恢复环境(Windows RE)
  8. git 入门教程之版本管理
  9. 2010年IT人士必去的10个网站
  10. 重塑自己的语音 笔记1
  11. 给一个aspx页面上所有的TextBox置值
  12. 孤岛惊魂4服务器稳定吗,《孤岛惊魂5》究竟好不好玩 让我来告诉你(缺点)
  13. 易语言5.9 免狗完美版下载+安装教程
  14. 无损音乐播放器,有软件与硬件之分
  15. 涉密专用计算机平台,涉密计算机及移动存储介质保密管理系统(三合一)
  16. FPGA:调试报错Error:add_1 must be in range [-1,DEPTH-1]解决办法和调试思路
  17. 基于SSM的网上书城系统设计与实现
  18. excel里面身份证号显示不全
  19. 了解什么是枚举(enumeration)
  20. 创建MySQL桌面快捷方式的方法

热门文章

  1. 2017-9-5-Java 泛型
  2. python学习笔记-Day5
  3. day③:函数式编程
  4. 代码复审1234跟我一起来
  5. nyist 2 括号配对问题
  6. AspxGridView 主子表设置
  7. 和菜鸟一起学android4.0.3源码之lcd屏幕背光调节
  8. Service Mesh简史
  9. TreeNode.trage的使用
  10. AngularJS入门(用ng-repeat指令实现循环输出)