单人登录-踢下线功能实现
用户在不同会话层登录账号会将之前的账户状态注销,同一时间只有一个用户在线。
1.由于session的存储形式类似于key-value形式,则将其存储在redis中的hashmap较为合适。
2.redis中的hashmap只能存储string类型的键值对,因此将<username,sessionid>进行存储标识。
3.利用监听器进行每次session属性为user的监听动作
- .1判断当前session请求为user的属性名后,获得sessionId
- .2判断map集合中是否存在此user,
若不存在-则将其直接加入到redis中的hashmap中,若存在-则将通过sessionId获取session对象将其属性移出
此刻由于servlet版本问题,不支持通过sessionId获取session对象。因此我们要自己新建一个工具类SessionUtil来通过sessionId操作session,并建立一个监听器监听每个session的创建与销毁操作,使工具类同步 代码如下: - .3将最新登录的sessionId加入到redis中的hashmap中
3.2-监听器
package com.blog.listener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import com.blog.util.SessionUtil;
/**
*当创建 user的session时将其加入到sessionutil工具类中的map集合中进行同步
*/
@WebListener
public class SessionListener implements HttpSessionListener {
//创建session时将其加入
public void sessionCreated(HttpSessionEvent se) {
SessionUtil.addSession(se.getSession());
}
/**
* @see HttpSessionListener#sessionDestroyed(HttpSessionEvent)
*/
//销毁session时将其从map中删除
public void sessionDestroyed(HttpSessionEvent se) {
SessionUtil.deleteSession(se.getSession());
}
}
3.2-SessionUtil工具类
package com.blog.util;
//工具类SessionUtil 通过sessionId操作session
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpSession;
public class SessionUtil {
//创建map存放sessionid、session
private static Map<String,HttpSession> map = new HashMap<>();
//添加session
public static void addSession(HttpSession session) {
if(session!=null) {
map.put(session.getId(), session);
}
}
//移除session
public static void deleteSession(HttpSession session) {
if(session!=null) {
map.remove(session.getId());
}
}
//通过sessionid获得session
public static HttpSession getSession(String id) {
HttpSession session = null;
if(id!=null) {
session = map.get(id);
}
return session;
}
}
3-监听session属性:
package com.blog.listener;
import java.util.Map;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import com.blog.entity.User;
import com.blog.util.RedisUtil;
import com.blog.util.SessionUtil;
import com.google.gson.Gson;
import redis.clients.jedis.Jedis;
/**
* 通过监听sessionattribute实现单点登录
* 将sessionid存储到redis数据库中
*/
@WebListener
public class Loginlistener implements HttpSessionAttributeListener {
public Loginlistener() {
// TODO Auto-generated constructor stub
}
/**
* @see HttpSessionAttributeListener#attributeAdded(HttpSessionBindingEvent)
*/
public void attributeAdded(HttpSessionBindingEvent arg0) {
if(arg0.getName().equals("user")) {
//通过工具类获得jedis对象
Jedis jedis = RedisUtil.getredis();
//获得当前session中user对象
User u = (User)arg0.getValue();
//获得redis数据库中的map对象
Map<String,String> map = jedis.hgetAll("session");
String name_key = u.getUsername(); //获得map中的key值
//将sessionid 存入redis 数据库
String sessionid = arg0.getSession().getId(); //获取当前登录的sessionid
//判断用户是否已经登录
if(map.containsKey(name_key)) {
//获得之前客户端sessionid
String pre_sessionid = map.get(name_key);
//移出之前登录的 销毁session
HttpSession pre_session = SessionUtil.getSession(map.get(name_key));
pre_session.removeAttribute("user");
map.remove(name_key);
}
//用户未登录,将当前用户放进session 及 map中
jedis.hset("session", u.getUsername(), sessionid);
}
}
/**
* @see HttpSessionAttributeListener#attributeRemoved(HttpSessionBindingEvent)
*/
public void attributeRemoved(HttpSessionBindingEvent arg0) {
// TODO Auto-generated method stub
System.out.println("attributeRemoved");
}
/**
* @see HttpSessionAttributeListener#attributeReplaced(HttpSessionBindingEvent)
*/
public void attributeReplaced(HttpSessionBindingEvent arg0) {
// TODO Auto-generated method stub
System.out.println("attributeReplaced");
}
}