[028] 微信公众帐号开发教程第4篇-消息及消息处理工具的封装(转)

简介:

工欲善其事必先利其器!本篇内容主要解说怎样将微信公众平台定义的消息及消息相关的操作封装成工具类,方面后期的使用。这里须要明白的是消息事实上是由用户发给你的公众帐号的,消息先被微信平台接收到,然后微信平台会将该消息转给你在开发模式接口配置中指定的URL地址。

 

微信公众平台消息接口

要接收微信平台发送的消息,我们须要先熟悉微信公众平台API中消息接口部分,点此进入,点击后将进入到消息接口指南部分,例如以下图所看到的:

在上图左側能够看到微信公众平台眼下开放的接口有三种:消息接口、通用接口和自己定义菜单接口。通用接口和自己定义菜单接口唯独拿到内測资格才干调用,而内測资格的申请也已经关闭了,我们唯独期待将来某一天微信会对大众用户开放吧,所以沒有内測资格的用户就不要再浪费时间在这两个接口上,仅仅须要用好消息接口就能够了。

 

消息推送和消息回复

以下将主要介绍消息接口。对于消息的接收、响应我们仅仅须要关注上图中的“4 消息推送”和“5 消息回复”就足够了。

我们先来了解接口中的“消息推送”指的是什么,点击“4 消息推送”,能够看到接口中的“消息推送”指的是“当普通用户向公众帐号发消息时,微信server将POST该消息到填写的URL上”,即这里定义的是用户能够发送哪些类型的消息、消息有哪些字段、消息被微信server以什么方式转发给我们的公众帐号后台。

消息推送中定义了我们将会接收到的消息类型有5种:文本消息、图片消息、地理位置消息、链接消息和事件推送,事实上语音消息我们也能够接收到的,仅仅只是拿不到详细的语音文件而以(须要内測资格才干够获取语音文件)。

 

接口中的“消息回复”定义了我们能回复给用户的消息类型、消息字段和消息格式,微信公众平台的接口指南中是这样描写叙述的:

上面说到我们能回复给用户的消息有5种,但眼下在开发模式下能回复的消息唯独3种:文本消息、音乐消息和图文消息,而语音消息和视频消息眼下仅仅能在编辑模式下使用。

 

消息的封装

接下来要做的就是将消息推送(请求)、消息回复(响应)中定义的消息进行封装,建立与之相应的Java类(Java是一门面向对象的编程语言,封装后使用起来更方便),以下的请求消息是指消息推送中定义的消息,响应消息指消息回复中定义的消息。

请求消息的基类

把消息推送中定义的全部消息都有的字段提取出来,封装成一个基类,这些公有的字段包含:ToUserName(开发人员微信号)、FromUserName(发送方帐号,OPEN_ID)、CreateTime(消息的创建时间)、MsgType(消息类型)、MsgId(消息ID),封装后基类org.liufeng.course.message.req.BaseMessage的代码例如以下:

 

[java]  view plain copy
 
  1. package org.liufeng.course.message.req;  
  2.   
  3. /** 
  4.  * 消息基类(普通用户 -> 公众帐号) 
  5.  *  
  6.  * @author liufeng 
  7.  * @date 2013-05-19 
  8.  */  
  9. public class BaseMessage {  
  10.     // 开发人员微信号  
  11.     private String ToUserName;  
  12.     // 发送方帐号(一个OpenID)  
  13.     private String FromUserName;  
  14.     // 消息创建时间 (整型)  
  15.     private long CreateTime;  
  16.     // 消息类型(text/image/location/link)  
  17.     private String MsgType;  
  18.     // 消息id,64位整型  
  19.     private long MsgId;  
  20.   
  21.     public String getToUserName() {  
  22.         return ToUserName;  
  23.     }  
  24.   
  25.     public void setToUserName(String toUserName) {  
  26.         ToUserName = toUserName;  
  27.     }  
  28.   
  29.     public String getFromUserName() {  
  30.         return FromUserName;  
  31.     }  
  32.   
  33.     public void setFromUserName(String fromUserName) {  
  34.         FromUserName = fromUserName;  
  35.     }  
  36.   
  37.     public long getCreateTime() {  
  38.         return CreateTime;  
  39.     }  
  40.   
  41.     public void setCreateTime(long createTime) {  
  42.         CreateTime = createTime;  
  43.     }  
  44.   
  45.     public String getMsgType() {  
  46.         return MsgType;  
  47.     }  
  48.   
  49.     public void setMsgType(String msgType) {  
  50.         MsgType = msgType;  
  51.     }  
  52.   
  53.     public long getMsgId() {  
  54.         return MsgId;  
  55.     }  
  56.   
  57.     public void setMsgId(long msgId) {  
  58.         MsgId = msgId;  
  59.     }  
  60. }  

请求消息之文本消息

[java]  view plain copy
 
  1. package org.liufeng.course.message.req;  
  2.   
  3. /** 
  4.  * 文本消息 
  5.  *  
  6.  * @author liufeng 
  7.  * @date 2013-05-19 
  8.  */  
  9. public class TextMessage extends BaseMessage {  
  10.     // 消息内容  
  11.     private String Content;  
  12.   
  13.     public String getContent() {  
  14.         return Content;  
  15.     }  
  16.   
  17.     public void setContent(String content) {  
  18.         Content = content;  
  19.     }  
  20. }  

请求消息之图片消息

 

[java]  view plain copy
 
  1. package org.liufeng.course.message.req;  
  2.   
  3. /** 
  4.  * 图片消息 
  5.  *  
  6.  * @author liufeng 
  7.  * @date 2013-05-19 
  8.  */  
  9. public class ImageMessage extends BaseMessage {  
  10.     // 图片链接  
  11.     private String PicUrl;  
  12.   
  13.     public String getPicUrl() {  
  14.         return PicUrl;  
  15.     }  
  16.   
  17.     public void setPicUrl(String picUrl) {  
  18.         PicUrl = picUrl;  
  19.     }  
  20. }  

请求消息之地理位置消息

[java]  view plain copy
 
  1. package org.liufeng.course.message.req;  
  2.   
  3. /** 
  4.  * 地理位置消息 
  5.  *  
  6.  * @author liufeng 
  7.  * @date 2013-05-19 
  8.  */  
  9. public class LocationMessage extends BaseMessage {  
  10.     // 地理位置维度  
  11.     private String Location_X;  
  12.     // 地理位置经度  
  13.     private String Location_Y;  
  14.     // 地图缩放大小  
  15.     private String Scale;  
  16.     // 地理位置信息  
  17.     private String Label;  
  18.   
  19.     public String getLocation_X() {  
  20.         return Location_X;  
  21.     }  
  22.   
  23.     public void setLocation_X(String location_X) {  
  24.         Location_X = location_X;  
  25.     }  
  26.   
  27.     public String getLocation_Y() {  
  28.         return Location_Y;  
  29.     }  
  30.   
  31.     public void setLocation_Y(String location_Y) {  
  32.         Location_Y = location_Y;  
  33.     }  
  34.   
  35.     public String getScale() {  
  36.         return Scale;  
  37.     }  
  38.   
  39.     public void setScale(String scale) {  
  40.         Scale = scale;  
  41.     }  
  42.   
  43.     public String getLabel() {  
  44.         return Label;  
  45.     }  
  46.   
  47.     public void setLabel(String label) {  
  48.         Label = label;  
  49.     }  
  50. }  

请求消息之链接消息

[java]  view plain copy
 
  1. package org.liufeng.course.message.req;  
  2.   
  3. /** 
  4.  * 链接消息 
  5.  *  
  6.  * @author liufeng 
  7.  * @date 2013-05-19 
  8.  */  
  9. public class LinkMessage extends BaseMessage {  
  10.     // 消息标题  
  11.     private String Title;  
  12.     // 消息描写叙述  
  13.     private String Description;  
  14.     // 消息链接  
  15.     private String Url;  
  16.   
  17.     public String getTitle() {  
  18.         return Title;  
  19.     }  
  20.   
  21.     public void setTitle(String title) {  
  22.         Title = title;  
  23.     }  
  24.   
  25.     public String getDescription() {  
  26.         return Description;  
  27.     }  
  28.   
  29.     public void setDescription(String description) {  
  30.         Description = description;  
  31.     }  
  32.   
  33.     public String getUrl() {  
  34.         return Url;  
  35.     }  
  36.   
  37.     public void setUrl(String url) {  
  38.         Url = url;  
  39.     }  
  40. }  

请求消息之语音消息

[java]  view plain copy
 
  1. package org.liufeng.course.message.req;  
  2.   
  3. /** 
  4.  * 音频消息 
  5.  *  
  6.  * @author liufeng 
  7.  * @date 2013-05-19 
  8.  */  
  9. public class VoiceMessage extends BaseMessage {  
  10.     // 媒体ID  
  11.     private String MediaId;  
  12.     // 语音格式  
  13.     private String Format;  
  14.   
  15.     public String getMediaId() {  
  16.         return MediaId;  
  17.     }  
  18.   
  19.     public void setMediaId(String mediaId) {  
  20.         MediaId = mediaId;  
  21.     }  
  22.   
  23.     public String getFormat() {  
  24.         return Format;  
  25.     }  
  26.   
  27.     public void setFormat(String format) {  
  28.         Format = format;  
  29.     }  
  30. }  

响应消息的基类

相同,把消息回复中定义的全部消息都有的字段提取出来,封装成一个基类,这些公有的字段包含:ToUserName(接收方帐号,用户的OPEN_ID)、FromUserName(开发人员的微信号)、CreateTime(消息的创建时间)、MsgType(消息类型)、FuncFlag(消息的星标标识),封装后基类org.liufeng.course.message.resp.BaseMessage的代码例如以下:

 

[java]  view plain copy
 
  1. package org.liufeng.course.message.resp;  
  2.   
  3. /** 
  4.  * 消息基类(公众帐号 -> 普通用户) 
  5.  *  
  6.  * @author liufeng 
  7.  * @date 2013-05-19 
  8.  */  
  9. public class BaseMessage {  
  10.     // 接收方帐号(收到的OpenID)  
  11.     private String ToUserName;  
  12.     // 开发人员微信号  
  13.     private String FromUserName;  
  14.     // 消息创建时间 (整型)  
  15.     private long CreateTime;  
  16.     // 消息类型(text/music/news)  
  17.     private String MsgType;  
  18.     // 位0x0001被标志时,星标刚收到的消息  
  19.     private int FuncFlag;  
  20.   
  21.     public String getToUserName() {  
  22.         return ToUserName;  
  23.     }  
  24.   
  25.     public void setToUserName(String toUserName) {  
  26.         ToUserName = toUserName;  
  27.     }  
  28.   
  29.     public String getFromUserName() {  
  30.         return FromUserName;  
  31.     }  
  32.   
  33.     public void setFromUserName(String fromUserName) {  
  34.         FromUserName = fromUserName;  
  35.     }  
  36.   
  37.     public long getCreateTime() {  
  38.         return CreateTime;  
  39.     }  
  40.   
  41.     public void setCreateTime(long createTime) {  
  42.         CreateTime = createTime;  
  43.     }  
  44.   
  45.     public String getMsgType() {  
  46.         return MsgType;  
  47.     }  
  48.   
  49.     public void setMsgType(String msgType) {  
  50.         MsgType = msgType;  
  51.     }  
  52.   
  53.     public int getFuncFlag() {  
  54.         return FuncFlag;  
  55.     }  
  56.   
  57.     public void setFuncFlag(int funcFlag) {  
  58.         FuncFlag = funcFlag;  
  59.     }  
  60. }  

响应消息之文本消息

 

[java]  view plain copy
 
  1. package org.liufeng.course.message.resp;  
  2.   
  3. /** 
  4.  * 文本消息 
  5.  *  
  6.  * @author liufeng 
  7.  * @date 2013-05-19 
  8.  */  
  9. public class TextMessage extends BaseMessage {  
  10.     // 回复的消息内容  
  11.     private String Content;  
  12.   
  13.     public String getContent() {  
  14.         return Content;  
  15.     }  
  16.   
  17.     public void setContent(String content) {  
  18.         Content = content;  
  19.     }  
  20. }  

响应消息之音乐消息

 

[java]  view plain copy
 
  1. package org.liufeng.course.message.resp;  
  2.   
  3. /** 
  4.  * 音乐消息 
  5.  *  
  6.  * @author liufeng 
  7.  * @date 2013-05-19 
  8.  */  
  9. public class MusicMessage extends BaseMessage {  
  10.     // 音乐  
  11.     private Music Music;  
  12.   
  13.     public Music getMusic() {  
  14.         return Music;  
  15.     }  
  16.   
  17.     public void setMusic(Music music) {  
  18.         Music = music;  
  19.     }  
  20. }  

音乐消息中Music类的定义

[java]  view plain copy
 
  1. package org.liufeng.course.message.resp;  
  2.   
  3. /** 
  4.  * 音乐model 
  5.  *  
  6.  * @author liufeng 
  7.  * @date 2013-05-19 
  8.  */  
  9. public class Music {  
  10.     // 音乐名称  
  11.     private String Title;  
  12.     // 音乐描写叙述  
  13.     private String Description;  
  14.     // 音乐链接  
  15.     private String MusicUrl;  
  16.     // 高质量音乐链接,WIFI环境优先使用该链接播放音乐  
  17.     private String HQMusicUrl;  
  18.   
  19.     public String getTitle() {  
  20.         return Title;  
  21.     }  
  22.   
  23.     public void setTitle(String title) {  
  24.         Title = title;  
  25.     }  
  26.   
  27.     public String getDescription() {  
  28.         return Description;  
  29.     }  
  30.   
  31.     public void setDescription(String description) {  
  32.         Description = description;  
  33.     }  
  34.   
  35.     public String getMusicUrl() {  
  36.         return MusicUrl;  
  37.     }  
  38.   
  39.     public void setMusicUrl(String musicUrl) {  
  40.         MusicUrl = musicUrl;  
  41.     }  
  42.   
  43.     public String getHQMusicUrl() {  
  44.         return HQMusicUrl;  
  45.     }  
  46.   
  47.     public void setHQMusicUrl(String musicUrl) {  
  48.         HQMusicUrl = musicUrl;  
  49.     }  
  50.   
  51. }  

响应消息之图文消息

 

[java]  view plain copy
 
  1. package org.liufeng.course.message.resp;  
  2.   
  3. import java.util.List;  
  4.   
  5. /** 
  6.  * 文本消息 
  7.  *  
  8.  * @author liufeng 
  9.  * @date 2013-05-19 
  10.  */  
  11. public class NewsMessage extends BaseMessage {  
  12.     // 图文消息个数,限制为10条以内  
  13.     private int ArticleCount;  
  14.     // 多条图文消息信息,默认第一个item为大图  
  15.     private List<Article> Articles;  
  16.   
  17.     public int getArticleCount() {  
  18.         return ArticleCount;  
  19.     }  
  20.   
  21.     public void setArticleCount(int articleCount) {  
  22.         ArticleCount = articleCount;  
  23.     }  
  24.   
  25.     public List<Article> getArticles() {  
  26.         return Articles;  
  27.     }  
  28.   
  29.     public void setArticles(List<Article> articles) {  
  30.         Articles = articles;  
  31.     }  
  32. }  

图文消息中Article类的定义

[java]  view plain copy
 
  1. package org.liufeng.course.message.resp;  
  2.   
  3. /** 
  4.  * 图文model 
  5.  *  
  6.  * @author liufeng 
  7.  * @date 2013-05-19 
  8.  */  
  9. public class Article {  
  10.     // 图文消息名称  
  11.     private String Title;  
  12.     // 图文消息描写叙述  
  13.     private String Description;  
  14.     // 图片链接,支持JPG、PNG格式,较好的效果为大图640*320,小图80*80,限制图片链接的域名须要与开发人员填写的基本资料中的Url一致  
  15.     private String PicUrl;  
  16.     // 点击图文消息跳转链接  
  17.     private String Url;  
  18.   
  19.     public String getTitle() {  
  20.         return Title;  
  21.     }  
  22.   
  23.     public void setTitle(String title) {  
  24.         Title = title;  
  25.     }  
  26.   
  27.     public String getDescription() {  
  28.         return null == Description ? "" : Description;  
  29.     }  
  30.   
  31.     public void setDescription(String description) {  
  32.         Description = description;  
  33.     }  
  34.   
  35.     public String getPicUrl() {  
  36.         return null == PicUrl ? "" : PicUrl;  
  37.     }  
  38.   
  39.     public void setPicUrl(String picUrl) {  
  40.         PicUrl = picUrl;  
  41.     }  
  42.   
  43.     public String getUrl() {  
  44.         return null == Url ? "" : Url;  
  45.     }  
  46.   
  47.     public void setUrl(String url) {  
  48.         Url = url;  
  49.     }  
  50.   
  51. }  

全部消息封装完成后,Eclipse工程中关于消息部分的结构应该与下图保持一致,假设不一致的(类名、属性名称不一致的)请检查后调整一致,因为后面的章节还要介绍怎样将微信开发中通用的类方法、与业务无关的工具类封装打成jar包,以后再做微信项目仅仅须要引入该jar包就可以,这样的工作做一次就能够了。

 

怎样解析请求消息?

接下来解决请求消息的解析问题。微信server会将用户的请求通过doPost方法发送给我们,让我们再来回忆下上一章节已经写好的doPost方法的定义:

 

[java]  view plain copy
 
  1. /**  
  2.     * 处理微信server发来的消息  
  3.     */    
  4.    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {    
  5.        // TODO 消息的接收、处理、响应    
  6.    }    

doPost方法有两个參数,request中封装了请求相关的全部内容,能够从request中取出微信server发来的消息;而通过response我们能够对接收到的消息进行响应,即发送消息。

 

那么怎样解析请求消息的问题也就转化为怎样从request中得到微信server发送给我们的xml格式的消息了。这里我们借助于开源框架dom4j去解析xml(这里使用的是dom4j-1.6.1.jar),然后将解析得到的结果存入HashMap,解析请求消息的方法例如以下:

 

[java]  view plain copy
 
  1. /** 
  2.  * 解析微信发来的请求(XML) 
  3.  *  
  4.  * @param request 
  5.  * @return 
  6.  * @throws Exception 
  7.  */  
  8. @SuppressWarnings("unchecked")  
  9. public static Map<String, String> parseXml(HttpServletRequest request) throws Exception {  
  10.     // 将解析结果存储在HashMap中  
  11.     Map<String, String> map = new HashMap<String, String>();  
  12.   
  13.     // 从request中取得输入流  
  14.     InputStream inputStream = request.getInputStream();  
  15.     // 读取输入流  
  16.     SAXReader reader = new SAXReader();  
  17.     Document document = reader.read(inputStream);  
  18.     // 得到xml根元素  
  19.     Element root = document.getRootElement();  
  20.     // 得到根元素的全部子节点  
  21.     List<Element> elementList = root.elements();  
  22.   
  23.     // 遍历全部子节点  
  24.     for (Element e : elementList)  
  25.         map.put(e.getName(), e.getText());  
  26.   
  27.     // 释放资源  
  28.     inputStream.close();  
  29.     inputStream = null;  
  30.   
  31.     return map;  
  32. }  

怎样将响应消息转换成xml返回?

 

我们先前已经将响应消息封装成了Java类,方便我们在代码中使用。那么,请求接收成功、处理完成后,该怎样将消息返回呢?这里就涉及到怎样将响应消息转换成xml返回的问题,这里我们将採用开源框架xstream来实现Java类到xml的转换(这里使用的是xstream-1.3.1.jar),代码例如以下:

 

[java]  view plain copy
 
  1. /** 
  2.  * 文本消息对象转换成xml 
  3.  *  
  4.  * @param textMessage 文本消息对象 
  5.  * @return xml 
  6.  */  
  7. public static String textMessageToXml(TextMessage textMessage) {  
  8.     xstream.alias("xml", textMessage.getClass());  
  9.     return xstream.toXML(textMessage);  
  10. }  
  11.   
  12. /** 
  13.  * 音乐消息对象转换成xml 
  14.  *  
  15.  * @param musicMessage 音乐消息对象 
  16.  * @return xml 
  17.  */  
  18. public static String musicMessageToXml(MusicMessage musicMessage) {  
  19.     xstream.alias("xml", musicMessage.getClass());  
  20.     return xstream.toXML(musicMessage);  
  21. }  
  22.   
  23. /** 
  24.  * 图文消息对象转换成xml 
  25.  *  
  26.  * @param newsMessage 图文消息对象 
  27.  * @return xml 
  28.  */  
  29. public static String newsMessageToXml(NewsMessage newsMessage) {  
  30.     xstream.alias("xml", newsMessage.getClass());  
  31.     xstream.alias("item"new Article().getClass());  
  32.     return xstream.toXML(newsMessage);  
  33. }  
  34.   
  35. /** 
  36.  * 扩展xstream,使其支持CDATA块 
  37.  *  
  38.  * @date 2013-05-19 
  39.  */  
  40. private static XStream xstream = new XStream(new XppDriver() {  
  41.     public HierarchicalStreamWriter createWriter(Writer out) {  
  42.         return new PrettyPrintWriter(out) {  
  43.             // 对全部xml节点的转换都添加CDATA标记  
  44.             boolean cdata = true;  
  45.   
  46.             @SuppressWarnings("unchecked")  
  47.             public void startNode(String name, Class clazz) {  
  48.                 super.startNode(name, clazz);  
  49.             }  
  50.   
  51.             protected void writeText(QuickWriter writer, String text) {  
  52.                 if (cdata) {  
  53.                     writer.write("<![CDATA[");  
  54.                     writer.write(text);  
  55.                     writer.write("]]>");  
  56.                 } else {  
  57.                     writer.write(text);  
  58.                 }  
  59.             }  
  60.         };  
  61.     }  
  62. });  

说明:因为xstream框架本身并不支持CDATA块的生成,40~62行代码是对xtream做了扩展,使其支持在生成xml各元素值时添加CDATA块。

消息处理工具的封装

知道怎么解析请求消息,也知道怎样将响应消息转化成xml了,接下来就是将消息相关的处理方法全部封装到工具类MessageUtil中,该类的完整代码例如以下:

 

[java]  view plain copy
 
  1. package org.liufeng.course.util;  
  2.   
  3. import java.io.InputStream;  
  4. import java.io.Writer;  
  5. import java.util.HashMap;  
  6. import java.util.List;  
  7. import java.util.Map;  
  8.   
  9. import javax.servlet.http.HttpServletRequest;  
  10.   
  11. import org.dom4j.Document;  
  12. import org.dom4j.Element;  
  13. import org.dom4j.io.SAXReader;  
  14. import org.liufeng.course.message.resp.Article;  
  15. import org.liufeng.course.message.resp.MusicMessage;  
  16. import org.liufeng.course.message.resp.NewsMessage;  
  17. import org.liufeng.course.message.resp.TextMessage;  
  18.   
  19. import com.thoughtworks.xstream.XStream;  
  20. import com.thoughtworks.xstream.core.util.QuickWriter;  
  21. import com.thoughtworks.xstream.io.HierarchicalStreamWriter;  
  22. import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;  
  23. import com.thoughtworks.xstream.io.xml.XppDriver;  
  24.   
  25. /** 
  26.  * 消息工具类 
  27.  *  
  28.  * @author liufeng 
  29.  * @date 2013-05-19 
  30.  */  
  31. public class MessageUtil {  
  32.   
  33.     /** 
  34.      * 返回消息类型:文本 
  35.      */  
  36.     public static final String RESP_MESSAGE_TYPE_TEXT = "text";  
  37.   
  38.     /** 
  39.      * 返回消息类型:音乐 
  40.      */  
  41.     public static final String RESP_MESSAGE_TYPE_MUSIC = "music";  
  42.   
  43.     /** 
  44.      * 返回消息类型:图文 
  45.      */  
  46.     public static final String RESP_MESSAGE_TYPE_NEWS = "news";  
  47.   
  48.     /** 
  49.      * 请求消息类型:文本 
  50.      */  
  51.     public static final String REQ_MESSAGE_TYPE_TEXT = "text";  
  52.   
  53.     /** 
  54.      * 请求消息类型:图片 
  55.      */  
  56.     public static final String REQ_MESSAGE_TYPE_IMAGE = "image";  
  57.   
  58.     /** 
  59.      * 请求消息类型:链接 
  60.      */  
  61.     public static final String REQ_MESSAGE_TYPE_LINK = "link";  
  62.   
  63.     /** 
  64.      * 请求消息类型:地理位置 
  65.      */  
  66.     public static final String REQ_MESSAGE_TYPE_LOCATION = "location";  
  67.   
  68.     /** 
  69.      * 请求消息类型:音频 
  70.      */  
  71.     public static final String REQ_MESSAGE_TYPE_VOICE = "voice";  
  72.   
  73.     /** 
  74.      * 请求消息类型:推送 
  75.      */  
  76.     public static final String REQ_MESSAGE_TYPE_EVENT = "event";  
  77.   
  78.     /** 
  79.      * 事件类型:subscribe(订阅) 
  80.      */  
  81.     public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";  
  82.   
  83.     /** 
  84.      * 事件类型:unsubscribe(取消订阅) 
  85.      */  
  86.     public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";  
  87.   
  88.     /** 
  89.      * 事件类型:CLICK(自己定义菜单点击事件) 
  90.      */  
  91.     public static final String EVENT_TYPE_CLICK = "CLICK";  
  92.   
  93.     /** 
  94.      * 解析微信发来的请求(XML) 
  95.      *  
  96.      * @param request 
  97.      * @return 
  98.      * @throws Exception 
  99.      */  
  100.     @SuppressWarnings("unchecked")  
  101.     public static Map<String, String> parseXml(HttpServletRequest request) throws Exception {  
  102.         // 将解析结果存储在HashMap中  
  103.         Map<String, String> map = new HashMap<String, String>();  
  104.   
  105.         // 从request中取得输入流  
  106.         InputStream inputStream = request.getInputStream();  
  107.         // 读取输入流  
  108.         SAXReader reader = new SAXReader();  
  109.         Document document = reader.read(inputStream);  
  110.         // 得到xml根元素  
  111.         Element root = document.getRootElement();  
  112.         // 得到根元素的全部子节点  
  113.         List<Element> elementList = root.elements();  
  114.   
  115.         // 遍历全部子节点  
  116.         for (Element e : elementList)  
  117.             map.put(e.getName(), e.getText());  
  118.   
  119.         // 释放资源  
  120.         inputStream.close();  
  121.         inputStream = null;  
  122.   
  123.         return map;  
  124.     }  
  125.   
  126.     /** 
  127.      * 文本消息对象转换成xml 
  128.      *  
  129.      * @param textMessage 文本消息对象 
  130.      * @return xml 
  131.      */  
  132.     public static String textMessageToXml(TextMessage textMessage) {  
  133.         xstream.alias("xml", textMessage.getClass());  
  134.         return xstream.toXML(textMessage);  
  135.     }  
  136.   
  137.     /** 
  138.      * 音乐消息对象转换成xml 
  139.      *  
  140.      * @param musicMessage 音乐消息对象 
  141.      * @return xml 
  142.      */  
  143.     public static String musicMessageToXml(MusicMessage musicMessage) {  
  144.         xstream.alias("xml", musicMessage.getClass());  
  145.         return xstream.toXML(musicMessage);  
  146.     }  
  147.   
  148.     /** 
  149.      * 图文消息对象转换成xml 
  150.      *  
  151.      * @param newsMessage 图文消息对象 
  152.      * @return xml 
  153.      */  
  154.     public static String newsMessageToXml(NewsMessage newsMessage) {  
  155.         xstream.alias("xml", newsMessage.getClass());  
  156.         xstream.alias("item"new Article().getClass());  
  157.         return xstream.toXML(newsMessage);  
  158.     }  
  159.   
  160.     /** 
  161.      * 扩展xstream,使其支持CDATA块 
  162.      *  
  163.      * @date 2013-05-19 
  164.      */  
  165.     private static XStream xstream = new XStream(new XppDriver() {  
  166.         public HierarchicalStreamWriter createWriter(Writer out) {  
  167.             return new PrettyPrintWriter(out) {  
  168.                 // 对全部xml节点的转换都添加CDATA标记  
  169.                 boolean cdata = true;  
  170.   
  171.                 @SuppressWarnings("unchecked")  
  172.                 public void startNode(String name, Class clazz) {  
  173.                     super.startNode(name, clazz);  
  174.                 }  
  175.   
  176.                 protected void writeText(QuickWriter writer, String text) {  
  177.                     if (cdata) {  
  178.                         writer.write("<![CDATA[");  
  179.                         writer.write(text);  
  180.                         writer.write("]]>");  
  181.                     } else {  
  182.                         writer.write(text);  
  183.                     }  
  184.                 }  
  185.             };  
  186.         }  
  187.     });  
  188. }  

OK,到这里关于消息及消息处理工具的封装就说到这里,事实上就是对请求消息/响应消息建立了与之相应的Java类、对xml消息进行解析、将响应消息的Java对象转换成xml。下一篇讲会介绍怎样利用上面封装好的工具识别用户发送的消息类型,并做出正确的响应。

本文转自博客园知识天地的博客,原文链接:[028] 微信公众帐号开发教程第4篇-消息及消息处理工具的封装(转),如需转载请自行联系原博主。


相关文章
|
14天前
|
小程序 前端开发 API
微信小程序全栈开发中的异常处理与日志记录
【4月更文挑战第12天】本文探讨了微信小程序全栈开发中的异常处理和日志记录,强调其对确保应用稳定性和用户体验的重要性。异常处理涵盖前端(网络、页面跳转、用户输入、逻辑异常)和后端(数据库、API、业务逻辑)方面;日志记录则关注关键操作和异常情况的追踪。实践中,前端可利用try-catch处理异常,后端借助日志框架记录异常,同时采用集中式日志管理工具提升分析效率。开发者应注意安全性、性能和团队协作,以优化异常处理与日志记录流程。
|
14天前
|
小程序 安全 数据安全/隐私保护
微信小程序全栈开发中的身份认证与授权机制
【4月更文挑战第12天】本文探讨了微信小程序全栈开发中的身份认证与授权机制。身份认证包括手机号验证、微信登录和第三方登录,而授权机制涉及角色权限控制、ACL和OAuth 2.0。实践中,开发者可利用微信登录获取用户信息,集成第三方登录,以及实施角色和ACL进行权限控制。注意点包括安全性、用户体验和合规性,以保障小程序的安全运行和良好体验。通过这些方法,开发者能有效掌握小程序全栈开发技术。
|
14天前
|
JavaScript 前端开发 小程序
微信小程序全栈开发之性能优化策略
【4月更文挑战第12天】本文探讨了微信小程序全栈开发的性能优化策略,包括前端的资源和渲染优化,如图片压缩、虚拟DOM、代码分割;后端的数据库和API优化,如索引创建、缓存使用、RESTful API设计;以及服务器的负载均衡和CDN加速。通过这些方法,开发者可提升小程序性能,优化用户体验,增强商业价值。
|
1月前
|
Docker 容器
Star 1.8k! 推荐一款更优雅的微信文章订阅工具,让阅读更便捷!
Star 1.8k! 推荐一款更优雅的微信文章订阅工具,让阅读更便捷!
|
14天前
|
小程序 前端开发 JavaScript
微信小程序全栈开发中的PWA技术应用
【4月更文挑战第12天】本文探讨了微信小程序全栈开发中PWA技术的应用,PWA结合Web的开放性和原生应用的性能,提供离线访问、后台运行、桌面图标和原生体验。开发者可利用Service Worker实现离线访问,Worker处理后台运行,Web App Manifest添加桌面图标,CSS和JavaScript提升原生体验。实践中需注意兼容性、性能优化和用户体验。PWA技术能提升小程序的性能和用户体验,助力开发者打造优质小程序。
|
2天前
|
数据采集 存储 人工智能
【Python+微信】【企业微信开发入坑指北】4. 企业微信接入GPT,只需一个URL,自动获取文章总结
【Python+微信】【企业微信开发入坑指北】4. 企业微信接入GPT,只需一个URL,自动获取文章总结
13 0
|
2天前
|
人工智能 机器人 API
【Python+微信】【企业微信开发入坑指北】3. 如何利用企业微信API给微信群推送消息
【Python+微信】【企业微信开发入坑指北】3. 如何利用企业微信API给微信群推送消息
6 0
|
2天前
|
缓存 人工智能 API
【Python+微信】【企业微信开发入坑指北】2. 如何利用企业微信API主动给用户发应用消息
【Python+微信】【企业微信开发入坑指北】2. 如何利用企业微信API主动给用户发应用消息
6 0
|
14天前
|
SQL 安全 小程序
探索微信小程序全栈开发的安全性问题
【4月更文挑战第12天】本文探讨了微信小程序全栈开发中的安全性问题,包括数据安全、接口安全、隐私保护和代码安全。为解决这些问题,建议采取数据加密、使用HTTPS协议、身份认证与授权、输入验证、安全审计及漏洞扫描以及安全培训等措施。通过这些方法,开发者可提升小程序安全性,保护用户隐私和数据。
|
1月前
|
安全 小程序 Java
java实现微信服务(公众)号用户关注时,获取openid,安全模式下的加密解密实现
java实现微信服务(公众)号用户关注时,获取openid,安全模式下的加密解密实现
19 0

热门文章

最新文章