单人登录-踢下线功能实现

单人登录-踢下线功能实现

  • 功能描述:

用户在不同会话层登录账号会将之前的账户状态注销,同一时间只有一个用户在线。

  • 实现:servlet+redis,

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");
    }
	
}

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值