Websocket如何获取httpSession,区分不同客户端

  1. 我们知道websocket协议与http协议有些不同,websocket有自带的Session,但是跟http的Session是不一样的,而我们做有些web项目的时候,又需要知道当前是哪个用户,用以处理该用户的业务逻辑,或者是对该用户进行授权之类的,所以必须需要获取并知道http的Session,具体方法如下:

  2. 我们先附上代码,根据代码来讲解(具体解释在第三点):
    2.1. 我们需要先创建一个新类GetHttpSessionConfig并继承Configurator类。

    import javax.websocket.HandshakeResponse;
    import javax.websocket.server.HandshakeRequest;
    import javax.websocket.server.ServerEndpointConfig;
    import javax.websocket.server.ServerEndpointConfig.Configurator;
    
    public class GetHttpSessionConfig extends Configurator{
    	@Override
     	public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) { 
     		HttpSession httpSession = (HttpSession) request.getHttpSession();
      		sec.getUserProperties().put(HttpSession.class.getName(),httpSession);
     	}
    }
    

    2.2 之后我们需要在socket类中,填加如下代码,便可以取得到http的Session信息。

    1. 我们需要在@ServerEndpoint注解多里面添加configurator属性。
    2. 我们还需要在open函数中多加个形式参数EndpointConfig config.
    import javax.servlet.http.HttpSession;
    import javax.websocket.EndpointConfig;
    import javax.websocket.OnOpen;
    import javax.websocket.Session;
    import javax.websocket.server.ServerEndpoint;
    
    import com.config.GetHttpSessionConfig;
    //1.我们需要在@ServerEndpoint注解多里面添加configurator属性
    @ServerEndpoint(value = "/CharSocket", configurator= GetHttpSessionConfig.class)
    public class chatSocket {
    	//2.我们还需要在open函数中多加个形式参数EndpointConfig config
    	@OnOpen
     	public void open(Session session, EndpointConfig config) {
     	
      		HttpSession httpsession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
     	}
    }
  3. 具体解释上面的代码含义(查看源代码)
    在这里插入图片描述

    3.1 首先我们是创建一个新类GetHttpSessionConfig并继承Configurator类,而我们又看见import javax.websocket.server.ServerEndpointConfig.Configurator;,因此我们进入ServerEndpointConfig类中查看源码,我们发现在里面的Configurator类中的有部分代码如下:

    public void modifyHandshake(ServerEndpointConfig sec,
                    HandshakeRequest request, HandshakeResponse response) {
                fetchContainerDefaultConfigurator().modifyHandshake(sec, request, response);
            }

    而且我们重写了这段代码,这又是为什么呢,Configurator类里面这么多函数,为什么就要选择这个呢?我们发现在HandshakeRequest request中request有点熟悉呀,那么我们点入HandshakeRequest中看看是什么东西?当我们点进去发现了这段代码:

    Object getHttpSession();

    哦,到这里才恍然大悟,用来是可以getHttpSession的,因此我们才用这个函数进行重构。

    ServerEndpointConfig sec
    sec.getUserProperties().put(HttpSession.class.getName(),httpSession);

    这段代码又是什么意思?老样子,我们点进去查看源码,发现了下面:
    在这里插入图片描述
    原来ServerEndpointConfig还继承了EndpointConfig,那我们继续深入其中,发现EndpointConfig是个接口。
    在这里插入图片描述
    原来getUserProperties是Map,那么就可以拿来存储数据了,既然都有Map了,肯定要用了啊,不用白不用,难道还自己在创建吗。

    3.2 在2.2 中

    //1.我们需要在@ServerEndpoint注解多里面添加configurator属性
     @ServerEndpoint(value = "/CharSocket", configurator= GetHttpSessionConfig.class)
     public class chatSocket {
      //2.我们还需要在open函数中多加个形式参数EndpointConfig config
      	@OnOpen
       	public void open(Session session, EndpointConfig config) {
       
         		HttpSession httpsession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
       	}
     }

    在open函数中,多加EndpointConfig config,是因为我们需要重新可以调用getUserProperties()得到Map,从而获得Session。

  4. 额外思考。
    我们从上面的代码知道,websocket是怎么获取http的Session的,具体是用Map<key,Object>,但是我们仔细看一下,key值是HttpSession.class.getName()函数,那么这个函数是返回什么呢?我们让代码告诉,如下:
    在这里插入图片描述
    运行两个网页,运行结果如下:
    在这里插入图片描述
    我们发现 HttpSession.class.getName()函数返回都是 javax.servlet.http.HttpSession,那么就有个问题了,我们先看下面的例子,再说上面的问题。

    public class Maptest {
    
     	private static Map<String,String> map = new HashMap<String,String>();
     	
     	public static void main(String[] args) {
      		map.put("abc","111");
      		map.put("abc", "222");
      		System.out.println("map.size........" +  map.size());
      		System.out.println("map.get(\"abc\") ........"+ map.get("abc"));
     	}
    }

    如果我在同一个map中存储两个数据,且key都是一样为”abc",那么map.get("abc“)结果为啥呢,我们让程序运行一下,查看结果如下:
    在这里插入图片描述
    我们可以看出,在Map中只有一个值了,且为后面添加的值,这就说明个问题,若此时我们有两个客户端准备申请连接websocket服务器,设为A,B,若A先连接时,存储在Map的键对是<“javax.servlet.http.HttpSession”,“A”>,但是服务器还没有取A值的时候,那此时B恰好也连接,存储在Map的键对又是<“javax.servlet.http.HttpSession”,“B”>,那么A的Session就不见了,若此时服务器取A的Session的时候,只能取到B的Session了。我个人理解是这样子。

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值