(Java)微信之个人公众账号开发(二)——接收并处理用户消息(上)

来源:互联网 发布:句子知乎诗词 编辑:程序博客网 时间:2024/06/05 19:37

经过上一篇,大家成功进入开发者模式后,主要工作就是我们服务器的后台开发了,这个跟我们平时的web项目没什么两样,主要就是根据微信服务器传过来的消息类型及内容进行判断和处理,然后返回相应信息。而消息的处理则主要在servlet中的POST方法中,get方法主要用来验证消息是否来自微信服务器,而post方法则主要接收用户消息类型和内容进行处理。下面是servlet中的post方法的代码:

/** * 处理微信服务器发来的消息 */public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 将请求、响应的编码均设置为UTF-8(防止中文乱码)request.setCharacterEncoding("UTF-8");response.setCharacterEncoding("UTF-8");// 接收消息、处理消息String respMessage = BylService.processRequest(request);// 响应消息PrintWriter out = response.getWriter();out.print(respMessage);out.close();}


其中最主要的便是BylService这个业务类(名字当然是自己定的了),业务类单独写有助于提高程序可读性和美观性。再写这个业务类前,我们有必要先了解下,消息都有那些类型,以及微信服务器发过来的各类型的xml数据包格式。具体情况大家参考微信公众平台开发者文档:http://mp.weixin.qq.com/wiki/index.php

~

在上图中我们看到,消息的几种类型:文本消息,图片消息,语音消息,视频消息,地理位置消息,链接消息,具体参数开发者文档中已经详细说明,需要强调的是,微信服务器发过来的是xml数据包,我们接收到这个数据包(输入流)后需要对其解析并得到里面包含的标签以及对应额参数值,返回的消息同样需要转换为固定的xml格式。具体步骤我们下面再讲,现在先看我们的消息类型,既然用java开发,我们就要知道java的特性——面向对象,所以我们可以把这些消息类型全部封装为对象,并抽取这几个消息类型相同的属性为父类,然后子类继承。具体结构如下图:

 

下面是requestBean包(接收的消息)中的BaseMessage.java(父类):

public class BaseMessage {    // 开发者微信号      private String ToUserName;      // 发送方帐号(一个OpenID)      private String FromUserName;      // 消息创建时间 (整型)      private long CreateTime;      // 消息类型(text/image/location/link)      private String MsgType;      // 消息id,64位整型      private long MsgId;        public String getToUserName() {          return ToUserName;      }        public void setToUserName(String toUserName) {          ToUserName = toUserName;      }        public String getFromUserName() {          return FromUserName;      }        public void setFromUserName(String fromUserName) {          FromUserName = fromUserName;      }        public long getCreateTime() {          return CreateTime;      }        public void setCreateTime(long createTime) {          CreateTime = createTime;      }        public String getMsgType() {          return MsgType;      }        public void setMsgType(String msgType) {          MsgType = msgType;      }        public long getMsgId() {          return MsgId;      }        public void setMsgId(long msgId) {          MsgId = msgId;      }  }

requestBean包中的TextMessage.java(文本消息类):

public class TextMessage extends BaseMessage{// 消息内容      private String Content;        public String getContent() {          return Content;      }        public void setContent(String content) {          Content = content;      }  }

下面是responseBean包(回复的消息)中的BaseMessage.java(父类):

public class BaseMessage {      // 接收方帐号(收到的OpenID)      private String ToUserName;      // 开发者微信号      private String FromUserName;      // 消息创建时间 (整型)      private long CreateTime;      // 消息类型(text/music/news)      private String MsgType;      // 位0x0001被标志时,星标刚收到的消息      private int FuncFlag;        public String getToUserName() {          return ToUserName;      }        public void setToUserName(String toUserName) {          ToUserName = toUserName;      }        public String getFromUserName() {          return FromUserName;      }        public void setFromUserName(String fromUserName) {          FromUserName = fromUserName;      }        public long getCreateTime() {          return CreateTime;      }        public void setCreateTime(long createTime) {          CreateTime = createTime;      }        public String getMsgType() {          return MsgType;      }        public void setMsgType(String msgType) {          MsgType = msgType;      }        public int getFuncFlag() {          return FuncFlag;      }        public void setFuncFlag(int funcFlag) {          FuncFlag = funcFlag;      }  }  

responseBean包中的TextMessage.java(文本消息类):

public class TextMessage extends BaseMessage {      // 回复的消息内容      private String Content;        public String getContent() {          return Content;      }        public void setContent(String content) {          Content = content;      }  

现只举文本消息为例,其他类型类似,大家可以根据开发者文档中每种类型的参数进行封装,好,下面我们就来看具体的业务类BylService:

public class BylService {/** * 处理微信发来的请求 * @param request * @return */public static String processRequest(HttpServletRequest request) {String respMessage = null; // 默认返回的文本消息内容          String respContent = "请求处理异常,请稍候尝试!";  try {// xml请求解析Map<String, String> requestMap = MessageUtil.parseXml(request);// 发送方帐号(open_id)String fromUserName = requestMap.get("FromUserName");// 公众帐号String toUserName = requestMap.get("ToUserName");// 消息类型String msgType = requestMap.get("MsgType");// 默认回复此文本消息TextMessage textMessage = new TextMessage();textMessage.setToUserName(fromUserName);textMessage.setFromUserName(toUserName);textMessage.setCreateTime(new Date().getTime());textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);textMessage.setFuncFlag(0);String content = requestMap.get("Content");// 文本消息if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {//DisposeMsgUtil是对文本消息的处理工具类     textMessage.setContent(DisposeMsgUtil.disposeMsg(content));      textMessage.setContent(respContent);                respMessage = MessageUtil.textMessageToXml(textMessage);   }else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) {// 图片消息 respContent = "您发送的是图片消息!"; textMessage.setContent(respContent);                respMessage = MessageUtil.textMessageToXml(textMessage);}else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)) {// 地理位置消息respContent = "您发送的是地理位置消息!"; textMessage.setContent(respContent);                respMessage = MessageUtil.textMessageToXml(textMessage);}else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)) {// 链接消息respContent = "您发送的是链接消息!"; textMessage.setContent(respContent);                respMessage = MessageUtil.textMessageToXml(textMessage);}else if (msgType.equals(MessageUtil.RESP_MESSAGE_TYPE_MUSIC)) {// 音频消息respContent = "您发送的是音频消息!"; textMessage.setContent(respContent);                respMessage = MessageUtil.textMessageToXml(textMessage);}else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)) {// 音频消息respContent = "您发送的是音频消息!"; textMessage.setContent(respContent);                respMessage = MessageUtil.textMessageToXml(textMessage);}else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {// 事件推送String eventType = requestMap.get("Event");// 事件类型if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {// 订阅//当用户点击关注时,会立即发送该条消息respContent = "欢迎关注ipastor生活小助手"+"/微笑";textMessage.setContent(respContent);respMessage = MessageUtil.textMessageToXml(textMessage);}else if (eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) {// 取消订阅// 取消订阅后点击事件}else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {// 自定义菜单点击事件// 自定义菜单权点击事件}}} catch (Exception e) {e.printStackTrace();}return respMessage;}}


我们先看消息处理工具类:MessageUtil,其中定义了每种消息类型的静态变量:

/** * 返回消息类型:文本 */public static final String RESP_MESSAGE_TYPE_TEXT = "text";/** * 返回消息类型:音乐 */public static final String RESP_MESSAGE_TYPE_MUSIC = "music";/** * 返回消息类型:图文 */public static final String RESP_MESSAGE_TYPE_NEWS = "news";/** * 请求消息类型:文本 */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";/** * 事件类型:subscribe(订阅) */public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";/** * 事件类型:unsubscribe(取消订阅) */public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";/** * 事件类型:CLICK(自定义菜单点击事件) */public static final String EVENT_TYPE_CLICK = "CLICK";


判断消息类型时便可根据是否与MessageUtil.xxx相同来判断消息类型,并做出相应处理。

MessageUtil对xml数据包的具体处理方法,以及文本消息处理类DisposeMsgUtil将在下一篇文章中继续讲解。



 

 

 

 

 

 

 

 

 

 

0 0
原创粉丝点击