Listener概述

Listener的使用

使用Listener需要实现相应的Listener接口。

public class SessionListenerTest implements HttpSessionListener {

public void sessionCreated(HttpSessionEvent se) {

HttpSession session = se.getSession();

System.out.println("新创建了一个session: " + session);

}

public void sessionDestroyed(HttpSessionEvent se) {

HttpSession session = se.getSession();

System.out.println("销毁了一个session: " + session);

}

}

以上代码实现了HttpSessionListener接口。创建Session时会是服务器调用SessionCreated()方法,销毁Session时服务器调用sessionDestroyed()方法。他们都以HttpSessionEvent对象为参数,可以从该参数中获取session。Listener需要在web.xml中配置才能生效。

配置如下:

<listener>

<listener-class>

com.helloweenvsfei.listener.SessionListenerTest

</listener-class>

</listener>

Listener的分类

1.监听对象的创建与销毁

HttpSessionListener,HttpContextListener,HttpRequestListener分别用于Session,context,request的创建与销毁。

可以一个类实现多个Listener接口,如下代码:

2.监听对象的属性变化

代码如下:

3.监听Session内的对象

HttpSessionBindingListener和HttpSessionActivationListener

HttpSessionBindingListener:当对象被放到Session时执行valueBound(HttpSessionBinding event)方法,对象被移除时执行valueUnbound(HttpSessionBinding event)方法。对象必须实现该Listener接口。

HttpSessionActivationListener:服务器关闭时,会将Session内的内容保存到硬盘上,这个过程叫钝化。服务器启动时会将硬盘内容加载进来。当Session里的对象被钝化时会执行sessionWillPassivate(HttpSessionEvent event),当对象被加载时执行sessionDidActivate(HttpSessionEvent event)。对象必须实现该listener接口。

Listener使用案例(单态登陆)

public class LoginSessionListener implements HttpSessionAttributeListener {

Log log = LogFactory.getLog(this.getClass());

Map<String, HttpSession> map = new HashMap<String, HttpSession>();

public void attributeAdded(HttpSessionBindingEvent event) {

String name = event.getName();

// 登录

if (name.equals("personInfo")) {

PersonInfo personInfo = (PersonInfo) event.getValue();

if (map.get(personInfo.getAccount()) != null) {

// map 中有记录,表明该帐号在其他机器上登录过,将以前的登录失效

HttpSession session = map.get(personInfo.getAccount());

PersonInfo oldPersonInfo = (PersonInfo) session

.getAttribute("personInfo");

log.info("帐号" + oldPersonInfo.getAccount() + "在"

+ oldPersonInfo.getIp() + "已经登录,该登录将被迫下线。");

session.removeAttribute("personInfo");

session.setAttribute("msg", "您的帐号已经在其他机器上登录,您被迫下线。");

}

// 将session以用户名为索引,放入map中

map.put(personInfo.getAccount(), event.getSession());

log.info("帐号" + personInfo.getAccount() + "在" + personInfo.getIp()

+ "登录。");

}

}

public void attributeRemoved(HttpSessionBindingEvent event) {

String name = event.getName();

// 注销

if (name.equals("personInfo")) {

// 将该session从map中移除

PersonInfo personInfo = (PersonInfo) event.getValue();

map.remove(personInfo.getAccount());

log.info("帐号" + personInfo.getAccount() + "注销。");

}

}

public void attributeReplaced(HttpSessionBindingEvent event) {

String name = event.getName();

// 没有注销的情况下,用另一个帐号登录

if (name.equals("personInfo")) {

// 移除旧的的登录信息

PersonInfo oldPersonInfo = (PersonInfo) event.getValue();

map.remove(oldPersonInfo.getAccount());

// 新的登录信息

PersonInfo personInfo = (PersonInfo) event.getSession()

.getAttribute("personInfo");

// 也要检查新登录的帐号是否在别的机器上登录过

if (map.get(personInfo.getAccount()) != null) {

// map 中有记录,表明该帐号在其他机器上登录过,将以前的登录失效

HttpSession session = map.get(personInfo.getAccount());

session.removeAttribute("personInfo");

session.setAttribute("msg", "您的帐号已经在其他机器上登录,您被迫下线。");

}

map.put("personInfo", event.getSession());

}

}

}

代码详解:

每次用户登录时都会将JavaBean personinfo对象放入到session中,此时会触发监听器LoginSessionListener中的attributeAdded方法,该方法获取personinfo的账号并与已有的map集合中信息比对,看是否有重复的,如果有重复的,则获取重复的session,并去除该session的personinfo信息。

HttpSession session = map.get(personInfo.getAccount());

session.removeAttribute("personInfo");

session.setAttribute("msg", "您的帐号已经在其他机器上登录,您被迫下线。");

以上代码之所以可以去除原有登陆信息的原因如下:

在Java中参数传递都是传的引用,因此Map集合中的session都是原始session的引用。

代码HttpSession session = map.get(personInfo.getAccount());获得的便是原始的session。因此删除该session的personInfo便是删除原始session的personInfo。

最新文章

  1. Huffman树进行编码和译码
  2. 1Z0-053 争议题目解析510
  3. 云计算的三种服务模式:SaaS/PaaS/IaaS
  4. php 上传大文件配置upload_max_filesize和post_max_size选项
  5. JDK环境变量详细讲解
  6. mysql 查表失败
  7. quay.io/coreos/etcd 基于Docker镜像的集群搭建
  8. bitmap格式分析
  9. 剑指offer系列49--求1+2+...+N的和
  10. 【老鸟学算法】包含 min函数的栈设计——java实现
  11. Ueditor文件上传问题
  12. STAThread 和 MTAThread
  13. iOS开发之GCD同步主线程、异步主线程
  14. delphi java 日期 转换 获取Unix时间戳
  15. 多项式&amp;生成函数(~~乱讲~~)
  16. Hadoop不适合处理实时数据的原因剖析
  17. Python 函数参数引用(传值/传址)/copy/deepcopy
  18. POJ 2296 Map Labeler (2-Sat)
  19. 学会阅读Java字节码
  20. 网络中,FIFO、LRU、OPT这三种置换算法的缺页次数

热门文章

  1. Mysql only_full_group_by 引起的错误
  2. (补题 杭电 1008)Elevator
  3. OAuth(开放授权)
  4. PL/SQL轻量版(一)——入门介绍
  5. 20155202 20155222 信息安全技术概论实验一 PGP的使用
  6. 20155310 2016-2017-2 《Java程序设计》第三周学习总结
  7. 20155333 2016-2017-2 《Java程序设计》第十周学习总结
  8. 【LG4587】[FJOI2016]神秘数
  9. 洛谷 P1941 飞扬的小鸟
  10. flask ssti python2和python3 注入总结和区别