看到许多博客里都是通过前端建立websocket请求时将用户信息传递给后端并绑定到websocket的实例中,这样也能满足需求,但是针对粒度要达到会话级别的时候,同时系统采用异步编程时,这个做法就无法满足业务场景了,同时这对前端还有侵入性。另大多数博客都没讲清原理,此处为加深自己记忆,整理一份文档,助和我曾经一样的小白们快速理解。
场景说明:
1、如果系统收到请求后将数据交给线程池异步执行,并且执行完成后需要通过websocket将执行结果推送给指定用户;
2、如果系统对用户不做登录限制,允许其在多个终端登录。那么此时一个用户可能存在多个会话,因此,推送用户时需要精确到会话级别;
针对上面的场景,springboot websocket有多种方式解决,下面为其中一种方式,也是用得比较多的一种
会话同步的解决方式:查看ServerEndpointConfig.Configurator源码,该内部类有一个modifyHandshake方法,源码如下:
public void modifyHandshake(ServerEndpointConfig sec,
HandshakeRequest request, HandshakeResponse response) {
fetchContainerDefaultConfigurator().modifyHandshake(sec, request, response);
}
意思很明确,就是修改握手,并且该方法会传入HandshakeRequest接口类该接口有一个方法,源码如下 :
/**
* Get the HTTP Session object associated with this request. Object is used
* to avoid a direct dependency on the Servlet API.
* @return The javax.servlet.http.HttpSession object associated with this
* request, if any.
*/
Object getHttpSession();
通过方法描述可以清楚知道该方法返回http会话实例。至此,应该不难理解了,当websocket连接握手时会执行该方法,则我们可以通过extends该类,重写该方法,从该方法HandshakeRequest形参中获取到http会话信息,并将之绑定到该方法另一形参ServerEndpointConfig的getUserProperties()用户属性中。则在完成websocket建立后,可以通过websocket的会话实例获取到该用户属性从而获取http会话。
异步执行时在线程里获取请求会话方式: