-
我们知道websocket协议与http协议有些不同,websocket有自带的Session,但是跟http的Session是不一样的,而我们做有些web项目的时候,又需要知道当前是哪个用户,用以处理该用户的业务逻辑,或者是对该用户进行授权之类的,所以必须需要获取并知道http的Session,具体方法如下:
-
我们先附上代码,根据代码来讲解(具体解释在第三点):
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信息。
- 我们需要在@ServerEndpoint注解多里面添加configurator属性。
- 我们还需要在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.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。
-
额外思考。
我们从上面的代码知道,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了。我个人理解是这样子。
Websocket如何获取httpSession,区分不同客户端
最新推荐文章于 2024-05-15 11:14:26 发布