前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >解决微信小程序无法建立持久化连接的两种方案

解决微信小程序无法建立持久化连接的两种方案

作者头像
roobtyan
发布2019-02-21 15:39:59
1.4K0
发布2019-02-21 15:39:59
举报

问题出现的场景

因为最近在做一个小程序的项目,在建立前后端连接的过程中,发现了一个非常让人奇怪的现象:本身小程序是通过调用wx.https()方法来发起http请求的,但是你会发现,如果你在后端将值保存到了request或者session中,这个值你再次调用的时候就不见了!取值的时候会出现NullPointerException,或者你在使用了Spring Security、Shiro这样的权限校验框架以后,会发现登录后出现了权限丢失的问题。 这到底是为什么呢?根据我的经验,我怀疑是session发生了变化,为了证明这一点,我通过观察两次请求的session是否为同一个得到了最终的结论。 小程序发起请求的代码是这样的:

代码语言:javascript
复制
wx.request({
    url: serverUrl + '/login',
    data: {
      username: username,
      password: password
    },
    header: {
      'content-type': 'application/json' // 默认值
    },
    success:function(){
        console.log("登录成功");
    }
  })

通过观察小程序的调试器的network,发现果然两次请求的session发生了变化。我猜想是因为小程序没有保存连接的Cookie,果然,通过查阅资料,发现小程序是无法建立持久化的连接的,所以就不会主动保存Cookie。其实这也在一定程度上体现了小程序用完即走的特性。

那么解决的办法也就很清楚了:将首次请求返回的response中的Cookie保存下来,然后下次发送请求时将此值放到请求头中。

解决问题的方案

实际上,我们在使用浏览器访问某个网站的时候,浏览器会主动的将Cookie中的JSESSIONID存入浏览器的Cookie缓存中,这样下次再请求的时候,就会自动将这个JESSIONID加到请求头中,这样对方的服务器就能够识别我们,从而达到建立一种“持久化”连接的状态。实际上我们知道,这种连接并不是真正持久的,都是需要数据的时候再次建立连接,然后断开。整个过程如图所示:

方案一:将JSESSIONID放入全局变量

其实最简单的办法就是,在第一次请求完成后,就将JSESSIONID放到全局的SESSIONID中,然后每次请求的时候在header中这样写:

代码语言:javascript
复制
header: {
  'content-type': 'application/json', // 默认
  'Cookie': app.globalData.JSESSIONID
},

这就能够做到SESSION不丢失,但是这样很麻烦,如果后期代码编写不当,这数据很容易丢失,所以我们并不推荐使用这种方法。

方案二:将JESSIONID放入缓存

微信为我们提供了几个方法,这几个方法类似于Java中的session.setAttrabiute()方法,都是

代码语言:javascript
复制
wx.request({
    url: serverUrl + '/login',
    data: {
    },
    header: {
      'content-type': 'application/json' // 默认值
    },
    success:function(res){
        //取出session
      var cookie = res.header["Set-Cookie"];
      if (undefined != cookie) {
        var sessionPos;
        var rememberMe;
        if ((sessionPos = cookie.indexOf("JSESSIONID=")) != -1) {
          //每次请求成功都将sessionId放入缓存
          wx.setStorageSync("JSESSIONID", cookie.substring(sessionPos, 48));
        }
        if ((sessionPos = cookie.indexOf("rememberMe=")) != -1) {
          //设置rememberme
          wx.setStorageSync("rememberMe", cookie.substring(sessionPos + 78, 712));
        }
      }
    }
  })

这段代码做的就是从Cookie的字符串中取到SessionId和RememberMe,可能因为版本不同等问题造成长度不一致,这个自己计算一下就行了。 然后就可以在小程序中建立“持久化的连接”了。

建个Util

其实像上面那样做可以,但是如果遇到session失效的情况,原有的写入的session就没了,还有就是代码复用的问题,像上面那样做,可能你每次请求的时候都要自己写Cookie之类的代码,这就很麻烦了,最好的办法就是建一个工具类,其中包括持久化连接的代码。

代码语言:javascript
复制
/**
 * 公共微信https请求封装
 * @param url
 * @param type
 * @param data
 * @param callBack 回调函数
 */
function https(url, type, data, callBack, header) {
  if (!data.isHideLoad) {
    wx.showLoading({
      title: '加载中',
    })
  }
  wx.showNavigationBarLoading();
  wx.request({
    url: url,
    method: type,
    data: data,
    header: header ? header : ({
      "Content-Type": "application/json",
      "Cookie": wx.getStorageSync('JSESSIONID') + wx.getStorageSync('rememberMe')
    }),
    success: function(res) {
      //取出session
      var cookie = res.header["Set-Cookie"];
      if (undefined != cookie) {
        var sessionPos;
        var rememberMe;
        if ((sessionPos = cookie.indexOf("JSESSIONID=")) != -1) {
          //每次请求成功都将sessionId放入缓存
          wx.setStorageSync("JSESSIONID", cookie.substring(sessionPos, 48));
        }
        if ((sessionPos = cookie.indexOf("rememberMe=")) != -1) {
          //设置rememberme
          wx.setStorageSync("rememberMe", cookie.substring(sessionPos + 78, 712));
        }
      }
      callBack(res.data);
    },
    fail: function(error) {
      // showToast("登录过期,请重新登录", "none");
      wx.reLaunch({
        url: '../../account/login',
        success: function() {
          wx.showToast({
            title: '登录过期,请重新登录',
            icon: 'none'
          })
        }
      })
    },
    complete: function(res) {
      if (res.status === 400) {
        showToast("家校通请求未授权");
      }
      wx.hideLoading();
      wx.stopPullDownRefresh();
      wx.hideNavigationBarLoading();
    }
  })
}

需要用到请求的时候,就先导入util,然后调用util.https(params…)。 如果你发现无法调用这个方法,那么问题是你没有将https这个方法暴露出去,在util方法的最后,写上这样一段代码:

代码语言:javascript
复制
module.exports = {
  https: https
}

结语

文章到这里就结束了,如果你喜欢我的文章,请多多点赞、转发。 如果您想要了解JAVA、JAVAWEB、小程序、数据库、干货……等深度文章以及学习资源(后台回复java可见,无套路),欢迎关注我的微信公众号:最高权限比特流

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年09月14日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 问题出现的场景
  • 解决问题的方案
    • 方案一:将JSESSIONID放入全局变量
      • 方案二:将JESSIONID放入缓存
      • 建个Util
      • 结语
      相关产品与服务
      云开发 CloudBase
      云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为200万+企业和开发者提供高可用、自动弹性扩缩的后端云服务,可用于云端一体化开发多种端应用(小程序、公众号、Web 应用等),避免了应用开发过程中繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档