微信小程序 websocket 获取不到 session ?
@RequestMapping("login") public ReturnValue login(HttpServletRequest request, HttpServletResponse response) throws Exception { String userId = request.getParameter("userId"); String proxyId=request.getParameter("proxyId"); String workOrderId=request.getParameter("workOrderId"); String clientType=request.getParameter("clientType"); if(Strings.isBlank(userId)||Strings.isBlank(proxyId)||Strings.isBlank(workOrderId)||Strings.isBlank(clientType)) { return new ReturnValue(false,"参数异常"); } HttpSession session = request.getSession(); if(null!=session) { System.out.println("登陆WebSocket成功:"+("1".equals(clientType)?"P"+proxyId+workOrderId:"U"+userId+workOrderId)); session.setAttribute("WEBSOCKET_SESSSION_ID", "1".equals(clientType)?"P"+proxyId+workOrderId:"U"+userId+workOrderId); //一般直接保存user实体 }else { System.out.println("登陆WebSocket失败,session==null:"+("1".equals(clientType)?"P"+proxyId+workOrderId:"U"+userId+workOrderId)); logger.error("登录websocket+login时,获取session失败"); } return new ReturnValue(true); } |
这是小程序登录websocket 时的代码,当在session 中设置好键值后,在spring tcp握手连接时得不到这个session 和其中的值。
下面是tcp 握手连接时的代码 ,就是得不到session ,但是浏览器端是可以的,因为他加了xhrFields 带了凭证可以保证得到的session是一致的,
var url="<%=afterSaleServer%>/ptt/controller/websocket/websocketcontroller/login"; $.ajax({ url: url, type: 'post', async:false, data: messageJsonLogin, xhrFields: { withCredentials: true//允许带上凭据 }, crossDomain: true, success:function(res){ if(res.code=="200"){ if ('WebSocket' in window) { ws = new WebSocket(""+socketUrl+"/ptt/websocket/socketServer"); console.log("连接成功"); } else if ('MozWebSocket' in window) { ws = new MozWebSocket(""+socketUrl+"/ptt/websocket/socketServer"); } else {// 这个是应对浏览器不支持websocket协议的时候降级为轮询的处理。 ws = new SockJS("https://"+socketUrl+"/ptt/sockjs/socketServer"); } } }, error:function(){ } }); |
@Override public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception { System.out.println("Before Handshake"); if (request instanceof ServletServerHttpRequest) { ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request; HttpSession session = servletRequest.getServletRequest().getSession(); System.out.println("握手时,获取到的session:"+session); if (session != null) { //使用拼接ID区分WebSocketHandler,以便定向发送消息 String sessionId = (String) session.getAttribute("WEBSOCKET_SESSSION_ID"); //一般直接保存user实体 if (sessionId!=null) { attributes.put("WEBSOCKET_SESSSION_ID",sessionId); } //使用拼接ID区分WebSocketHandler,以便定向发送消息 出来处理工单也,在主页面的socket String sessionNo_workOrderId = (String) session.getAttribute("WEBSOCKET_NO_WORKORDER_WAIT_MESSAGE_SESSSION_ID"); //一般直接保存user实体 if (sessionNo_workOrderId!=null) { attributes.put("WEBSOCKET_NO_WORKORDER_WAIT_MESSAGE_SESSSION_ID",sessionNo_workOrderId); } } } return super.beforeHandshake(request, response, wsHandler, attributes); } |
下面是小程序端的代码,虽然我每次请求都发送了sessionId, 但是都是没有用,就是获取不到session,为什么要获取这个session呢?
loginWebSocket({ workOrderId: workOrderId, userId: userId, proxyId: proxyId, clientType: clientType}).then( console.log("登陆成功"), wx.connectSocket({ url: "" + socketUrl + "/ptt/websocket/socketServer", success() { console.log('连接成功') that.initEventHandle() } }) ); |
initEventHandle() { let that = this wx.onSocketMessage((res) => { console.log("收到消息",res); //收到消息 if (res.data == "pong") { heartCheck.reset().start() } else { //处理数据 console.log(res.data); var nowDate2 = util.formatDate(new Date());//发送日期 var nowTime2 = util.formatNowTime(new Date());//发送时间 var messageJson2 = {}; messageJson2.content = res.data; messageJson2.makeDate = nowDate2; messageJson2.makeTime = nowTime2; messageJson2.proxyId = proxyId; messageJson2.userId = null; var array2 = that.data.leaveMsgList; array2.push(messageJson2); that.setData({ leaveMsgList: array2 }); that.toButtom(); } }) wx.onSocketOpen(() => { console.log('WebSocket连接打开') heartCheck.reset().start() }) wx.onSocketError((res) => { console.log('WebSocket连接打开失败') this.reconnect() }) wx.onSocketClose((res) => { console.log('WebSocket 已关闭!') this.reconnect() }) }, reconnect:function() { console.log(this.lockReconnect); if (this.lockReconnect) return; this.lockReconnect = true; console.log("...."); clearTimeout(this.timer) if (this.data.limit < 12) { this.timer = setTimeout(() => { this.linkWebSocket(); this.lockReconnect = false; }, 5000); this.setData({ limit: this.data.limit + 1 }) } }, |
因为要通过在session 中设置的值来往 集合中放入session,方便对这个session 发送消息
/** * 连接成功时候,会触发页面上onopen方法 */ @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { System.out.println("成功建立websocket连接!"); String userId = (String) session.getAttributes().get(USER_ID); String no_workOrderId_userId = (String) session.getAttributes().get(No_WORKORDER_USERID); System.out.println("成功建立websocket连接 userId=!"+userId); System.out.println("成功建立websocket连接no_workOrderId_userId=!"+no_workOrderId_userId); if(Strings.isNotBlank(userId)) { if(users.containsKey(userId)) {//如果已包含将关闭之前的session,发送消息到新的session WebSocketSession wss=users.get(userId); wss.close(); } users.put(userId,session); } if(Strings.isNotBlank(no_workOrderId_userId)) { if(users.containsKey(no_workOrderId_userId)) {//如果已包含将关闭之前的session,发送消息到新的session WebSocketSession wss=users.get(no_workOrderId_userId); wss.close(); } users.put(no_workOrderId_userId,session); } System.out.println("当前线上用户数量:"+users.size()); users.entrySet().forEach(System.out::println); System.out.println(".......以上为用户session数量"); //这块会实现自己业务,比如,当用户登录后,会把离线消息推送给用户 //TextMessage returnMessage = new TextMessage("成功建立socket连接,你将收到的离线"); //session.sendMessage(returnMessage); } |
/** * 给某个用户发送消息 * * [@param](/user/param) userId * [@param](/user/param) message */ public void sendMessageToUser(String userId, TextMessage message) { logger.error("开始发送消息!给->"+userId +" 信息"+message); for (String id : users.keySet()) { logger.error("目前有:键值"+id+" 会话"+users.get(id)); if (id.equals(userId)) { try { if (users.get(id).isOpen()) { users.get(id).sendMessage(message); logger.error("成功发送消息给:"+userId); } } catch (IOException e) { e.printStackTrace(); } break; } } } |
跪求大佬们,耽误好几天了,在开发工具当中没有问题,但是小程序到了真机和体验版时,一致有这个问题
