在开发中遇到一个问题,系统内,同一个账号可以在不同的地方多个人同时进行登陆,操作。
要求是同一账号在系统内必须保持唯一,即,若是有人用同一账号登陆了,已登录账号失效
解决方案有两种:
一种是在系统中设置状态位,登陆签到,退出签退...至于异常退出,在旧的session销毁之前是无法再次进行登陆的,配置session的监听,在session销毁时,进行数据库操作,更改库里对应用户的状态位
另一种思想:在服务器上维护一个map,以用户唯一标识为主键,值为session,登录时判断该用户是否已在,不在的话加入,已在的话将原session销毁,放入现有的session,这样的话前面登陆的人就不能再进行操作了。
下面实现后者,前者的话也是一样的
ConcurrentHashMap 是util.concurrent 包的一部分,它提供比Hashtable 或者 synchronizedMap 更高程度的并发性。而且,对于大多数成功的 get() 操作它会设法避免完全锁定,其结果就是使得并发应用程序有着非常好的吞吐量
public class SessionHandler {
private static final ConcurrentHashMap<String,HttpSession> sessionMap = new ConcurrentHashMap<String, HttpSession>();
/**
* 登录时调用
* @param userId 用户名
* @param session 会话
*/
public static synchronized void kickUser(String userId,HttpSession session)
{
HttpSession oldSession = sessionMap.get(userId);
if(oldSession != null)
{
if (!oldSession.getId().equals(session.getId()))
{
try{
oldSession.invalidate();
}catch (Exception e)
{}
sessionMap.put(userId,session);
return;
}
}
sessionMap.put(userId,session);
}
/**
* 正常退出时调用
* @param userId
*/
public static void removeUserFromSessionMap(String userId)
{
if (sessionMap.containsKey(userId))
sessionMap.remove(userId);
}
}
至于异常的退出,只能等到会话超时了
此时必须设置监听会话超时时session销毁时附带进行的操作
public class SessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
HttpSession session = httpSessionEvent.getSession();
SessionManager.removeUserFromSessionMap((String)session.getAttribute("userId"));
}
}
web.xml中配置
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.cyb.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>login</url-pattern>
</servlet-mapping>
<listener>
<listener-class>com.cyb.servlet.listener.SessionListener</listener-class>
</listener>
</web-app>
单用户会话管理

本文介绍了一种确保系统中单一用户账号唯一性的方法,通过使用ConcurrentHashMap来维护在线用户的会话信息,并在用户重复登录时自动注销原有会话。
1197

被折叠的 条评论
为什么被折叠?



