zoukankan      html  css  js  c++  java
  • 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 == '	') || (ch == '
    ') || (ch == '
    ')
    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消息体的接收及消息的处理

     

  • 相关阅读:
    Git 分支开发规范
    小程序技术调研
    弹性布局
    vue 自定义指令的魅力
    记一次基于 mpvue 的小程序开发及上线实战
    mpvue学习笔记-之微信小程序数据请求封装
    微信小程序开发框架 Wepy 的使用
    Hbuilder 开发微信小程序的代码高亮
    luogu3807 【模板】 卢卡斯定理
    luogu1955 [NOI2015] 程序自动分析
  • 原文地址:https://www.cnblogs.com/han108/p/9609037.html
Copyright © 2011-2022 走看看