微信小程序 websocket 获取不到 session ?
发布于 6 年前 作者 jfan 12489 次浏览 来自 官方Issues
[@RequestMapping](/user/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](/user/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](/user/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;
            }
        }
    }

跪求大佬们,耽误好几天了,在开发工具当中没有问题,但是小程序到了真机和体验版时,一致有这个问题

回到顶部