Java开发微信公众号(四)---微信服务器post消息体的接收及消息的处理

      在前几节文章中我们讲述了微信公众号环境的搭建如何接入微信公众平台、以及微信服务器请求消息,响应消息,事件消息以及工具处理类的封装;接下来我们重点说一下-微信服务器post消息体的接收及消息的处理,这个post方法定义在如何接入微信公众平台的【controller】中。

/**
     * 接收微信消息处理并做分发
     * @param request
     * @param response
     * @throws Exception
     */
    @RequestMapping(method=RequestMethod.POST)
    public void post(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // TODO 消息的接收、处理、响应

    }

post方法有两个参数:

   1.request中封装了请求相关的所有内容,可以从request中取出微信服务器发来的消息;

   2.response我们可以对接收到的消息进行响应,即发送消息。

 因为微信服务器发送过来的是xml格式的消息,所以我们可以采用 开源框架dom4j去解析xml 。在pom.xml文件中加:

<dependency>
    <groupId>org.apache.directory.studio</groupId>
    <artifactId>org.dom4j.dom4j</artifactId>
    <version>1.6.1</version>
</dependency>

处理xml格式消息的方法 前面也提到过的工具类MessageType中:

 1 /**
 2      * @Title parseXml
 3      * @Description 将用户的xml消息提取成map key value 类型
 4      * @param request
 5      * @param response
 6      * @return
 7      * @throws Exception
 8      */
 9     public static Map<String, String> parseXml(HttpServletRequest request, HttpServletResponse response)
10             throws Exception {
11         // 将解析结果存储在HashMap中
12         Map<String, String> map = new HashMap<String, String>();
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         for (Element e : elementList) {
24             map.put(e.getName(), e.getText());
25         }
26         // 释放资源
27         inputStream.close();
28         inputStream = null;
29         return map;
30     }
View Code

 将响应消息转换成xml格式返回给微信服务器,我是直接把各种消息类型封装成xml文件,你们也可以利用xstream-1.3.1.jar 或 xmlpull-1.1.3.1.jar来实现Java类到xml的转换

构建回复消息ReplyMessageUtil类

  1 package com.webchat.util.weixin;
  2 
  3 import java.io.Serializable;
  4 
  5 import com.webchat.entity.output.Articles;
  6 import com.webchat.entity.output.ImageOutputMessage;
  7 import com.webchat.entity.output.MusicOutputMessage;
  8 import com.webchat.entity.output.NewsOutputMessage;
  9 import com.webchat.entity.output.TextMessage;
 10 import com.webchat.entity.output.VideoOutPutMessage;
 11 import com.webchat.entity.output.VoiceOutputMessage;
 12 
 13 /**
 14  * 构建回复消息
 15  * 
 16  * @author Administrator
 17  *
 18  */
 19 public class ReplyMessageUtil implements Serializable {
 20     private static final long serialVersionUID = 1L;
 21     /**
 22      * <xml> <ToUserName><![CDATA[toUser]]></ToUserName>
 23      * <FromUserName><![CDATA[fromUser]]></FromUserName>
 24      * <CreateTime>12345678</CreateTime> <MsgType><![CDATA[news]]></MsgType>
 25      * <ArticleCount>2</ArticleCount> <Articles> <item>
 26      * <Title><![CDATA[title1]]></Title>
 27      * <Description><![CDATA[description1]]></Description>
 28      * <PicUrl><![CDATA[picurl]]></PicUrl> <Url><![CDATA[url]]></Url> </item>
 29      * <item> <Title><![CDATA[title]]></Title>
 30      * <Description><![CDATA[description]]></Description>
 31      * <PicUrl><![CDATA[picurl]]></PicUrl> <Url><![CDATA[url]]></Url> </item>
 32      * </Articles> </xml>
 33      * 
 34      * @Title sendImageTextMessage
 35      * @Description 回复图文消息
 36      * @param message
 37      * @return
 38      */
 39     public static String sendImageTextMessage(NewsOutputMessage message) {
 40         StringBuffer sb = new StringBuffer();
 41         sb.append("<xml>");
 42         sb.append("<ToUserName><![CDATA[" + message.getToUserName() + "]]></ToUserName>");
 43         sb.append("<FromUserName><![CDATA[" + message.getFromUserName() + "]]></FromUserName>");
 44         sb.append("<CreateTime>" + message.getCreateTime() + "</CreateTime>");
 45         sb.append("<MsgType><![CDATA[" + MessageType.IMAGE_TEXT_MESSAGE + "]]></MsgType>");
 46         sb.append("<ArticleCount>" + message.getArticleCount() + "</ArticleCount>");
 47         sb.append("<Articles> ");
 48         for (Articles article : message.getArticles()) {
 49             sb.append("<item>");
 50             if(article.getTitle()!=null && article.getTitle()!=""){
 51                 sb.append("<Title><![CDATA[").append(article.getTitle()).append("]]></Title>");
 52             }
 53             if(article.getDescription()!=null && article.getDescription()!=""){
 54                 sb.append("<Description><![CDATA[").append(article.getDescription()).append("]]></Description>");
 55             }
 56             if(article.getPicUrl()!=null && article.getPicUrl()!=""){
 57                 sb.append("<PicUrl><![CDATA[").append(article.getPicUrl()).append("]]></PicUrl>");
 58             }
 59             if(article.getUrl()!=null && article.getUrl()!=""){
 60                 sb.append("<Url><![CDATA[").append(article.getUrl()).append("]]></Url>");
 61             }
 62             sb.append("</item>");
 63         }
 64         sb.append("</Articles>");
 65         sb.append("</xml>");
 66         return sb.toString();
 67     }
 68 
 69     /**
 70      * <xml> <ToUserName><![CDATA[toUser]]></ToUserName>
 71      * <FromUserName><![CDATA[fromUser]]></FromUserName>
 72      * <CreateTime>12345678</CreateTime> <MsgType><![CDATA[music]]></MsgType>
 73      * <Music> <Title><![CDATA[TITLE]]></Title>
 74      * <Description><![CDATA[DESCRIPTION]]></Description>
 75      * <MusicUrl><![CDATA[MUSIC_Url]]></MusicUrl>
 76      * <HQMusicUrl><![CDATA[HQ_MUSIC_Url]]></HQMusicUrl>
 77      * <ThumbMediaId><![CDATA[media_id]]></ThumbMediaId> </Music> </xml>
 78      * 
 79      * @Title sendMusicMessage
 80      * @Description 回复音乐消息
 81      * @param message
 82      * @return
 83      */
 84     public static String sendMusicMessage(MusicOutputMessage message) {
 85         StringBuffer sb = new StringBuffer();
 86         sb.append("<xml>");
 87         sb.append("<ToUserName><![CDATA[" + message.getToUserName() + "]]></ToUserName>");
 88         sb.append("<FromUserName><![CDATA[" + message.getFromUserName() + "]]></FromUserName>");
 89         sb.append("<CreateTime>" + message.getCreateTime() + "</CreateTime>");
 90         sb.append("<MsgType><![CDATA[" + MessageType.MUSIC_MESSAGE + "]]></MsgType>");
 91         sb.append("<Music>");
 92         if (message.getMusic().getTitle() != null && !"".equals(message.getMusic().getTitle())) {
 93             sb.append("<Title><![CDATA[" + message.getMusic().getTitle() + "]]></Title>");
 94         }
 95         if (message.getMusic().getDescription() != null && !"".equals(message.getMusic().getDescription())) {
 96             sb.append("<Description><![CDATA[" + message.getMusic().getDescription() + "]]></Description>");
 97         }
 98         if (message.getMusic().getMusicUrl() != null && !"".equals(message.getMusic().getMusicUrl())) {
 99             sb.append("<MusicUrl><![CDATA[" + message.getMusic().getMusicUrl() + "]]></MusicUrl>");
100         }
101         if (message.getMusic().getHQMusicUrl() != null && !"".equals(message.getMusic().getHQMusicUrl())) {
102             sb.append("<HQMusicUrl><![CDATA[" + message.getMusic().getHQMusicUrl() + "]]></HQMusicUrl>");
103         }
104 
105         sb.append("<ThumbMediaId><![CDATA[" + message.getMusic().getThumbMediaId() + "]]></ThumbMediaId>");
106         sb.append("</Music>");
107         sb.append("</xml>");
108         return sb.toString();
109     }
110 
111     /**
112      * <xml> <ToUserName><![CDATA[toUser]]></ToUserName>
113      * <FromUserName><![CDATA[fromUser]]></FromUserName>
114      * <CreateTime>12345678</CreateTime> <MsgType><![CDATA[video]]></MsgType>
115      * <Video> <MediaId><![CDATA[media_id]]></MediaId>
116      * <Title><![CDATA[title]]></Title>
117      * <Description><![CDATA[description]]></Description> </Video> </xml>
118      * 
119      * @Title sendVideoMessage
120      * @Description 回复视频消息
121      * @param message
122      * @return
123      */
124     public static String sendVideoMessage(VideoOutPutMessage message) {
125         StringBuffer sb = new StringBuffer();
126         sb.append("<xml>");
127         sb.append("<ToUserName><![CDATA[" + message.getToUserName() + "]]></ToUserName>");
128         sb.append("<FromUserName><![CDATA[" + message.getFromUserName() + "]]></FromUserName>");
129         sb.append("<CreateTime>" + message.getCreateTime() + "</CreateTime>");
130         sb.append("<MsgType><![CDATA[" + MessageType.VIDEO_MESSAGE + "]]></MsgType>");
131         sb.append("<Video>");
132         sb.append("<MediaId><![CDATA[" + message.getVideo().getMediaId() + "]]></MediaId>");
133         if (message.getVideo().getTitle() != null && !"".equals(message.getVideo().getTitle())) {
134             sb.append("<Title><![CDATA[" + message.getVideo().getTitle() + "]]></Title>");
135         }
136         if (message.getVideo().getDescription() != null && !"".equals(message.getVideo().getDescription())) {
137             sb.append("<Description><![CDATA[" + message.getVideo().getDescription() + "]]></Description>");
138         }
139         sb.append("</Video>");
140         sb.append("</xml>");
141         return sb.toString();
142     }
143 
144     /**
145      * <xml> <ToUserName><![CDATA[toUser]]></ToUserName>
146      * <FromUserName><![CDATA[fromUser]]></FromUserName>
147      * <CreateTime>12345678</CreateTime> <MsgType><![CDATA[voice]]></MsgType>
148      * <Voice> <MediaId><![CDATA[media_id]]></MediaId> </Voice> </xml>
149      * @Title sendVoiceMessage
150      * @Description 回复语音消息
151      * @param message
152      * @return
153      */
154     public static String sendVoiceMessage(VoiceOutputMessage message) {
155         StringBuffer sb = new StringBuffer();
156         sb.append("<xml>");
157         sb.append("<ToUserName><![CDATA[" + message.getToUserName() + "]]></ToUserName>");
158         sb.append("<FromUserName><![CDATA[" + message.getFromUserName() + "]]></FromUserName>");
159         sb.append("<CreateTime>" + message.getCreateTime() + "</CreateTime>");
160         sb.append("<MsgType><![CDATA[" + MessageType.VOICE_MESSAGE + "]]></MsgType>");
161         sb.append("<Voice>");
162         sb.append("<MediaId><![CDATA[" + message.getVoice().getMediaId() + "]]></MediaId>");
163         sb.append("</Voice>");
164         sb.append("</xml>");
165         return sb.toString();
166     }
167 
168     /**
169      * <xml> <ToUserName><![CDATA[toUser]]></ToUserName>
170      * <FromUserName><![CDATA[fromUser]]></FromUserName>
171      * <CreateTime>12345678</CreateTime> <MsgType><![CDATA[image]]></MsgType>
172      * <Image> <MediaId><![CDATA[media_id]]></MediaId> </Image> </xml>
173      * @Title sendImageMessage
174      * @Description 回复图片消息
175      * @param message
176      */
177     public static String sendImageMessage(ImageOutputMessage message) {
178         StringBuffer sb = new StringBuffer();
179         sb.append("<xml>");
180         sb.append("<ToUserName><![CDATA[" + message.getToUserName() + "]]></ToUserName>");
181         sb.append("<FromUserName><![CDATA[" + message.getFromUserName() + "]]></FromUserName>");
182         sb.append("<CreateTime>" + message.getCreateTime() + "</CreateTime>");
183         sb.append("<MsgType><![CDATA[" + MessageType.IMAGE_MESSAGE + "]]></MsgType>");
184         sb.append("<Image>");
185         sb.append("<MediaId><![CDATA[" + message.getImage().getMediaId() + "]]></MediaId>");
186         sb.append("</Image>");
187         sb.append("</xml>");
188         return sb.toString();
189     }
190     /**
191      * <xml> <ToUserName>< ![CDATA[toUser] ]></ToUserName> <FromUserName><
192      * ![CDATA[fromUser] ]></FromUserName> <CreateTime>12345678</CreateTime>
193      * <MsgType>< ![CDATA[text] ]></MsgType> <Content>< ![CDATA[你好] ]></Content>
194      * </xml> sendTextMessage
195      * @param message
196      * @return
197      */
198     public static String sendTextMessage(TextMessage message) {
199         StringBuffer sb = new StringBuffer();
200         sb.append("<xml>");
201         sb.append("<ToUserName><![CDATA[" + message.getToUserName() + "]]></ToUserName>");
202         sb.append("<FromUserName><![CDATA[" + message.getFromUserName() + "]]></FromUserName>");
203         sb.append("<CreateTime>" + message.getCreateTime() + "</CreateTime>");
204         sb.append("<MsgType><![CDATA[" + MessageType.TEXT_MESSAGE + "]]></MsgType>");
205         sb.append("<Content><![CDATA[" + message.getContent() + "]]></Content>");
206         sb.append("</xml>");
207         return sb.toString();
208     }
209 }
View Code

 我们在接收微信发送的消息时,需要根据消息的不同类别来进行处理,这是我们就需要一个工具类来处理事件类型的消息和普通消息类型的工具类:WebChatService

  1 package com.webchat.service;
  2 
  3 import java.util.ArrayList;
  4 import java.util.Date;
  5 import java.util.HashMap;
  6 import java.util.List;
  7 import java.util.Map;
  8 
  9 import com.webchat.entity.output.Articles;
 10 import com.webchat.entity.output.NewsOutputMessage;
 11 import com.webchat.entity.output.TextMessage;
 12 import com.webchat.util.weixin.MessageType;
 13 import com.webchat.util.weixin.ReplyMessageUtil;
 14 import com.webchat.util.weixin.utils.XmlUtil;
 15 
 16 /**
 17  * 处理接收信息和回复消息的服务类接口
 18  * 
 19  * @author Administrator
 20  *
 21  */
 22 public class WebChatService {
 23     // 处理微信发来的请求 map 消息业务处理分发
 24     public static String parseMessage(Map<String, String> map) {
 25         String respXml = null;
 26         try {
 27             // 发送方帐号
 28             String fromUserName = map.get("FromUserName");
 29             // 开发者微信号
 30             String toUserName = map.get("ToUserName");
 31             // 取得消息类型
 32             String MsgType = map.get("MsgType");
 33             // 发现直接把要返回的信息直接封装成replyMap集合,然后转换成 xml文件,是不是实体类可以不用了
 34             Map<String, String> replyMap = new HashMap<String, String>();
 35             replyMap.put("ToUserName", fromUserName);
 36             replyMap.put("FromUserName", toUserName);
 37             replyMap.put("CreateTime", String.valueOf(new Date().getTime()));
 38             if (MsgType.equals(MessageType.TEXT_MESSAGE)) {
 39                 // 封装文本返回消息
 40                 TextMessage textMessage = new TextMessage();
 41                 textMessage.setToUserName(fromUserName);
 42                 textMessage.setFromUserName(toUserName);
 43                 textMessage.setCreateTime(new Date().getTime());
 44                 textMessage.setContent("您发送的是文本消息");
 45                 textMessage.getMsgType();
 46                 // respXml = ReplyMessageUtil.sendTextMessage(textMessage);
 47 
 48                 // 用map集合封装
 49                 replyMap.put("MsgType", MessageType.RESP_MESSAGE_TYPE_TEXT);
 50                 replyMap.put("Content", "您发送的是文本消息");
 51                 respXml = XmlUtil.xmlFormat(replyMap, true);
 52             } else if (MsgType.equals(MessageType.IMAGE_MESSAGE)) {
 53                 // 这里回复图片 或者图文消息 以图文消息为例
 54                 NewsOutputMessage message = new NewsOutputMessage();
 55                 message.setToUserName(fromUserName);
 56                 message.setFromUserName(toUserName);
 57                 message.setCreateTime(new Date().getTime());
 58                 message.getMsgType();
 59 
 60                 Articles article = new Articles();
 61                 article.setDescription("图文消息 "); // 图文消息的描述
 62                 article.setPicUrl("https://p4.ssl.cdn.btime.com/dmfd/192_108_/t019d0b65e33000f8a0.jpg?size=458x240"); // 图文消息图片地址
 63                 article.setTitle("图文消息 "); // 图文消息标题
 64                 article.setUrl("http://www.baidu.com"); // 图文 url 链接
 65                 List<Articles> list = new ArrayList<Articles>();
 66                 list.add(article);// 这里发送的是单图文,如果需要发送多图文则在这里 list 中加入多个
 67                                     // Articles!
 68 
 69                 message.setArticleCount(list.size());
 70                 message.setArticles(list);
 71                 respXml = ReplyMessageUtil.sendImageTextMessage(message);
 72             } else if (MsgType.equals(MessageType.VOICE_MESSAGE)) {
 73                 // 以下方式根据需要来操作
 74                 replyMap.put("MsgType", MessageType.RESP_MESSAGE_TYPE_TEXT);
 75                 replyMap.put("Content", "您发送的是语音消息");
 76                 respXml = XmlUtil.xmlFormat(replyMap, true);
 77             } else if (MsgType.equals(MessageType.VIDEO_MESSAGE)) {
 78                 replyMap.put("MsgType", MessageType.RESP_MESSAGE_TYPE_TEXT);
 79                 replyMap.put("Content", "您发送的是视频消息");
 80                 respXml = XmlUtil.xmlFormat(replyMap, true);
 81             } else if (MsgType.equals(MessageType.SHORTVIDEO_MESSAGE)) {
 82                 replyMap.put("MsgType", MessageType.RESP_MESSAGE_TYPE_TEXT);
 83                 replyMap.put("Content", "您发送的是小视频消息");
 84                 respXml = XmlUtil.xmlFormat(replyMap, true);
 85             } else if (MsgType.equals(MessageType.POSOTION_MESSAGE)) {
 86                 replyMap.put("MsgType", MessageType.RESP_MESSAGE_TYPE_TEXT);
 87                 replyMap.put("Content", "您发送的是地理位置消息");
 88                 respXml = XmlUtil.xmlFormat(replyMap, true);
 89             } else if (MsgType.equals(MessageType.LINK_MESSAGE)) {
 90                 replyMap.put("MsgType", MessageType.RESP_MESSAGE_TYPE_TEXT);
 91                 replyMap.put("Content", "您发送的是链接消息");
 92                 respXml = XmlUtil.xmlFormat(replyMap, true);
 93             }
 94         } catch (Exception e) {
 95             e.printStackTrace();
 96         }
 97         return respXml;
 98     }
 99 
100     // 事件消息业务分发
101     public static String parseEvent(Map<String, String> map) {
102         String respXml = null;
103         try {
104             // 发送方帐号
105             String fromUserName = map.get("FromUserName");
106             // 开发者微信号
107             String toUserName = map.get("ToUserName");
108             // 取得消息类型
109             String MsgType = map.get("MsgType");
110             //获取事件类型
111             String eventType = map.get("Event");
112             
113             // 发现直接把要返回的信息直接封装成replyMap集合,然后转换成 xml文件,是不是实体类可以不用了
114             Map<String, String> replyMap = new HashMap<String, String>();
115             replyMap.put("ToUserName", fromUserName);
116             replyMap.put("FromUserName", toUserName);
117             replyMap.put("CreateTime", String.valueOf(new Date().getTime()));
118             if (eventType.equals(MessageType.EVENT_TYPE_SUBSCRIBE)) {// 关注
119                 // 用map集合封装
120                 replyMap.put("MsgType", MessageType.RESP_MESSAGE_TYPE_TEXT);
121                 replyMap.put("Content", MessageType.menuText());
122                 respXml = XmlUtil.xmlFormat(replyMap, true);
123             }
124             if (eventType.equals(MessageType.EVENT_TYPE_UNSUBSCRIBE)) {// 取消关注
125 
126             }
127             if (eventType.equals(MessageType.EVENT_TYPE_SCAN)) {// 用户已关注时的扫描带参数二维码
128 
129             }
130             if (eventType.equals(MessageType.EVENT_TYPE_LOCATION)) {// 上报地理位置
131 
132             }
133             if (eventType.equals(MessageType.EVENT_TYPE_CLICK)) {// 自定义菜单
134 
135             }
136         } catch (Exception e) {
137             e.printStackTrace();
138         }
139         return respXml;
140     }
141 }
View Code

 通过查看WebChatService工具类,你会发现我里面既有通过回复消息实体类 获取回复信息然后调用ReplyMessageUtil类中对应的方法来返回信息,还有通过集合Map(replyMap)key,value的方法来添加数据,然后调用XmlUtil.java 的xmlFormat()方法返回消息的,有兴趣的可以都研究下:现在提供需要的工具类和jar文件

在pom.xml文件加入xmlpull-1.1.3.1.jar

<dependency>
            <groupId>xmlpull</groupId>
            <artifactId>xmlpull</artifactId>
            <version>1.1.3.1</version>
</dependency>

XmlUtil工具类:

 1 package com.webchat.util.weixin.utils;
 2 
 3 import java.io.ByteArrayInputStream;
 4 import java.io.IOException;
 5 import java.io.InputStream;
 6 import java.util.HashMap;
 7 import java.util.Map;
 8 import java.util.Map.Entry;
 9 
10 import org.xmlpull.v1.XmlPullParser;
11 import org.xmlpull.v1.XmlPullParserException;
12 import org.xmlpull.v1.XmlPullParserFactory;  
13 /**
14  * 封装和处理xml文件
15  * @author Administrator
16  *
17  */
18 public class XmlUtil {
19 
20     private static final String PREFIX_XML = "<xml>";
21 
22     private static final String SUFFIX_XML = "</xml>";
23 
24     private static final String PREFIX_CDATA = "<![CDATA[";
25 
26     private static final String SUFFIX_CDATA = "]]>";
27 
28     /**
29      * 转化成xml, 单层无嵌套
30      * 
31      * @param map
32      * @param isAddCDATA  ture 加CDATA标签  false 不加CDATA标签
33      * @return
34      */
35     public static String xmlFormat(Map<String, String> parm, boolean isAddCDATA) {
36 
37         StringBuffer strbuff = new StringBuffer(PREFIX_XML);
38         if (CollectionUtil.isNotEmpty(parm)) {
39             for (Entry<String, String> entry : parm.entrySet()) {
40                 strbuff.append("<").append(entry.getKey()).append(">");
41                 if (isAddCDATA) {
42                     strbuff.append(PREFIX_CDATA);
43                     if (StringUtil.isNotEmpty(entry.getValue())) {
44                         strbuff.append(entry.getValue());
45                     }
46                     strbuff.append(SUFFIX_CDATA);
47                 } else {
48                     if (StringUtil.isNotEmpty(entry.getValue())) {
49                         strbuff.append(entry.getValue());
50                     }
51                 }
52                 strbuff.append("</").append(entry.getKey()).append(">");
53             }
54         }
55         return strbuff.append(SUFFIX_XML).toString();
56     }
57 
58     /**
59      * 解析xml
60      * 
61      * @param xml
62      * @return
63      * @throws XmlPullParserException
64      * @throws IOException
65      */
66     public static Map<String, String> xmlParse(String xml) throws XmlPullParserException, IOException {
67         Map<String, String> map = null;
68         if (StringUtil.isNotEmpty(xml)) {
69             InputStream inputStream = new ByteArrayInputStream(xml.getBytes());
70             XmlPullParser pullParser = XmlPullParserFactory.newInstance().newPullParser();
71             pullParser.setInput(inputStream, "UTF-8"); // 为xml设置要解析的xml数据
72             int eventType = pullParser.getEventType();
73 
74             while (eventType != XmlPullParser.END_DOCUMENT) {
75                 switch (eventType) {
76                 case XmlPullParser.START_DOCUMENT:
77                     map = new HashMap<String, String>();
78                     break;
79                 case XmlPullParser.START_TAG:
80                     String key = pullParser.getName();
81                     if (key.equals("xml"))
82                         break;
83                     String value = pullParser.nextText().trim();
84                     map.put(key, value);
85                     break;
86                 case XmlPullParser.END_TAG:
87                     break;
88                 }
89                 eventType = pullParser.next();
90             }
91         }
92         return map;
93     }
94 }
View Code

XmlUtil 工具类关联的类CollectionUtil 和StringUtil

  1 package com.webchat.util.weixin.utils;
  2 
  3 import java.util.HashSet;
  4 import java.util.Set;
  5 import java.util.UUID;
  6 import java.util.regex.Matcher;
  7 import java.util.regex.Pattern;
  8 
  9 /**
 10  * String工具类
 11  */
 12 public class StringUtil {
 13 
 14     private StringUtil() {
 15         super();
 16     }
 17 
 18     /**
 19      * 出去null和""
 20      * @param src
 21      * @return
 22      */
 23     public static String formatNull(String src) {
 24         return (src == null || "null".equals(src)) ? "" : src;
 25     }
 26 
 27     /**
 28      * 判断字符串是否为空的正则表达式,空白字符对应的unicode编码
 29      */
 30     private static final String EMPTY_REGEX = "[\\s\\u00a0\\u2007\\u202f\\u0009-\\u000d\\u001c-\\u001f]+";
 31 
 32     /**
 33      * 验证字符串是否为空
 34      * 
 35      * @param input
 36      * @return
 37      */
 38     public static boolean isEmpty(String input) {
 39         return input == null || input.equals("") || input.matches(EMPTY_REGEX);
 40     }
 41     
 42     public static boolean isNotEmpty(String input){
 43         return !isEmpty(input);
 44     }
 45 
 46     private static final String NUM_REG = "(\\+|\\-)?\\s*\\d+(\\.\\d+)?";
 47 
 48     /**
 49      * 判断是否数字
 50      * 
 51      * @param str
 52      * @return
 53      */
 54     public static boolean isNumber(String str) {
 55         if (isEmpty(str)) {
 56             return false;
 57         }
 58 
 59         if (str.trim().matches(NUM_REG)) {
 60             return true;
 61         }
 62 
 63         return false;
 64     }
 65 
 66     /**
 67      * 判断是否包含有乱码的数据,如果字符串中包含有替换字符就认为是乱码
 68      * 
 69      * @param str
 70      * @return
 71      */
 72     public static boolean containUnreadableCode(String str) {
 73         return contain(str, "\\ufffd");
 74     }
 75 
 76     /**
 77      * 判读是否包含数字
 78      * 
 79      * @param str
 80      * @return
 81      */
 82     public static boolean containNumber(String str) {
 83         return contain(str, "\\d");
 84     }
 85 
 86     /**
 87      * 判断是否包含a-zA-Z_0-9
 88      * 
 89      * @param str
 90      * @return
 91      */
 92     public static boolean containWord(String str) {
 93         return contain(str, "\\w");
 94     }
 95 
 96     /**
 97      * 是否包含有标点符号
 98      * 
 99      * @param str
100      * @return
101      */
102     public static boolean containPunct(String str) {
103         return contain(str, PUNCT_REG);
104     }
105 
106     public static boolean contain(String str, String regex) {
107         if (isEmpty(str) || isEmpty(regex)) {
108             return false;
109         }
110 
111         if (str.trim().matches(regex)) {
112             return true;
113         }
114 
115         Pattern pattern = Pattern.compile(regex);
116         Matcher matcher = pattern.matcher(str);
117         if (matcher.find()) {
118             return true;
119         }
120 
121         return false;
122     }
123 
124     /**
125      * 替换所有的(不区分大小写)
126      * 
127      * @param input
128      * @param regex
129      * @param replacement
130      * @return
131      */
132     public static String replaceAll(String input, String regex,
133             String replacement) {
134         return Pattern.compile(regex, Pattern.CASE_INSENSITIVE).matcher(input)
135                 .replaceAll(replacement);
136     }
137 
138     /**
139      * 移除所有的空格
140      * 
141      * @param text
142      * @return
143      */
144     public static String removeAllSpace(String text) {
145         if (isEmpty(text)) {
146             return text;
147         }
148 
149         return text.replaceAll("[ ]+", "");
150     }
151 
152     private static final String PUNCT_REG = "[^a-zA-Z0-9\\u4e00-\\u9fa5]";
153 
154     /**
155      * 移除字符串中的所有的中英文标点符号
156      * 
157      * @param str
158      * @return
159      */
160     public static String removeAllPunct(String str) {
161         if (isEmpty(str)) {
162             return str;
163         }
164 
165         return str.replaceAll(PUNCT_REG, "");
166     }
167 
168     /**
169      * 计算str中包含多少个子字符串sub
170      * 
171      * @param str
172      * @param sub
173      * @return
174      */
175     public static int countMatches(String str, String sub) {
176         if (isEmpty(str) || isEmpty(sub)) {
177             return 0;
178         }
179 
180         int count = 0;
181         int idx = 0;
182         while ((idx = str.indexOf(sub, idx)) != -1) {
183             count++;
184             idx += sub.length();
185         }
186 
187         return count;
188     }
189 
190     /**
191      * 获得源字符串的一个子字符串
192      * 
193      * @param str
194      *            :源字符串
195      * @param beginIndex
196      *            :开始索引(包括)
197      * @param endIndex
198      *            :结束索引(不包括)
199      * @return
200      */
201     public static String substring(String str, int beginIndex, int endIndex) {
202         if (isEmpty(str)) {
203             return str;
204         }
205 
206         int length = str.length();
207 
208         if (beginIndex >= length || endIndex <= 0 || beginIndex >= endIndex) {
209             return null;
210         }
211 
212         if (beginIndex < 0) {
213             beginIndex = 0;
214         }
215         if (endIndex > length) {
216             endIndex = length;
217         }
218 
219         return str.substring(beginIndex, endIndex);
220     }
221 
222     /**
223      * 计算str中包含子字符串sub所在位置的前一个字符或者后一个字符和sub所组成的新字符串
224      * 
225      * @param str
226      * @param sub
227      * @return
228      */
229     public static Set<String> substring(String str, String sub) {
230         if (isEmpty(str) || isEmpty(sub)) {
231             return null;
232         }
233 
234         Set<String> result = new HashSet<String>();
235         int idx = 0;
236         while ((idx = str.indexOf(sub, idx)) != -1) {
237             String temp = substring(str, idx - 1, idx + sub.length());
238             if (!isEmpty(temp)) {
239                 temp = removeAllPunct(temp);
240                 if (!sub.equalsIgnoreCase(temp) && !containWord(temp)) {
241                     result.add(temp);
242                 }
243 
244             }
245 
246             temp = substring(str, idx, idx + sub.length() + 1);
247             if (!isEmpty(temp)) {
248                 temp = removeAllPunct(temp);
249                 if (!sub.equalsIgnoreCase(temp) && !containWord(temp)) {
250                     result.add(temp);
251                 }
252             }
253 
254             idx += sub.length();
255         }
256 
257         return result;
258     }
259 
260     /**
261      * 过滤掉XML中无法解析的非法字符
262      * 
263      * @param content
264      * @return
265      */
266     public static String wrapXmlContent(String content) {
267         if (isEmpty(content)) {
268             return "";
269         }
270 
271         StringBuilder result = new StringBuilder();
272 
273         for (int i = 0; i < content.length(); i++) {
274             char ch = content.charAt(i);
275             if ((ch == '\t') || (ch == '\n') || (ch == '\r')
276                     || ((ch >= ' ') && (ch <= 55295))
277                     || ((ch >= 57344) && (ch <= 65533))
278                     || ((ch >= 65536) && (ch <= 1114111))) {
279                 result.append(ch);
280             }
281         }
282 
283         return result.toString();
284     }
285 
286     /**
287      * 判断字符串的长度
288      * 
289      * @param str
290      * @return
291      */
292     public static boolean overLength(String str) {
293         if (isEmpty(str)) {
294             return false;
295         }
296 
297         return str.length() > 1 ? true : false;
298     }
299 
300     /**
301      * 字符串中含有特殊字符的处理
302      * 
303      * @param str
304      * @return
305      */
306     public static String specialStr(String str) {
307         str = str.replaceAll("[^\\u4e00-\\u9fa5 | 0-9| a-zA-Z | \\.]+", " ")
308                 .replaceAll("[\\.]{2,}", " ").trim();
309         return str;
310     }
311 
312     /**
313      * 将特殊符号去掉,但是保留空格
314      * 
315      * @param str
316      * @return
317      */
318     public static String replaceInValidateChar(String str) {
319         return str.replaceAll("[^a-zA-Z0-9\\u4e00-\\u9fa5\\s+]", " ");
320     }
321 
322     /**
323      * 返回字符串对应的unicode编码
324      * 
325      * @param str
326      * @return
327      */
328     public static String[] toHexString(String str) {
329         char[] chars = str.toCharArray();
330 
331         String[] result = new String[chars.length];
332 
333         for (int i = 0; i < chars.length; i++) {
334             result[i] = Integer.toHexString((int) chars[i]);
335         }
336 
337         return result;
338     }
339 
340     public static String getUuid() {
341         return UUID.randomUUID().toString();
342     }
343     
344     public static boolean isUrl(String src) {
345         String regex = "http[s]?:\\/\\/([\\w-]+\\.[\\w-]+)(\\.[\\w-])+(:\\d{2,10})?.*";
346         Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
347         Matcher matcher = pattern.matcher(src);
348         return matcher.matches();
349     }
350     
351     /**
352      * sql 查询转义
353      * @param str
354      * @return
355      */
356     public static String escapeSql(String str){
357         if (StringUtil.isNotEmpty(str)) {
358             StringBuffer strbuff = new StringBuffer();
359             for (String s : str.split("")) {
360                 if (s.equals("%") || s.equals("_") || s.equals("\\")) {
361                     strbuff.append("\\");
362                 }
363                 strbuff.append(s);
364             }
365             return strbuff.toString();
366         }
367         return str;
368     }
369 }
View Code
 1 package com.webchat.util.weixin.utils;
 2 
 3 import java.util.ArrayList;
 4 import java.util.Collection;
 5 import java.util.List;
 6 import java.util.Map;
 7 
 8 public class CollectionUtil {
 9 
10     private CollectionUtil() {
11         super();
12     }
13 
14     // 判断一个集合是否为空
15     public static <T> boolean isEmpty(Collection<T> col) {
16         if (col == null || col.isEmpty()) {
17             return true;
18         }
19 
20         return false;
21     }
22 
23     // 判断一个集合是否不为空
24     public static <T> boolean isNotEmpty(Collection<T> col) {
25         return !isEmpty(col);
26     }
27 
28     // 判断Map是否为空
29     public static <K, V> boolean isEmpty(Map<K, V> map) {
30         if (map == null || map.isEmpty()) {
31             return true;
32         }
33 
34         return false;
35     }
36 
37     // 判断Map是否不为空为空
38     public static <K, V> boolean isNotEmpty(Map<K, V> map) {
39         return !isEmpty(map);
40     }
41 
42     // 去除list中的重复数据
43     public static <T> List<T> removeRepeat(List<T> list) {
44         if (isEmpty(list)) {
45             return list;
46         }
47 
48         List<T> result = new ArrayList<T>();
49         for (T e : list) {
50             if (!result.contains(e)) {
51                 result.add(e);
52             }
53         }
54 
55         return result;
56     }
57 
58     // 将集合转换为String数组
59     public static <T> String[] toArray(List<T> list) {
60         if (isEmpty(list)) {
61             return null;
62         }
63 
64         String[] result = new String[list.size()];
65         for (int i = 0; i < list.size(); i++) {
66             result[i] = String.valueOf(list.get(i));
67         }
68 
69         return result;
70     }
71 
72 }
View Code

 

这个时候我们需要我们来完善消息入口【WebChatController.java】中的 post 方法,最终结果如下:

 1 /**
 2      * 接收微信消息处理并做分发
 3      * @param request
 4      * @param response
 5      * @throws Exception
 6      */
 7     @RequestMapping(method=RequestMethod.POST)
 8     public void post(HttpServletRequest request, HttpServletResponse response) throws Exception {
 9         // TODO 消息的接收、处理、响应
10         //消息来源可靠性验证
11         String signature = request.getParameter("signature");// 微信加密签名
12         String timestamp = request.getParameter("timestamp");// 时间戳
13         String nonce = request.getParameter("nonce");       // 随机数
14         //确认此次GET请求来自微信服务器,原样返回echostr参数内容,则接入生效,成为开发者成功,否则接入失败
15         if (!WebChatUtil.checkSignature(signature, timestamp, nonce)) {
16             //消息不可靠,直接返回
17             response.getWriter().write("");
18             return;
19         }
20         //用户每次向公众号发送消息、或者产生自定义菜单点击事件时,响应URL将得到推送
21         try {
22             response.setCharacterEncoding("UTF-8");
23             response.setContentType("text/xml");
24             //调用parseXml方法解析请求消息
25             Map<String, String> map = MessageType.parseXml(request, response);
26             String MsgType = map.get("MsgType");
27             String xml = null;//处理输入消息,返回结果的xml
28             if(MessageType.REQ_MESSAGE_TYPE_EVENT.equals(MsgType)){
29                 xml = WebChatService.parseEvent(map);
30             }else{
31                 xml = WebChatService.parseMessage(map);
32             }
33             //返回封装的xml
34             //System.out.println(xml);
35             response.getWriter().write(xml);
36         } catch (Exception ex) {
37             response.getWriter().write("");
38         }
39     }
View Code

好了,现在让我们启动本地服务来测试一下吧,打开微信测试号管理:https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login,配置可以参考:Java开发微信公众号(二)---开启开发者模式,接入微信公众平台开发 和 Java开发微信公众号(一)---初识微信公众号以及环境搭建

扫描二维码,关注你的测试公众号:然后你可以发送消息来测试

 

效果如下:

 如果在操作过程中有问题,欢迎随时讨论^.^

 

 

 

 

 

 

 

其他文章关联

(一)Java开发微信公众号(一)---初识微信公众号以及环境搭建

(二)Java开发微信公众号(二)---开启开发者模式,接入微信公众平台开发

(三)Java开发微信公众号(三)---微信服务器请求消息,响应消息,事件消息以及工具处理类的封装

(四)Java开发微信公众号(四)---微信服务器post消息体的接收及消息的处理

 

 

posted @ 2018-09-08 16:26  HanZongBo  阅读(8618)  评论(1编辑  收藏  举报