您的位置:首页 > 移动开发 > 微信开发

微信服务器发送三次重复的排重问题

2015-11-18 01:49 513 查看
问题来源:http://www.zhihu.com/question/22685171微信服务器在五秒内收不到响应会断掉连接,并且重新发起请求,总共重试三次由于微信官方的服务器在处理消息时候的特殊方式,导致了这种问题的发生微信的本意是为了在丢包稍微严重的情况下服务依旧能正常运行,但是这样给开发者确提升了难度一般是每隔5s发送一次请求的,但是如果我们的处理是耗时操作怎么办呢,我们在第10s才能结束操作,这怎么办>>>>>>>>>>>>>>>>>>--------仅用于企业号和服务号1.就和回答中的Aloong兄弟那样说的,我们可以先给微信服务器反馈一个空白或者不空白的数据(XML或者非XML都行),然后调用微信的高级接口,给用户发送数据即可(理由:我们反馈了一个任意数据,微信服务器认为他的工作完成了,就不会再重复发送数据了,此时我们再调用高级接口发送数据也就不会有干扰了-即使是用户短时间内多次发送请求)流程:a.得到数据response.getWriter();b.得到数据request下的所有数据--->写入一个HashMap中c.使用response的writer返回一个空白,并且关闭writer,注意如果不关闭的话,那么这个空白消息是不会被传给微信服务器的d.使用之前的HashMap的值做我们的超时处理--------通用方法2.和李一峰兄弟说的那样,建立一个简单的list缓冲-相当于消息队列,来了一个消息之后就和list比对(有msgid的消息使用msgid排重。事件类型消息推荐使用FromUserName + CreateTime[重复发送相同消息这个值是一样的] 排重。),遍历list发现如果在list中存在那么就不加入list,直接return,否则的话加入list,然后继续执行操作,执行完成后反馈即可---必须使用AsyncContext这种异步操作流程:a.新建一个静态全局ArrayList<XXX>,添加一个类XXX{msgid, FromUserName, CreateTime}b.遍历list如果在list中,那么直接return || 如果不在list中,list.add就行了(return之后由于Async的存在连接不会断开,所以request和response不会释放,也就不会断开本次回话,如果不使用Async的话,微信的结束自己的任务,不会重复发送,问题是我们也发不出数据回去了)c.耗时操作,并反馈XML数据回去模拟:只在第三次的时候返回数据,其他时候挂起Servlet中
int coutn = 1;
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
final AsyncContext asyncContext = request.startAsync(request, response);
asyncContext.setTimeout(5000);
//		asyncContext.addListener(new AsyncListener()); 这里需要自己添加
asyncContext.start(new Deal_Thread(asyncContext)); //新建一个自己的Thread类,类中执行应尽的操作
}
DealThread中
@Overridepublic void run() {Date nDate = new Date(System.currentTimeMillis());PrintWriter pw = null;Map<String, String> userSendMap = null;try {pw = ((HttpServletResponse)this.context.getResponse()).getWriter();userSendMap = new dealXML().toMap((HttpServletRequest)this.context.getRequest());//			if(is_exist(CoreServlet.list, (HashMap<String, String>)userSendMap))if(CoreServlet.coutn == 3) {Message_Text message_Text = new EasyFunctions().genaText(userSendMap.get("FromUserName"), userSendMap.get("ToUserName"), "wocao");pw.print(message_Text.toXMLString_And_enCode());}else{CoreServlet.coutn++;return;}pw.flush();pw.close();} catch (Exception e1) {e1.printStackTrace();}}
总结:第一种方法用着思维挺简单,操作也挺简单,但是要求必须是企业号或者是服务号,要求不高的话可以用这个方法,操作简单并且基本上不需要考虑多线程的问题第二种方法比较好,适用于各种情况,不仅仅是在微信上的,但是需要考虑到请求的时间问题,所以比较复杂
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息