二、微信公众号开发--解读和封装消息类型

前言

        这次篇幅较长,不多比比,直接进入正文;

正文

        在处理微信请求之前,我们要先分析一下微信的请求都有哪些,还有微信支持的我们的响应有哪些;打开随意一个公众号,我们可以看到我们要处理的信息一共有两种,一种是文字,图片,语音等这种的消息类型,一般的微信公众号不会去关注这些,特别是一些外包公司做的,这些基本上是点了之后没啥反映的。其实我认为这一部分用好了也能做出许多功能来;还有一种就是菜单或者关注,取关等等一些事件信息了,这一部分也是开发的重点,因为这里是允许跳转外链的,这样的话就可以使用网页来展示更多的元素信息;

        首先,我们先分析一下用户发送请求的时候,微信服务器传递给我们的都有哪些数据:

        这一部分实例官方文档中有,我就不贴出来浪费空间了,连接附上:点击打开链接

        其实我在一开始写的时候,是把这一部分进行了封装,封装了每一种类型的Request请求。后来我发现那样的结果就是又徒增了一些代码,于是我果断放弃掉了这个方案,而是将请求数据封装成了一个map集合,使用get(key)的方式进行取值。

        在返回的时候还是要把值封装一下的,这里我封装了Response响应对象,对应的是微信的响应信息;

        首先所有的类都有一些共性,我们将这些共性先封装起来,封装一个BaseResponse

package com.wx.response;

/**
 * User:Jiahengfei --> [email protected]
 * create by 2018年4月28日 from Eclipse.
 * describe:响应消息基类
 */
public class BaseResponse {
	// 接收方帐号(收到的OpenID)
    private String ToUserName;
    // 开发者微信号
    private String FromUserName;
    // 消息创建时间 (整型)
    private long CreateTime;
    // 消息类型
    private String MsgType;

    public String getToUserName() {
        return ToUserName;
    }

    public void setToUserName(String toUserName) {
        ToUserName = toUserName;
    }

    public String getFromUserName() {
        return FromUserName;
    }

    public void setFromUserName(String fromUserName) {
        FromUserName = fromUserName;
    }

    public long getCreateTime() {
        return CreateTime;
    }

    public void setCreateTime(long createTime) {
        CreateTime = createTime;
    }

    public String getMsgType() {
        return MsgType;
    }

    public void setMsgType(String msgType) {
        MsgType = msgType;
    }
}

        之后就是六种响应信息类的封装了,我在下边把代码一一贴出来,模型类没啥不好理解的,直接复制粘贴看一眼就好了;

package com.wx.response;

/**
 * User:Jiahengfei --> [email protected]
 * create by 2018年4月28日 from Eclipse.
 * describe:图片信息响应类
 */
public class ImageResponse extends BaseResponse{
	public ImageResponse(){
		this.setMsgType("image");
	}
	 private Image Image;
	    public Image getImage() {
	        return Image;
	    }

	    public void setImage(Image image) {
	        Image = image;
	    }
    /**
     * User:Jiahengfei --> [email protected]
     * create by 2018年4月28日 from Eclipse.
     * describe:图片模型类
     */
    public class Image{
    	private String MediaId;

        public String getMediaId() {
            return MediaId;
        }

        public void setMediaId(String mediaId) {
            MediaId = mediaId;
        }
    }
}
package com.wx.response;

/**
 * User:Jiahengfei --> [email protected]
 * create by 2018年4月28日 from Eclipse.
 * describe:文本信息响应类
 */
public class TextResponse extends BaseResponse{
	public TextResponse(){
		this.setMsgType("text");
	}
	// 回复的消息内容
    private String Content;
package com.wx.response;

/**
 * User:Jiahengfei --> [email protected]
 * create by 2018年4月28日 from Eclipse.
 * describe:音乐信息响应类
 */
public class MusicResponse extends BaseResponse {
	public MusicResponse(){
		this.setMsgType("music");
	}
	// 音乐
    private Music Music;

    public Music getMusic() {
        return Music;
    }

    public void setMusic(Music music) {
        Music = music;
    }
    
    /**
     * User:Jiahengfei --> [email protected]
     * create by 2018年4月28日 from Eclipse.
     * describe:音乐信息模型
     */
    public class Music {
        // 音乐标题
        private String Title;
        // 音乐描述
        private String Description;
        // 音乐链接
        private String MusicUrl;
        // 高质量音乐链接,WIFI环境优先使用该链接播放音乐
        private String HQMusicUrl;
        // 缩略图的媒体id,通过上传多媒体文件得到的id
        private String ThumbMediaId;

        public String getTitle() {
            return Title;
        }

        public void setTitle(String title) {
            Title = title;
        }

        public String getDescription() {
            return Description;
        }

        public void setDescription(String description) {
            Description = description;
        }

        public String getMusicUrl() {
            return MusicUrl;
        }

        public void setMusicUrl(String musicUrl) {
            MusicUrl = musicUrl;
        }

        public String getHQMusicUrl() {
            return HQMusicUrl;
        }

        public void setHQMusicUrl(String musicUrl) {
            HQMusicUrl = musicUrl;
        }

        public String getThumbMediaId() {
            return ThumbMediaId;
        }

        public void setThumbMediaId(String thumbMediaId) {
            ThumbMediaId = thumbMediaId;
        }
    }
}

public String getContent() { return Content; } public void setContent(String content) { Content = content; }}
package com.wx.response;

import java.util.List;

/**
 * User:Jiahengfei --> [email protected]
 * create by 2018年4月28日 from Eclipse.
 * describe:图文消息响应类
 */
public class NewsResponse extends BaseResponse {
	public NewsResponse(){
		this.setMsgType("news");
	}
	// 图文消息个数,限制为10条以内
    private int ArticleCount;
    // 多条图文消息信息,默认第一个item为大图
    private List<Article> Articles;

    public int getArticleCount() {
        return ArticleCount;
    }

    public void setArticleCount(int articleCount) {
        ArticleCount = articleCount;
    }

    public List<Article> getArticles() {
        return Articles;
    }

    public void setArticles(List<Article> articles) {
        Articles = articles;
    }
    
    /**
     * User:Jiahengfei --> [email protected]
     * create by 2018年4月28日 from Eclipse.
     * describe:图文信息模型
     */
    public class Article {
        // 图文消息名称
        private String Title;
        // 图文消息描述
        private String Description;
        // 图片链接,支持JPG、PNG格式,较好的效果为大图640*320,小图80*80
        private String PicUrl;
        // 点击图文消息跳转链接
        private String Url;

        public String getTitle() {
            return Title;
        }

        public void setTitle(String title) {
            Title = title;
        }

        public String getDescription() {
            return null == Description ? "" : Description;
        }

        public void setDescription(String description) {
            Description = description;
        }

        public String getPicUrl() {
            return null == PicUrl ? "" : PicUrl;
        }

        public void setPicUrl(String picUrl) {
            PicUrl = picUrl;
        }

        public String getUrl() {
package com.wx.response;

/**
 * User:Jiahengfei --> [email protected]
 * create by 2018年4月28日 from Eclipse.
 * describe:视频信息响应类
 */
public class VideoResponse extends BaseResponse {
	public VideoResponse(){
		this.setMsgType("video");
	}
	 // 视频
    private Video Video;

    public Video getVideo() {
        return Video;
    }

    public void setVideo(Video video) {
        Video = video;
    }
    
    /**
     * User:Jiahengfei --> [email protected]
     * create by 2018年4月28日 from Eclipse.
     * describe:视频信息模型
     */
    public class Video {
        // 媒体文件id
        private String MediaId;
        // 缩略图的媒体id
        private String ThumbMediaId;

        public String getMediaId() {
            return MediaId;
        }

        public void setMediaId(String mediaId) {
            MediaId = mediaId;
        }

        public String getThumbMediaId() {
            return ThumbMediaId;
        }

        public void setThumbMediaId(String thumbMediaId) {
            ThumbMediaId = thumbMediaId;
        }
    }
}

return null == Url ? "" : Url; } public void setUrl(String url) { Url = url; } }}
package com.wx.response;

/**
 * User:Jiahengfei --> [email protected]
 * create by 2018年4月28日 from Eclipse.
 * describe:语音信息响应类
 */
public class VoiceResponse extends BaseResponse {
	public VoiceResponse(){
		this.setMsgType("voice");
	}
	// 语音
    private Voice Voice;

    public Voice getVoice() {
        return Voice;
    }

    public void setVoice(Voice voice) {
        Voice = voice;
    }
    
    /**
     * User:Jiahengfei --> [email protected]
     * create by 2018年4月28日 from Eclipse.
     * describe:语音信息模型
     */
    public class Voice {
        // 媒体文件id
        private String MediaId;

        public String getMediaId() {
            return MediaId;
        }

        public void setMediaId(String mediaId) {
            MediaId = mediaId;
        }
    }
    
}
         封装好响应信息之后,还要封装一些其他东西, 为开发做准备工作。

        为此我们先封装一个消息工具类,用来处理一些繁琐的消息转换-->MessageUtil,这个类算是一个比较核心的类,因为后边所有与微信信息交互的地方都会用到这个类;

package com.wx.util;

import java.io.InputStream;
import java.io.Writer;
import java.util.Date;
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.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;
import com.wx.response.BaseResponse;
import com.wx.response.NewsResponse;
import com.wx.response.TextResponse;

/**
 * User:Jiahengfei --> [email protected]
 * create by 2018年5月1日 from Eclipse.
 * describe:消息处理工具类
 */
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;
    }
    
    /**
     * 从一个流中解析一个数据
     * @param inputStream
     * @return
     * @throws Exception
     */
    public static Map<String, String> parseXml(InputStream inputStream) throws Exception {
    	// 将解析结果存储在HashMap中
        Map<String, String> map = new HashMap<String, String>();
        // 读取输入流
        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 textResponse 文本消息对象
     * @return xml
     */
    public static <T extends BaseResponse> String reponseTpXml(T t) {
        xstream.alias("xml", t.getClass());
        return xstream.toXML(t);
    }

    /**
     * 图文消息对象转换成xml[特殊]
     * @param newsResponse 图文消息对象
     * @return xml
     */
    public static String newsResponseToXml(NewsResponse newsResponse) {
        xstream.alias("xml", newsResponse.getClass());
        xstream.alias("item", new NewsResponse().new Article().getClass());
        return xstream.toXML(newsResponse);
    }
    
    /**
     * 生成一个响应对象
     * 注意:::::响应时,发送消息的名称和接受消息的名称是相反的
     * @param map 接收的request集合
     * @param t 相应对象的存储空间
     * @return T
     */
    public static <T extends BaseResponse> T mapTo(Map<String, String> map,T t){
    	t.setToUserName(map.get("FromUserName"));
    	t.setFromUserName(map.get("ToUserName"));
    	t.setCreateTime(new Date().getTime());
		return t;
    }
    
    /**
     * User:Jiahengfei --> [email protected]
     * create by 2018年5月1日 from Eclipse.
     * describe:获取一些预定义好的消息对象
     */
    public static class Default{
    	/**
    	 * 文本消息
    	 * @param content 回复的消息内容
    	 */
    	public static String text(Map<String, String> map,String content){
    		TextResponse text = mapTo(map, new TextResponse());
    		text.setContent(content);
			return reponseTpXml(text);
    	}
    }
    
}
        这里需要两个jar包,一个是dom4j,还有一个是xstream,下载连接附上了,卖点积分,没积分下载的话直接联系我就好了,我直接发给你; 下载dom4j+xstream

        其他的封装用到的时候再讲,因为开发终归是要用json的,我一直用的都是fastjson,下面附上了一个json解析工具类,我一直在用;

package com.wx.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Summarize:json解析工具类
 * User:贾恒飞
 * Date:2018/3/31
 * Time:2:08
 * Email:[email protected]
 * Created with AndroidStudio3.0
 */

public class Json {
    /**
     * 解析JsonObject数据
     *
     * @param jsonString
     *            Json格式字符串
     * @param cls
     *            封装类
     *
     */
    public static <T> T obj(String jsonString, Class<T> cls) {
        T t = null;
        try {
            t = JSON.parseObject(jsonString, cls);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return t;
    }

    /**
     * 解析JsonArray数据
     *
     * @param jsonString
     * @param cls
     * @return
     */
    public static <T> List<T> array(String jsonString, Class<T> cls) {
        List<T> list = new ArrayList<T>();
        try {
            list = JSON.parseArray(jsonString, cls);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * 解析JsonArray数据,返回Map类型的List
     *
     * @param jsonString
     * @return
     */
    public static List<Map<String, Object>> maps(String jsonString) {
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        try {
            list = JSON.parseObject(jsonString,new TypeReference<List<Map<String, Object>>>() {});
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }
    
    /**
     * json to map
     * @param jsonStr
     * @return
     */
    @SuppressWarnings("unchecked")
	public static Map<String,Object> map(String jsonStr){
    	return JSON.parseObject(jsonStr, Map.class);
    }

    /**
     * 对象解析成Json数据
     * @param t 对象
     * @param <T> 类型
     * @return json字符串
     */
    public static <T> String toJson(T t){
        String json = "";
        try {
            json = JSON.toJSONString(t);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return json;
    }
}








猜你喜欢

转载自blog.csdn.net/qq_36676433/article/details/80203565