X5内核  请求超时后会自动阻止请求返回并由代理服务器将原参数重新发送请求到服务层代码。但由于第一次请求已经请求到服务器,会导致出现重复下单、支付等重大问题。

该问题由于腾讯x5浏览器会自动阻止第一次请求返回到页面,届时将抛出io异常。最开始打算通过拦截器来进行拦截第二次请求,但这样将使页面无法接受到返回信息报错。

初步解决思路 当第二次请求访问进服务层时暂停该线程,并定时循环查询第一次请求是否返回成功,将第一次返回成功的结果赋值给第二次。

由于我们系统中所有页面请求都会过一个通用controller 所以也会有很多正常请求通过 为了不影响整体使用

这里我用到了页面验签的方法,用于验证请求是否为同一次。这里先将参数进行排序,再用md5加密,添加一个“sign”的参数到后台,后台再排序加密进行比对,进行验签,注意这里参数加入了

时间戳,用于防止重复提交

KGF.getMD5 = function(params){
params["key"] = "ouE6yWvy";
var sParams = Object.keys(params).sort();
var oriString = "";
for(key in sParams){
oriString += sParams[key]+"="+params[sParams[key]]+"&";
}
oriString = oriString.substr(0,oriString.length-1);
delete params.key;
return KGF.md5(oriString);
};

验签成功后,由于需要将第一次返回成功的结果赋值给第二次。所以需要将调用接口成功的结果存入seesion中,但此时需要及时去清理,否则容易造成服务器内存溢出。

默认调用接口成功后就将结果集放入session,验签一通过就去取,这里的关键在于何时去删除session中的值。由于所有结果访问均会通过该控制器,为了区分不同的请求,

故用sign作为键,返回结果为值。

下面贴出代码

@RequestMapping(value={"/common/ajax.do"}, method={RequestMethod.POST}, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public List<AjaxResponse> execute2(@RequestHeader(value="Accept", required=false) String accept, HttpServletRequest request){
XMLResults results = new XMLResults();
try{
AjaxObject object = (AjaxObject)request.getAttribute("ParamName");
String openid = (String) request.getSession().getAttribute("openid");
Class[] cArg = new Class[2];
cArg[0] = HttpServletRequest.class;
cArg[1] = Map.class;
DataResult dataResult = new DataResult();
Map<String, Object> params = object.getParams();
String signFromAjax = (String) params.get("sign");
long startTime = 0;
long endTime = 0;
if(!checkSign(params)){
log.error("接口请求验签失败");
dataResult.setRetInfo("-1", "接口请求验签失败", CommonUtil.parseDoubleList(new HashMap()));
}else{
String signFromSession = (String) request.getSession().getAttribute(signFromAjax);
request.getSession().setAttribute(signFromAjax,signFromAjax);
//处理腾讯安卓微信浏览器,10s重发请求的问题
if(signFromSession != null){
for(int i = 0; i <10; i++){
try {
Thread.currentThread().sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
log.debug("====================重复请求读取接口返回信息:第"+(i+1)+"次====================");
DataResult dataResultFromSession = (DataResult) request.getSession().getAttribute(signFromAjax+"interfaceResult");
if(dataResultFromSession != null){
request.getSession().removeAttribute(signFromAjax);
request.getSession().removeAttribute(signFromAjax+"interfaceResult");
results = this.baseService.convertResult(dataResult);
dataResult = dataResultFromSession;
break;
}
if(i == 9){
dataResult.setRetInfo("-1", "接口请求超时,请联系管理员", CommonUtil.parseDoubleList(new HashMap()));
}
}
}else{
startTime = new Date().getTime();
params.put("requestIp", CommonUtil.getIpAddr(request));
params.put("openid", openid);
params.put("deviceType", CommonUtil.getDeviceType(request));
params.put("browserType", CommonUtil.getBrowserType(request));
params.put("g_stationaddr", CommonUtil.getIpAddr(request));
Method method = commonDataModel.getClass().getDeclaredMethod(object.getCode(), cArg);
dataResult = (DataResult) method.invoke(commonDataModel, request, params);
endTime = new Date().getTime();
request.getSession().setAttribute(signFromAjax+"interfaceResult", dataResult);
}
}
if(endTime - startTime <= 10000){
request.getSession().removeAttribute(signFromAjax);
request.getSession().removeAttribute(signFromAjax+"interfaceResult");
}
results = this.baseService.convertResult(dataResult);
}catch (Exception e){
log.error("数据请求失败,错误信息:" + e.getMessage());
results.setRetInfo("-1", "数据请求失败");
}
return webHelper.convertAjaxResponse(results);
}

微信内置安卓x5浏览器请求超时自动重发问题处理小记的更多相关文章

  1. 2017年05月10日记一次微项目投产 | 安卓版微信内置浏览器不能解析gzip压缩过的mp4视频的问题

    前言 今天投产了一个小项目,一个很简单的H5,有播放视频功能,使用了videojs插件. 之前也做过数个视频播放,视频的转压都按照既定流程进行,文件放到FTP后,iphone和安卓机测试下来都没有问题 ...

  2. 让微信内置浏览器兼容clipboard.js 复制粘贴 ios 安卓

    <!--js copy事件--><script type="text/javascript" src="/static/js/clipboard.min ...

  3. 微信内置浏览器http请求10秒内接收不到数据会自动重发第二遍请求

    微信内置浏览器http请求10秒内接收不到数据会自动重发第二遍请求     这是个坑

  4. asp.net微信内置浏览器下Session失效

    问题记录:仅限安卓端微信内置浏览器,服务器集群设置了黏性Session,在Post请求时会强制走代理,导致出去的ip指向另一台服务器,黏性Session失效,用户状态无法保存. 目前想知道除了设置Se ...

  5. 微信内置浏览器WebApp开发,踩坑 · Issue #31 · maxzhang/maxzhang.github.com · GitHub

    最近花6天时间完成了一个七夕的小活动,是一个简单的WebApp.由于我前期对面向微信的Web开发评估不足,导致开发过程十分艰难.写这篇文章总结下,惊醒自己未来不要再犯这样的错误. 问题: 1. 有些比 ...

  6. 微信内置浏览器的JsAPI(WeixinJSBridge续)[转载]

    原文地址:  http://www.baidufe.com/item/f07a3be0b23b4c9606bb.html 之前有写过几篇关于微信内置浏览器(WebView)中特有的Javascript ...

  7. 【微网站开发】之微信内置浏览器API使用

    最近在写微网站,发现了微信内置浏览器的很多不称心的地方: 1.安卓版的微信内浏览器底部总是出现一个刷新.前进.后退的底部栏,宽度很大,导致屏幕显示尺寸被压缩 2.分享当前网站至朋友圈时,分享的图片一般 ...

  8. 微信内置浏览器中,点击下拉框出现页面乱跳转现象(iphone)

    微信内置浏览器中,点击下拉框出现页面乱跳转现象(iphone) 前言: 这是小菜博客的第三篇文章.一直认为自己可以表达的东西太过简单,难以上台面,总是吝啬地不肯写.就算是写,也不知道从何开始.在同事的 ...

  9. 微信内置浏览器的JsAPI(WeixinJSBridge续)_Alien的笔记

    微信内置浏览器的JsAPI(WeixinJSBridge续)_Alien的笔记 微信内置浏览器的JsAPI(WeixinJSBridge续)进入全屏 之前有写过几篇关于微信内置浏览器(WebView) ...

随机推荐

  1. linux php --ini

    $ php --ini

  2. 每天学点Linux-切割命令split

    一种常见的需求是,有一个比较大的文件,需要把它切割成比较小的几个文件,在Linux系统中你就可以使用Split命令了.Split命令可以将一个大的文件按照文件大小或者行数切割成小文件.Split命令的 ...

  3. 框架源码系列十二:Mybatis源码之手写Mybatis

    一.需求分析 1.Mybatis是什么? 一个半自动化的orm框架(Object Relation Mapping). 2.Mybatis完成什么工作? 在面向对象编程中,我们操作的都是对象,Myba ...

  4. Elasticsearch学习笔记——常用命令

    1.创建一个名字为index的topic curl -XPUT http://localhost:9200/index 2.创建一个mapping curl -XPOST http://localho ...

  5. c++ protobuf序列化

    只看了int类型的序列化,后面的有时间再研究 #include <vector> #include <iostream> int main() { ; while (true) ...

  6. 学习Vue 入门到实战——学习笔记

    闲聊: 自从进了现在的公司,小颖就再没怎么接触vue了,最近不太忙,所以想再学习下vue,就看了看vue相关视频,顺便做个笔记嘻嘻. 视频地址:Vue 入门到实战1.Vue 入门到实战2 学习内容: ...

  7. react better-scroll 编写类似手机chrome的header显示隐藏效果

    关键代码 const H = 50; // header的高度 const H2 = H / 2; let cy = 0; class Home extends Component { @observ ...

  8. windows下eclipse实现操作虚拟机ubantu中的hdfs hbase

    1.首先打开虚拟机,查看虚拟机的ip地址 2.修改C:\Windows\System32\drivers\etc下的主机名与ip的映射文件 3.配置Map/reduce 配置成功后可以查看hdfs文件 ...

  9. web开发中xml的内容

    文档声明(注:文档声明前不能有注释) XML中的元素/标签 注:xmlx中解析程序会将其中的空格与换行当做内容来解析,区分大小写 CDATA区域中的内容不解析

  10. GitLab使用公钥SSH key登录

    SSH key提供了一种与GitLab通信的方式,能够不输密码就进行版本控制 第一步,检查SSH key是否存在 如果存在则把SSH Key放到GitLab上,如果不存在则生成新的SSH Key,再放 ...