符合中小企业对网站设计、功能常规化式的企业展示型网站建设
本套餐主要针对企业品牌型网站、中高端设计、前端互动体验...
商城网站建设因基本功能的需求不同费用上面也有很大的差别...
手机微信网站开发、微信官网、微信商城网站...
这篇文章将为大家详细讲解有关WebSocket中怎么区分不同客户端,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。
成都创新互联公司专注于江海企业网站建设,自适应网站建设,电子商务商城网站建设。江海网站建设公司,为江海等地区提供建站服务。全流程按需定制,专业设计,全程项目跟踪,成都创新互联公司专业和态度为您提供的服务
当我们在完成用户登录的功能时,用户登录成功,则将当前用户放入HttpSession中,这是一种很常见的做法,这一部分代码如下(框架是SpringMVC,不详细介绍,具体代码请以自己所用框架为准):
if(Objects.equals(userDetail.getUserDetailPassword(), userPassword)){ //如果当前用户登录成功,则将user对象放入httpSession的currentUser httpSession.setAttribute("currentUser",user);resoult = "success";}
那么接下来问题的关键就来了,我们怎么在Server中获取在这里放入HttpSession中的User对象呢,直接获取肯定是不行的,不卖关子,直接放代码。
注意,结构如图:
新建一个GetHttpSessionConfigurator类,内容如下:
import javax.servlet.http.HttpSession;import javax.websocket.HandshakeResponse;import javax.websocket.server.HandshakeRequest;import javax.websocket.server.ServerEndpointConfig;import javax.websocket.server.ServerEndpointConfig.Configurator;public class GetHttpSessionConfigurator extends Configurator{@Overridepublic void modifyHandshake(ServerEndpointConfig sec,HandshakeRequest request, HandshakeResponse response) { HttpSession httpSession=(HttpSession) request.getHttpSession(); sec.getUserProperties().put(HttpSession.class.getName(),httpSession); } }
然后在Server里面注解的地方加上一句:
@ServerEndpoint(value="/server/",configurator=GetHttpSessionConfigurator.class)
此时,我们就已经可以用
@OnOpenpublic void onOpen(Session session, EndpointConfig config){ HttpSession httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName()); }
来获取httpSession对象了,然后直接取出currentUser存储的用户对象就可以了。
但是,在这里我产生了一个问题:原则上来讲我在server获取的httpsession中取出来的用户对象就是现在正和服务端建立连接的对象,因为这种情况的操作肯定是先登录,然后直接建立连接,可是在实际中多用户同时登录时就不一定是这样子了。因为登录是客户端发起的操作,建立连接也是客户端发起的操作,且不说在客户端这两个操作是否是紧密相连,就算是紧密相连,从服务器验证成功(此时已经放入currentUser对象)返回登录结果给客户端到客户端向服务端发起连接这中间因为网络原因也是会消耗一定时间的。那么这时候一件尴尬的事情就发生了:此时,另一个用户也在登录,并且在之前用户两个操作期间完成了登录验证操作,那么第一个用户连接建立之后取出的use对象就不是这个用户的而是第二个用户的,这就乱套了。这种方法相当于是 ,用户A先对服务器说,记住了,我叫A,然后过了一会儿来说,我要建立连接,我是刚刚告诉你名字那个人。那如果B在A离开那会儿也告诉了服务器我叫B,那么服务器就会把A当成B了。
当前,上面我所说的我没办法去验证,如果我对HttpSession理解错误那就另当别论了。(应该没理解错吧)如果理解有误还请大神指正。
所以,感觉上来讲还是第二种方法靠谱一点。
这种方法是在建立连接时把userId放在建立连接的申请之中,这样的话就不会乱掉了:因为用户A登录成功之后我就把用户A的user对象传回去了,然后用户A拿着自己的userId来对客户端说我要建立连接我是A,服务端自然不会搞错。实现方法如下:
服务端注解地方如下:
@ServerEndpoint(value="/server/{userId}")
方法参数如下:
@OnOpenpublic void onOpen(@PathParam("userId")String userId,Session session)
服务端在建立连接请求时路径如下(cp是jsp中的:)
currentUser就是我们之前登录成功时放入httpSession的值,这个值即便别的用户登录也不会被刷新因为它是被保存在自己的浏览器之中的。
ws = "ws://localhost:8080" + "${cp}" + "/server"+"/${currentUser.userId}";
这样的话,服务端就获取到了当前建立连接的用户了。
能够获取不同用户userId之后,我们就可以在服务端进行如下操作来区分用户了,具体见注释。(为了突出要点,代码做了精简,仅仅用于示范区分不同的用户)
public class Server { //存放每个客户端对应的Server对象,可以考虑使用Map来代替,key作为用户标识 private static CopyOnWriteArraySetserver = new CopyOnWriteArraySet (); //表示与某个用户的连接会话,通过它给客户端发送数据 @SuppressWarnings("unused") private Session session; //用户id private String userId; //用户id和websocket的session绑定的路由表 @SuppressWarnings("rawtypes") private static Map routeTable = new HashMap<>(); /** * 连接建立成功调用的方法 * @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据 */@SuppressWarnings("unchecked")@OnOpenpublic void onOpen(@PathParam("userId")String userIds,Session session){this.session = session;//获取当前登录用户的idthis.userId=userIds;//将用户id和session绑定到路由表//绑定之后就可以在其它地方根据id来获取session,这时两个用户私聊就可以实现了routeTable.put(userId, session); }//其它部分代码就不放了
关于WebSocket中怎么区分不同客户端就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。