订阅号消息事件封装
![](https://img.haomeiwen.com/i3239635/01da0f9f72de2c0b.png)
消息事件的封装其实是比较细节的。后面会提到一些细节。
分析微信消息
消息类型分析
- image 图片消息
<xml>
<ToUserName>< ![CDATA[toUser] ]></ToUserName>
<FromUserName>< ![CDATA[fromUser] ]></FromUserName>
<CreateTime>1348831860</CreateTime>
<MsgType>< ![CDATA[image] ]></MsgType>
<PicUrl>< ![CDATA[this is a url] ]></PicUrl>
<MediaId>< ![CDATA[media_id] ]></MediaId>
<MsgId>1234567890123456</MsgId>
</xml>
- text 文本消息
<xml>
<ToUserName>< ![CDATA[toUser] ]></ToUserName>
<FromUserName>< ![CDATA[fromUser] ]></FromUserName>
<CreateTime>1348831860</CreateTime>
<MsgType>< ![CDATA[text] ]></MsgType>
<Content>< ![CDATA[this is a test] ]></Content>
<MsgId>1234567890123456</MsgId>
</xml>
- voice 语音消息
<xml>
<ToUserName>< ![CDATA[toUser] ]></ToUserName>
<FromUserName>< ![CDATA[fromUser]></FromUserName>
<CreateTime>1357290913</CreateTime>
<MsgType>< ![CDATA[voice] ]></MsgType>
<MediaId>< ![CDATA[media_id] ]></MediaId>
<Format>< ![CDATA[Format] ]></Format>
<MsgId>1234567890123456</MsgId>
</xml>
- video视频消息
<xml>
<ToUserName>< ![CDATA[toUser] ]></ToUserName>
<FromUserName>< ![CDATA[fromUser] ]></FromUserName>
<CreateTime>1357290913</CreateTime>
<MsgType>< ![CDATA[video] ]></MsgType>
<MediaId>< ![CDATA[media_id] ]></MediaId>
<ThumbMediaId>< ![CDATA[thumb_media_id] ]></ThumbMediaId>
<MsgId>1234567890123456</MsgId>
</xml>
- shortvideo 小视频信息
<xml>
<ToUserName>< ![CDATA[toUser] ]></ToUserName>
<FromUserName>< ![CDATA[fromUser] ]></FromUserName>
<CreateTime>1357290913</CreateTime>
<MsgType>< ![CDATA[shortvideo] ]></MsgType>
<MediaId>< ![CDATA[media_id] ]></MediaId>
<ThumbMediaId>< ![CDATA[thumb_media_id] ]></ThumbMediaId>
<MsgId>1234567890123456</MsgId>
</xml>
- location 地理位置信息
<xml>
<ToUserName>< ![CDATA[toUser] ]></ToUserName>
<FromUserName>< ![CDATA[fromUser] ]></FromUserName>
<CreateTime>1351776360</CreateTime>
<MsgType>< ![CDATA[location] ]></MsgType>
<Location_X>23.134521</Location_X>
<Location_Y>113.358803</Location_Y>
<Scale>20</Scale>
<Label>< ![CDATA[位置信息] ]></Label>
<MsgId>1234567890123456</MsgId>
</xml>
- link 链接信息
<xml>
<ToUserName>< ![CDATA[toUser] ]></ToUserName>
<FromUserName>< ![CDATA[fromUser] ]></FromUserName>
<CreateTime>1351776360</CreateTime>
<MsgType>< ![CDATA[link] ]></MsgType>
<Title>< ![CDATA[公众平台官网链接] ]></Title>
<Description>< ![CDATA[公众平台官网链接] ]></Description>
<Url>< ![CDATA[url] ]></Url>
<MsgId>1234567890123456</MsgId>
</xml>
- event(下章介绍)
以上具体字段含义请参考微信api官网文档
封装实现
- 公共属性提取
- 利于转化为微信能识别的xml格式
公共属性BaseMessage
public class BaseMessage {
@XStreamAlias("ToUserName")
private String toUserName;
@XStreamAlias("FromUserName")
private String fromUserName;
@XStreamAlias("CreateTime")
private long createTime;
@XStreamAlias("MsgId")
private long msgId;
public enum MsgType {
image, text, voice, video, shortvideo, location, link, event
}
}
text文本消息
@XStreamAlias("xml")
public class TextMessage extends BaseMessage {
@XStreamAlias("Content")
private String content;
@XStreamAlias("MsgType")
private final MsgType msgType = MsgType.text;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public MsgType getMsgType() {
return msgType;
}
}
image图片消息
@XStreamAlias("xml")
public class ImageMessage extends BaseMessage{
@XStreamAlias("PicUrl")
private String picUrl;
@XStreamAlias("MsgType")
private final MsgType msgType = MsgType.image;
@XStreamAlias("MediaId")
private String mediaId;
}
video视频消息
@XStreamAlias("xml")
public class VideoMessage extends BaseMessage {
@XStreamAlias("MediaId")
private String mediaId;
@XStreamAlias("MsgType")
private final MsgType msgType = MsgType.video;
@XStreamAlias("ThumbMediaId")
private String thumbMediaId;
}
shortvideo短视频消息
@XStreamAlias("xml")
public class ShortVideoMessage extends BaseMessage {
@XStreamAlias("MediaId")
private String mediaId;
@XStreamAlias("MsgType")
private final MsgType msgType = MsgType.shortvideo;
@XStreamAlias("ThumbMediaId")
private String thumbMediaId;
}
link连接消息
@XStreamAlias("xml")
public class LinkMessage extends BaseMessage {
@XStreamAlias("Title")
private String title;
@XStreamAlias("Description")
private String description;
@XStreamAlias("MsgType")
private final MsgType msgType = MsgType.link;
@XStreamAlias("Url")
private String url;
}
Location 地理位置消息
@XStreamAlias("xml")
public class LocationMessage extends BaseMessage {
@XStreamAlias("Location_X")
private String location_X;
@XStreamAlias("Location_Y")
private String location_Y;
@XStreamAlias("MsgType")
private final MsgType msgType = MsgType.location;
@XStreamAlias("Scale")
private String scale;
@XStreamAlias("Lable")
private String label;
}
voice语音消息
@XStreamAlias("xml")
public class VoiceMessage extends BaseMessage{
@XStreamAlias("MediaId")
private String mediaId;
@XStreamAlias("MsgType")
private final MsgType msgType = MsgType.voice;
@XStreamAlias("Format")
private String format;
@XStreamAlias("Recognition")
private String recognition;
}
以上就是封装内容,@XStreamAlias很重要,这是一个xml解析成对象,对象转换成xml的工具包(xstream)提供的,详见pom文件。其中的@XStreamAlias("xml")就是转换成xml是作为节点的名字用的。
<xml>
<ToUserName>< ![CDATA[toUser] ]></ToUserName>
<FromUserName>< ![CDATA[fromUser] ]></FromUserName>
<CreateTime>1351776360</CreateTime>
<MsgType>< ![CDATA[link] ]></MsgType>
<Title>< ![CDATA[公众平台官网链接] ]></Title>
<Description>< ![CDATA[公众平台官网链接] ]></Description>
<Url>< ![CDATA[url] ]></Url>
<MsgId>1234567890123456</MsgId>
</xml>
这样就不用傻傻的把成员变量定义成首字母大写吧?
依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.11</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.51</version>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>1.4.11.1</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>
</dependencies>
xstream 转换时如何变成微信想要的样子
MessageUtil封装
public class MessageUtil {
/**
* 将信息转换成符合微信服务器需要的xml字符串
* @param message 消息实体(video,text,......等等所有的消息公用)
* @param <T> 泛型可以传递任意的类型消息
* @return
*/
public static <T> String messageToXml(T message) {
XStream xstream = getXstream();
//xstream 处理注解如:@XStreamAlias("CreateTime")
xstream.processAnnotations(message.getClass());
return xstream.toXML(message);
}
/**
*
* @param xml xml文本消息转换成消息实体
* @param cls 需要转换的消息类型
* @param <V> 泛型 返回你传递的消息类型实体
* @return
*/
public static <V> V xmlToMessage(String xml, Class<V> cls) {
XStream xstream = getXstream();
xstream.processAnnotations(cls);
return (V) xstream.fromXML(xml);
}
/**
* 将xml字符串转换成Map
* @param xml xml字符串
* @return
* @throws Exception
*/
public static Map<String, String> parseXml(String xml) throws Exception {
Map<String, String> map = new HashMap<>();
SAXReader reader = new SAXReader();
Document document = reader.read(new ByteArrayInputStream(xml.getBytes()));
Element root = document.getRootElement();
List<Element> elementList = root.elements();
for (Element e : elementList)
map.put(e.getName(), e.getText());
return map;
}
/**
* 解析request的请求内容
* @param request
* @return
* @throws IOException
*/
public static String requestToXml(HttpServletRequest request) throws IOException {
InputStream inputStream = request.getInputStream();
String result = new BufferedReader(new InputStreamReader(inputStream))
.lines().collect(Collectors.joining(System.lineSeparator()));
return result;
}
/**
* 定制Xstream 对所有xml节点的转换都增加CDATA标记
* @return
*/
private static XStream getXstream() {
return new XStream(new XppDriver() {
public HierarchicalStreamWriter createWriter(Writer out) {
return new PrettyPrintWriter(out) {
// 对所有xml节点的转换都增加CDATA标记
boolean cdata = true;
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);
}
}
};
}
});
}
}
测试验证
public class MessageUtilTest {
@Test
public void beanToXml(){
TextMessage textMessage = new TextMessage();
textMessage.setFromUserName("ppb");
textMessage.setToUserName("aaa");
textMessage.setContent("笔芯");
textMessage.setCreateTime(new Date().getTime());
String responseMessage = MessageUtil.messageToXml(textMessage);
assertNotNull(responseMessage);
TextMessage textMessage1 = MessageUtil.xmlToMessage(responseMessage,TextMessage.class);
assertNotNull(textMessage1);
}
}
总结
消息的封装以及处理都差不多了。感觉有帮助就点个赞
网友评论