微信开发之框架4 - Framework设计&实现
凌雪 2018-12-17 来源 :网络 阅读 813 评论 0

摘要:本文将带你了解微信开发框架4 - Framework设计&实现,希望本文对大家学微信有所帮助。

本文将带你了解微信开发框架4 - Framework设计&实现,希望本文对大家学微信有所帮助。



下图为框架的主流程:

Framework中最最核心的类为MessageProcessor,它包含以下核心功能

安全验证

解码消息

分发消息

编码消息返回

可以说MessageProcessor就是该框架的神经中枢,至于其他类都是围绕MessageProcessor展开的。

可以看到MessageReceiver包含两个方法:receiveGetMessage和receivePostMessage,其中receiveGetMessage用来接收微信服务器的get方法调用,而receivePostMessage用来接收微信服务器的post调用。

前面我们讲过MessageReceiver只是负责应用消息的分发,而不负责具体的业务处理,而需要在具体的业务中注入,而属性_messageProcessor就是业务注入点。

属性_token用来做安全验证用,具体的值就是公众号中填写的值,也需要在具体的应用中注入。

安全验证

 

在前面我们已经讲过,腾讯的微信服务器会把消息转发给我们自己的应用服务器,而转发过来的消息总的可以分为两类:

验证消息(发给接口URL的Get方法)

应用消息(发给接口URL的Post方法)

而MessageProcessor的receiveGetMessage就是用来处理微信服务器的get请求,因此也是用来处理安全验证请求的,receiveGetMessage的代码如下:

 

代码并不复杂,有以下关键点:

接收微信服务器传过来的参数集合

组合公共号中预留的Token和参数timestamp、noce进行SHA1计算,如果得出的结果恰好等于Token签名,则返回参数echostr通知微信服务器验证通过,否则返回其他任意内容(我返回了“access   deny”)表示验证不通过。

应用消息转发

在上面我们已经提到,在MessageReceiver中我们提供了两个方法:receiveGetMessage和receivePostMessage,顾名思义,receiveGetMessage用来接收微信服务器转发过来的get请求(安全验证),而方法receivePostMessage用来接收微信服务器转发过来的post请求,而post请求的内容就是具体的应用消息,而应用消息分为下面几大类:

文本消息

图片消息

语音消息

视频消息

小视频消息

地理位置消息

链接消息

更加详细的内容,大家可以阅读微信的官方开发者文档

//mp.weixin.qq.com/wiki/17/f298879f8fb29ab98b2f2971d42552fd.html

下面为函数receivePostMessage的具体代码及标注:

 

我把上面的代码根据功能分为4段:

读取原始消息

解析消息

获取消息处理结果

返回处理结果给微信服务器

其中“读取原始消息”和“返回处理结果给微信服务器”都是一些通用代码,自没什么好讲的,下面的讲解主要针对“解析消息”和“获取消息处理结果”。

解析消息

上面我们已经讲过receivePostMessage函数的目的就是接收微信服务器发送过来的应用消息,而微信服务器服务器发送的消息内容为xml格式,下面是具体的例子(来自官方开发者中心):

文本消息

     1348831860  1234567890123456 

图片消息

   1348831860    1234567890123456 

当receivePostMessage函数收到消息后就可以要把消息转发给应用层做具体的处理,而在转发的时候有两种方式:

不做任何处理,把原始的xml内容直接给应用层,由应用层对xml的内容进行解析。

在框架中把xml映射为消息对象,然后再把消息对象转发给应用层,这样应用层面对就不再是原始的xml,而是一个具体应用消息对象。

者两种方式中,显然后者更友好,也是框架应该发力的地方。为了解析xml消息,框架中定义了类ReceiveEntity,下面是该类的一个片段:

public class ReceiveEntity {    public static final String   REQ_MESSAGE_TYPE_TEXT = "text";      public static final String REQ_MESSAGE_TYPE_IMAGE =   "image";    public static   final String REQ_MESSAGE_TYPE_LINK = "link";    public static final String   REQ_MESSAGE_TYPE_LOCATION = "location";    public static final String   REQ_MESSAGE_TYPE_VOICE = "voice";      public static final String REQ_MESSAGE_TYPE_EVENT =   "event";        public static   final String EVENT_TYPE_SUBSCRIBE = "subscribe";    public static final String   EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";    public static final String   EVENT_TYPE_CLICK = "CLICK";          private String ToUserName="";    private String   FromUserName="";    private   String CreateTime="";      private String MsgType="";    //消息类型    private String   MsgId="";    private String   Event="";    private String   EventKey="";    private   String Ticket="";    private   String Latitude="";      private String Longitude="";    private String   Precision="";    private   String PicUrl="";    private   String MediaId="";    private   String Title="";    private   String Description="";

我们已经知道,微信服务器发送过来的消息有很多种,但在这里我们为每种消息都设计一个单独的类,而是设计一个大类ReceiveEntity,通过MsgType来描述消息类型。

而DomainUtility的函数getReceiveEntity就是负责把xml消息解析为ReceiveEntity对象。

 

public static ReceiveEntity   getReceiveEntity(String strXml){          ReceiveEntity entity = null;          try {            if   (strXml.length() <= 0 || strXml == null)                return null;            strXml = strXml.trim();  //There is blank space after wechat Chinese   message                        Document   document = DocumentHelper.parseText(strXml);            Element root =   document.getRootElement();              Iterator iter = root.elementIterator();                        entity = new   ReceiveEntity();              Class c = Class.forName("com.xgzhang.wechat.framework.domain.ReceiveEntity");            entity =   (ReceiveEntity)c.newInstance();                          while(iter.hasNext()){                  Element element = (Element)iter.next();                Field field =   c.getDeclaredField(element.getName());                Method method =   c.getDeclaredMethod("set"+element.getName(), field.getType());                method.invoke(entity,   element.getText());            }        } catch (Exception e) {            System.out.println("xml   format error: "+ strXml);              logger.error(strXml);              logger.error(e.getMessage(), e);            e.printStackTrace();        }        return entity;      }

获取应用层的处理结果

在上一步中,框架已经得到了一个具体的ReceiveEntity对象,接下来要做的是把具体的消息转给应用层去处理,但这里有几个问题要思考:

因为这里我们要设计的是一个框架,引用层会依赖框架,当框架不应该知道具体的应用逻辑。

对应用层来说,其并不关心消息的附加内容,它思维的方式可能只是“哎呀,我收到了一张图片,一段文字…”

应用层对消息进行处理后,可能返回一段文字给客户端,也可能返回一段音乐给客户端,但具体的消息内容,框架不关心。

按照这个思路,框架设计了接口MessageProcessor

public interface MessageProcesser {    ResponseMessage processText(String   text);    ResponseMessage   processImage(byte[] imageBuffer);      ResponseMessage processEvent(String   eventKey);}

该接口会在应用层被动态的注入到MessageReciver中,而在MessageReciver得到ReceiveEntity对象后,也不会直接把对象转给应用层,而是把ReceiveEntity中的文字、图像、事件读出来后,通过processText,ProcessImage、processEvent直接传递给应用层,如下:

//ResponseResponseMessage reponseMessage =   null;if(receiveEntity.getMsgType().equals(ReceiveEntity.REQ_MESSAGE_TYPE_TEXT)){  reponseMessage   = this._messageProcessor.processText(receiveEntity.getContent());}else   if(receiveEntity.getMsgType().equals(ReceiveEntity.REQ_MESSAGE_TYPE_IMAGE)){  reponseMessage   =   this._messageProcessor.processImage(IOUtility.downloadImage(receiveEntity.getPicUrl()));}else   if(receiveEntity.getMsgType().equals(ReceiveEntity.REQ_MESSAGE_TYPE_EVENT)){  reponseMessage   = this._messageProcessor.processEvent(receiveEntity.getEventKey());}reponseMessage.setFromUserName(receiveEntity.getToUserName());reponseMessage.setToUserName(receiveEntity.getFromUserName());

虽然应用层不接触到ReceiveEntity对象,但应用层却需要决断返回何种类型的消息给客户端,而再往下讲之前我们先了解一下,微信共支持那些类型的返回消息:

文本消息

图片消息

语音消息

视频消息

音乐消息

图文消息

下面的例子展示了具体的消息格式(来自微信官方):

回复图文消息


 回复图片消息

<xml><tousername><!--{cke_protected}{C}%3C!%2D%2D%5BCDATA%5BtoUser%5D%5D%2D%2D%3E--></tousername><fromusername><!--{cke_protected}{C}%3C!%2D%2D%5BCDATA%5BfromUser%5D%5D%2D%2D%3E--></fromusername><createtime>12345678</createtime><msgtype><!--{cke_protected}{C}%3C!%2D%2D%5BCDATA%5Bimage%5D%5D%2D%2D%3E--></msgtype><img><mediaid><!--{cke_protected}{C}%3C!%2D%2D%5BCDATA%5Bmedia_id%5D%5D%2D%2D%3E--></mediaid></xml>

本着为应用服务的原则,框架定义了各种消息对象类提供给应用层使用

 

所有的消息都继承自同一个父类ResponseMessage,这样框架层面只只知道返回的消息为ReponseMessage,而具体的消息类型由应用层来决定。

在最后框架会把具体的消息对象转成xml内容交给微信服务器,微信服务器再转给客户端。

 

    

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之微信频道!


本文由 @凌雪 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程