@pastqing
2015-01-08T09:08:43.000000Z
字数 4360
阅读 3228
java
此文指针对小白, 加上日常记录之用。 小牛, 大牛勿进。
Listener是Servlet的一个高级特性, 它能监听java web程序中的事件, 例如创建、 修改、 删除Session, request, context等。

这里用到两种Listener,分别是HttpSessionBindingListener与HttpSessionActivationListener, 它们的触发时机分别为:
关于钝化:服务器关闭时, 会将Session里的内容保存到硬盘上(保存到哪?I don‘t know),这个就叫钝化。服务器重新启动时, 会将session内容从硬盘中重新加载。
public class PersonInfo implements HttpSessionBindingListener, HttpSessionActivationListener, Serializable {private String name;private Date dateCreated;/*** 该对象被存入session前调用* @see HttpSessionBindingListener#valueBound(HttpSessionBindingEvent)*/public void valueBound(HttpSessionBindingEvent arg0) {HttpSession session = arg0.getSession(); //记录它所在的sessionString name = arg0.getName(); //得到其在session中的属性名称System.out.println(this + "被绑定到session " + session.getId() + " name: " + name);this.setDateCreated(new Date());}/*** 从硬盘中读入session后调用* @see HttpSessionActivationListener#sessionDidActivate(HttpSessionEvent)*/public void sessionDidActivate(HttpSessionEvent arg0) {HttpSession session = arg0.getSession();System.out.println(this + "已经成功从硬盘中加载 sessionID:" + session.getId() );}/*** 即将被钝化到硬盘时调用(服务器关闭时, session信息会被保存到硬盘上)* @see HttpSessionActivationListener#sessionWillPassivate(HttpSessionEvent)*/public void sessionWillPassivate(HttpSessionEvent arg0) {HttpSession session = arg0.getSession();System.out.println(this + "已经成功钝化到硬盘 sessionID:" + session.getId() );}/*** 从session中移除对象时调用* @see HttpSessionBindingListener#valueUnbound(HttpSessionBindingEvent)*/public void valueUnbound(HttpSessionBindingEvent arg0) {HttpSession session = arg0.getSession();String name = arg0.getName();System.out.println(this + "从session中移除的session, sessionID: " + session.getId() + " name: " + name);}
这里提一下java序列化Serializable, 这里要用到序列化的原因大概是要往硬盘里写, 那么怎么把对象写进硬盘里呢, 就是将对象序列化后放入内存, 从内存中写到硬盘里。至于Serializable我也不是很懂, 有兴趣可以参考这个文章java序列化
public class LoginListener implements HttpSessionAttributeListener {//定义一个map用来存放session对象Map<String, HttpSession> map = new HashMap<String, HttpSession>();public void attributeAdded(HttpSessionBindingEvent arg0) {System.out.println("start add");String name = arg0.getName();if("personInfo".equals(name)) {LoginPerson loginPerson = (LoginPerson)arg0.getValue();if( map.get(loginPerson.getAccount()) != null ) { //若map中存在账号//账号在不同的会话中登陆, 注销一个, 实现单态登陆HttpSession session = map.get(loginPerson.getAccount());LoginPerson oldPerson = (LoginPerson)session.getAttribute("personInfo");System.out.println("账号 " + oldPerson.getAccount() + " 在 " + oldPerson.getIp() + " 已经登陆, 将被迫下线");session.removeAttribute("personInfo");session.setAttribute("msg", "您的账号已在其他机器上登陆");map.put(loginPerson.getAccount(), arg0.getSession());System.out.println("账号 " + loginPerson.getAccount() + " 在 " + loginPerson.getIp() + " 登陆");}}}public void attributeRemoved(HttpSessionBindingEvent arg0) {System.out.println("start remove");//注销时调用String name = arg0.getName();if( "personInfo".equals(name) ) {LoginPerson loginPerson = (LoginPerson)arg0.getValue();map.remove(loginPerson.getAccount());System.out.println("账号: " + loginPerson.getAccount() + "已注销");}}public void attributeReplaced(HttpSessionBindingEvent arg0) {System.out.println("start replace");String name = arg0.getName();if("personInfo".equals(name)) { //没有注销的情况下, 使用其他账号登陆LoginPerson oldPerson = (LoginPerson)arg0.getValue();map.remove(oldPerson); //移除旧的登陆信息LoginPerson loginPerson = (LoginPerson)arg0.getSession().getAttribute("personInfo"); //新的登陆信息//验证新的登陆是否在其他会话中登陆if(map.get(loginPerson.getAccount()) != null ) {HttpSession session = map.get(loginPerson.getAccount());session.removeAttribute("personInfo");session.setAttribute("msg", "您的账号已在其他机器上登陆");System.out.println("msg已经存入session");}map.put(loginPerson.getAccount(), arg0.getSession());}}}