写一个session属性监听器:定义两个map,一个存session,以用户编号为key;一个存用户信息,也以用户编号为key.map的个数就是在线用户数.每个用户登录时,先检查map中是否存在,如果不存在,就新增到map里面去,如果存在,就通过用户编号找对应session使其失效.再将当前登录用户信息写入到map里面.
package com.sunshine.monitor.comm.filter;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import com.sunshine.monitor.system.manager.bean.SysUser;
/**
* session属性监听,用于统计在线用户数,同一账户登录踢出在线用户
* 对于直接关闭浏览器的操作等待session失效之后,才能做到清除.
* @date 2016-6-1
* @author licheng
*
*/
public class SessionListener implements HttpSessionAttributeListener{
/**
* 定义监听的session属性名
*/
public final static String LISTENER_NAME = "_login";
public final static String LISTENER_COUNT = "_count";
/**
* 定义存储客户登录用户的集合
*/
private static Map<String, SysUser> users = new HashMap<String, SysUser>();
/**
* 定义存储客户登录session的集合
*/
private static Map<String, HttpSession> sessions = new HashMap<String, HttpSession>();
/**
* 定义存储在线用户数的集合
*/
private static Map<String, Integer> counts = new HashMap<String, Integer>();
/**
* 加入session时的监听方法
*
* @param HttpSessionBindingEvent
* session事件
*/
public void attributeAdded(HttpSessionBindingEvent sbe) {
if(LISTENER_NAME.equals(sbe.getName())){
SysUser s = (SysUser) sbe.getValue();
if(users.containsKey(s.getYhdh())) {
HttpSession session = sessions.get(s.getYhdh());
session.removeAttribute(LISTENER_NAME);
session.invalidate();
}
sessions.put(s.getYhdh(), sbe.getSession());
users.put(s.getYhdh(), s);
}
Integer count = users.size();
counts.put(LISTENER_COUNT, count);
}
/**
* session失效时的监听方法
*
* @param HttpSessionBindingEvent
* session事件
*/
public void attributeRemoved(HttpSessionBindingEvent sbe) {
if(LISTENER_NAME.equals(sbe.getName())){
// 从session集合中减去一个
SysUser s = (SysUser) sbe.getValue();
sessions.remove(s.getYhdh());
users.remove(s.getYhdh());
counts.put(LISTENER_COUNT, users.size());
}
}
/**
* session覆盖时的监听方法
*
* @param HttpSessionBindingEvent
* session事件
*/
public void attributeReplaced(HttpSessionBindingEvent sbe) {
}
public static Map<String, SysUser> getUsers() {
return users;
}
public static Map<String, HttpSession> getSessions() {
return sessions;
}
public static Map<String, Integer> getCounts() {
return counts;
}
}
监听器写好之后要在web.xml里面配置一下.
<listener>
<listener-class>com.sunshine.monitor.comm.filter.SessionListener</listener-class>
</listener>
如何使用呢,用户登录时给session设置一个数据,获取在线用户数
request.getSession().setAttribute(SessionListener.LISTENER_NAME, s);
application.setAttribute("online", SessionListener.getCounts().get(SessionListener.LISTENER_COUNT));
页面上的在线人数这样获取:
<c:out value="${online}"></c:out>
注销时,这样写:
/**
* 注销移除sesson,从设置application的onlines属性
* @param request
* @param response
* @return
*/
@RequestMapping
public ModelAndView logout(HttpServletRequest request,
HttpServletResponse response){
ModelAndView mv = new ModelAndView(forwardLoginPath);
HttpSession session = request.getSession();
session.removeAttribute(SessionListener.LISTENER_NAME);
session.invalidate();
session.getServletContext().setAttribute("online", SessionListener.getCounts().get(SessionListener.LISTENER_COUNT));
return mv;
}
如果用户非法退出,如直接关闭浏览器,关闭窗口等.这时session并不会立即失效.我尝试过使用js监听窗口关闭操作,然后移除session.可是这段js只适用于ie8及以下.最终放弃,只能等待session失效.session的失效时常是在web.xml里面设置的.
session失效时,也是会触发属性移除时间的.