zoukankan      html  css  js  c++  java
  • 第四篇 :微信公众平台开发实战Java版之完成消息接受与相应以及消息的处理

    温馨提示:

         这篇文章是依赖前几篇的文章的。

         第一篇:微信公众平台开发实战之了解微信公众平台基础知识以及资料准备

         第二篇 :微信公众平台开发实战之开启开发者模式,接入微信公众平台开发

         第三篇 :微信公众平台开发实战之请求消息,响应消息以及事件消息类的封装

    首先,我们看看原来写的dopost方法:

    /**
         * 处理微信服务器发来的消息
         */
        public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            // TODO 消息的接收、处理、响应
        }

    doPost方法有两个参数:

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

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

    一、解析微信服务器传来的消息

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

    所用到的jar 包是:dom4j-1.6.1.jar  

    官网下载地址:http://www.dom4j.org/dom4j-1.6.1/

    网盘下载地址:http://yunpan.cn/cQyR8KkIXxHXn  访问密码 0f2e

    二、将响应消息转换成xml返回给微信服务器

    如何将响应消息转换成xml返回的问题,这里我们将  采用开源框架xstream来实现Java类到xml的转换

    所用到的jar包为:xstream-1.3.1.jar

    网盘下载地址:http://yunpan.cn/cQyBU2vTYAe2f  访问密码 ad36

    封装消息处理工具:

    package com.souvc.weixin.util;
    
    import java.io.InputStream;
    import java.io.Writer;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import javax.servlet.http.HttpServletRequest;
    
    import org.dom4j.Document;
    import org.dom4j.Element;
    import org.dom4j.io.SAXReader;
    
    import com.souvc.weixin.message.resp.Article;
    import com.souvc.weixin.message.resp.ImageMessage;
    import com.souvc.weixin.message.resp.MusicMessage;
    import com.souvc.weixin.message.resp.NewsMessage;
    import com.souvc.weixin.message.resp.TextMessage;
    import com.souvc.weixin.message.resp.VideoMessage;
    import com.souvc.weixin.message.resp.VoiceMessage;
    import com.thoughtworks.xstream.XStream;
    import com.thoughtworks.xstream.core.util.QuickWriter;
    import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
    import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
    import com.thoughtworks.xstream.io.xml.XppDriver;
    
    /**
    * 类名: MessageUtil </br>
    * 描述: 消息处理工具类</br>
    * 开发人员: souvc </br>
    * 创建时间:  2015-9-30 </br>
    * 发布版本:V1.0  </br>
     */
    public class MessageUtil {
        // 请求消息类型:文本
        public static final String REQ_MESSAGE_TYPE_TEXT = "text";
        // 请求消息类型:图片
        public static final String REQ_MESSAGE_TYPE_IMAGE = "image";
        // 请求消息类型:语音
        public static final String REQ_MESSAGE_TYPE_VOICE = "voice";
        // 请求消息类型:视频
        public static final String REQ_MESSAGE_TYPE_VIDEO = "video";
        // 请求消息类型:小视频
        public static final String REQ_MESSAGE_TYPE_SHORTVIDEO = "shortvideo";
        // 请求消息类型:地理位置
        public static final String REQ_MESSAGE_TYPE_LOCATION = "location";
        // 请求消息类型:链接
        public static final String REQ_MESSAGE_TYPE_LINK = "link";
    
        // 请求消息类型:事件推送
        public static final String REQ_MESSAGE_TYPE_EVENT = "event";
    
        // 事件类型:subscribe(订阅)
        public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";
        // 事件类型:unsubscribe(取消订阅)
        public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";
        // 事件类型:scan(用户已关注时的扫描带参数二维码)
        public static final String EVENT_TYPE_SCAN = "scan";
        // 事件类型:LOCATION(上报地理位置)
        public static final String EVENT_TYPE_LOCATION = "LOCATION";
        // 事件类型:CLICK(自定义菜单)
        public static final String EVENT_TYPE_CLICK = "CLICK";
    
        // 响应消息类型:文本
        public static final String RESP_MESSAGE_TYPE_TEXT = "text";
        // 响应消息类型:图片
        public static final String RESP_MESSAGE_TYPE_IMAGE = "image";
        // 响应消息类型:语音
        public static final String RESP_MESSAGE_TYPE_VOICE = "voice";
        // 响应消息类型:视频
        public static final String RESP_MESSAGE_TYPE_VIDEO = "video";
        // 响应消息类型:音乐
        public static final String RESP_MESSAGE_TYPE_MUSIC = "music";
        // 响应消息类型:图文
        public static final String RESP_MESSAGE_TYPE_NEWS = "news";
    
        /**
         * 解析微信发来的请求(XML)
         * 
         * @param request
         * @return Map<String, String>
         * @throws Exception
         */
        @SuppressWarnings("unchecked")
        public static Map<String, String> parseXml(HttpServletRequest request) throws Exception {
            // 将解析结果存储在HashMap中
            Map<String, String> map = new HashMap<String, String>();
    
            // 从request中取得输入流
            InputStream inputStream = request.getInputStream();
            // 读取输入流
            SAXReader reader = new SAXReader();
            Document document = reader.read(inputStream);
            // 得到xml根元素
            Element root = document.getRootElement();
            // 得到根元素的所有子节点
            List<Element> elementList = root.elements();
    
            // 遍历所有子节点
            for (Element e : elementList)
                map.put(e.getName(), e.getText());
    
            // 释放资源
            inputStream.close();
            inputStream = null;
    
            return map;
        }
    
        /**
         * 扩展xstream使其支持CDATA
         */
        private static XStream xstream = new XStream(new XppDriver() {
            public HierarchicalStreamWriter createWriter(Writer out) {
                return new PrettyPrintWriter(out) {
                    // 对所有xml节点的转换都增加CDATA标记
                    boolean cdata = true;
    
                    @SuppressWarnings("unchecked")
                    public void startNode(String name, Class clazz) {
                        super.startNode(name, clazz);
                    }
    
                    protected void writeText(QuickWriter writer, String text) {
                        if (cdata) {
                            writer.write("<![CDATA[");
                            writer.write(text);
                            writer.write("]]>");
                        } else {
                            writer.write(text);
                        }
                    }
                };
            }
        });
    
        /**
         * 文本消息对象转换成xml
         * 
         * @param textMessage 文本消息对象
         * @return xml
         */
        public static String messageToXml(TextMessage textMessage) {
            xstream.alias("xml", textMessage.getClass());
            return xstream.toXML(textMessage);
        }
    
        /**
         * 图片消息对象转换成xml
         * 
         * @param imageMessage 图片消息对象
         * @return xml
         */
        public static String messageToXml(ImageMessage imageMessage) {
            xstream.alias("xml", imageMessage.getClass());
            return xstream.toXML(imageMessage);
        }
    
        /**
         * 语音消息对象转换成xml
         * 
         * @param voiceMessage 语音消息对象
         * @return xml
         */
        public static String messageToXml(VoiceMessage voiceMessage) {
            xstream.alias("xml", voiceMessage.getClass());
            return xstream.toXML(voiceMessage);
        }
    
        /**
         * 视频消息对象转换成xml
         * 
         * @param videoMessage 视频消息对象
         * @return xml
         */
        public static String messageToXml(VideoMessage videoMessage) {
            xstream.alias("xml", videoMessage.getClass());
            return xstream.toXML(videoMessage);
        }
    
        /**
         * 音乐消息对象转换成xml
         * 
         * @param musicMessage 音乐消息对象
         * @return xml
         */
        public static String messageToXml(MusicMessage musicMessage) {
            xstream.alias("xml", musicMessage.getClass());
            return xstream.toXML(musicMessage);
        }
    
        /**
         * 图文消息对象转换成xml
         * 
         * @param newsMessage 图文消息对象
         * @return xml
         */
        public static String messageToXml(NewsMessage newsMessage) {
            xstream.alias("xml", newsMessage.getClass());
            xstream.alias("item", new Article().getClass());
            return xstream.toXML(newsMessage);
        }
    }
    View Code

    使用CoreServlet 类完成消息的接受与响应:

    package com.souvc.weixin.servlet;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import com.souvc.weixin.service.CoreService;
    import com.souvc.weixin.util.SignUtil;
    
    /**
     * 类名: CoreServlet </br> 
     * 描述: 来接收微信服务器传来信息 </br> 
     * 开发人员: souvc</br> 
     * 创建时间:2015-9-29 </br> 
     * 发布版本:V1.0 </br>
     */
    public class CoreServlet extends HttpServlet {
    
        private static final long serialVersionUID = 4323197796926899691L;
    
        /**
         * 确认请求来自微信服务器
         */
        public void doGet(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            
            // 微信加密签名
            String signature = request.getParameter("signature");
            // 时间戳
            String timestamp = request.getParameter("timestamp");
            // 随机数
            String nonce = request.getParameter("nonce");
            // 随机字符串
            String echostr = request.getParameter("echostr");
    
            PrintWriter out = response.getWriter();
            
            // 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
            if (SignUtil.checkSignature(signature, timestamp, nonce)) {
                out.print(echostr);
            }
            
            out.close();
            out = null;
        }
    
        /**
         * 处理微信服务器发来的消息
         */
        public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            // 消息的接收、处理、响应
            // 将请求、响应的编码均设置为UTF-8(防止中文乱码)
            request.setCharacterEncoding("UTF-8");
            response.setCharacterEncoding("UTF-8");
    
            // 调用核心业务类接收消息、处理消息
            String respXml = CoreService.processRequest(request);
    
            // 响应消息
            PrintWriter out = response.getWriter();
            out.print(respXml);
            out.close();
        }
    
    }
    View Code

    使用CoreService类完成消息的处理:

    package com.souvc.weixin.service;
    
    import java.util.Date;
    import java.util.Map;
    
    import javax.servlet.http.HttpServletRequest;
    
    import com.souvc.weixin.message.resp.TextMessage;
    import com.souvc.weixin.util.MessageUtil;
    
    /**
    * 类名: CoreService </br>
    * 描述: 核心服务类 </br>
    * 开发人员: souvc </br>
    * 创建时间:  2015-9-30 </br>
    * 发布版本:V1.0  </br>
     */
    public class CoreService {
        /**
         * 处理微信发来的请求
         * @param request
         * @return xml
         */
        public static String processRequest(HttpServletRequest request) {
            // xml格式的消息数据
            String respXml = null;
            // 默认返回的文本消息内容
            String respContent = "未知的消息类型!";
            try {
                // 调用parseXml方法解析请求消息
                Map<String, String> requestMap = MessageUtil.parseXml(request);
                // 发送方帐号
                String fromUserName = requestMap.get("FromUserName");
                // 开发者微信号
                String toUserName = requestMap.get("ToUserName");
                // 消息类型
                String msgType = requestMap.get("MsgType");
    
                // 回复文本消息
                TextMessage textMessage = new TextMessage();
                textMessage.setToUserName(fromUserName);
                textMessage.setFromUserName(toUserName);
                textMessage.setCreateTime(new Date().getTime());
                textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);
    
                // 文本消息
                if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {
                    respContent = "您发送的是文本消息!";
                }
                // 图片消息
                else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) {
                    respContent = "您发送的是图片消息!";
                }
                // 语音消息
                else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)) {
                    respContent = "您发送的是语音消息!";
                }
                // 视频消息
                else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VIDEO)) {
                    respContent = "您发送的是视频消息!";
                }
                // 视频消息
                else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_SHORTVIDEO)) {
                    respContent = "您发送的是小视频消息!";
                }
                // 地理位置消息
                else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)) {
                    respContent = "您发送的是地理位置消息!";
                }
                // 链接消息
                else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)) {
                    respContent = "您发送的是链接消息!";
                }
                // 事件推送
                else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {
                    // 事件类型
                    String eventType = requestMap.get("Event");
                    // 关注
                    if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {
                        respContent = "谢谢您的关注!";
                    }
                    // 取消关注
                    else if (eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) {
                        // TODO 取消订阅后用户不会再收到公众账号发送的消息,因此不需要回复
                    }
                    // 扫描带参数二维码
                    else if (eventType.equals(MessageUtil.EVENT_TYPE_SCAN)) {
                        // TODO 处理扫描带参数二维码事件
                    }
                    // 上报地理位置
                    else if (eventType.equals(MessageUtil.EVENT_TYPE_LOCATION)) {
                        // TODO 处理上报地理位置事件
                    }
                    // 自定义菜单
                    else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {
                        // TODO 处理菜单点击事件
                    }
                }
                // 设置文本消息的内容
                textMessage.setContent(respContent);
                // 将文本消息对象转换成xml
                respXml = MessageUtil.messageToXml(textMessage);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return respXml;
        }
    }
    View Code

    然后部署到我们的BAE上面,体验一下。(部署方法请参照 第二篇 :微信公众平台开发实战之开启开发者模式,接入微信公众平台开发)。

    效果如下:

    其他文章关联:

    第一篇:微信公众平台开发实战Java版之了解微信公众平台基础知识以及资料准备

    第二篇 :微信公众平台开发实战Java版之开启开发者模式,接入微信公众平台开发

    第三篇 :微信公众平台开发实战Java版之请求消息,响应消息以及事件消息类的封装

    第四篇 :微信公众平台开发实战Java版之完成消息接受与相应以及消息的处理

    第五篇 :微信公众平台开发实战Java版之如何获取公众号的access_token以及缓存access_token

    第六篇 :微信公众平台开发实战Java版之如何自定义微信公众号菜单

    第七篇 :微信公众平台开发实战Java版之如何获取微信用户基本信息

    第八篇 :微信公众平台开发实战Java版之如何网页授权获取用户基本信息

    第九篇 :微信公众平台开发实战Java版之如何实现自定义分享内容

    其他:Web开发须知:URL编码与解码

  • 相关阅读:
    spring与springmvc父子容器
    spring容器BeanFactory简单例子
    spring整体架构
    css中".",",",“~”和“>”符号的意义
    CSS中的块级元素与行级元素
    java反射和动态代理
    thymeleaf的fragment例子
    编写一个简单的 JDBC 程序
    http://localhost/ 或 http://127.0.0.1/ 报错:HTTP 404 的解决办法
    教你如何清除 MyEclipse/Eclipse 中 Web Browser 和 Switch Workspace 的历史记录
  • 原文地址:https://www.cnblogs.com/liuhongfeng/p/4848481.html
Copyright © 2011-2022 走看看