第四篇:微信公众平台开发实战Java版之完成消息接受与相应以及消息的处理
温馨提示:
这篇文章是依赖前几篇的文章的。
第一篇:微信公众平台开发实战之了解微信公众平台基础知识以及资料准备
第二篇 :微信公众平台开发实战之开启开发者模式,接入微信公众平台开发
第三篇 :微信公众平台开发实战之请求消息,响应消息以及事件消息类的封装
首先,我们看看原来写的dopost方法:
/*** 处理微信服务器发来的消息*/publicvoiddoPost(HttpServletRequest request, HttpServletResponse response)throwsServletException, 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
封装消息处理工具:
packagecom.souvc.weixin.util;importjava.io.InputStream;importjava.io.Writer;importjava.util.HashMap;importjava.util.List;importjava.util.Map;importjavax.servlet.http.HttpServletRequest;importorg.dom4j.Document;importorg.dom4j.Element;importorg.dom4j.io.SAXReader;importcom.souvc.weixin.message.resp.Article;importcom.souvc.weixin.message.resp.ImageMessage;importcom.souvc.weixin.message.resp.MusicMessage;importcom.souvc.weixin.message.resp.NewsMessage;importcom.souvc.weixin.message.resp.TextMessage;importcom.souvc.weixin.message.resp.VideoMessage;importcom.souvc.weixin.message.resp.VoiceMessage;importcom.thoughtworks.xstream.XStream;importcom.thoughtworks.xstream.core.util.QuickWriter;importcom.thoughtworks.xstream.io.HierarchicalStreamWriter;importcom.thoughtworks.xstream.io.xml.PRettyPrintWriter;importcom.thoughtworks.xstream.io.xml.XppDriver;/*** 类名: MessageUtil </br>
* 描述: 消息处理工具类</br>
* 开发人员: souvc </br>
* 创建时间: 2015-9-30 </br>
* 发布版本:V1.0 </br>*/publicclassMessageUtil {//请求消息类型:文本publicstaticfinalString REQ_MESSAGE_TYPE_TEXT = "text";//请求消息类型:图片publicstaticfinalString REQ_MESSAGE_TYPE_IMAGE = "image";//请求消息类型:语音publicstaticfinalString REQ_MESSAGE_TYPE_VOICE = "voice";//请求消息类型:视频publicstaticfinalString REQ_MESSAGE_TYPE_VIDEO = "video";//请求消息类型:小视频publicstaticfinalString REQ_MESSAGE_TYPE_SHORTVIDEO = "shortvideo";//请求消息类型:地理位置publicstaticfinalString REQ_MESSAGE_TYPE_LOCATION = "location";//请求消息类型:链接publicstaticfinalString REQ_MESSAGE_TYPE_LINK = "link";//请求消息类型:事件推送publicstaticfinalString REQ_MESSAGE_TYPE_EVENT = "event";//事件类型:subscribe(订阅)publicstaticfinalString EVENT_TYPE_SUBSCRIBE = "subscribe";//事件类型:unsubscribe(取消订阅)publicstaticfinalString EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";//事件类型:scan(用户已关注时的扫描带参数二维码)publicstaticfinalString EVENT_TYPE_SCAN = "scan";//事件类型:LOCATION(上报地理位置)publicstaticfinalString EVENT_TYPE_LOCATION = "LOCATION";//事件类型:CLICK(自定义菜单)publicstaticfinalString EVENT_TYPE_CLICK = "CLICK";//响应消息类型:文本publicstaticfinalString RESP_MESSAGE_TYPE_TEXT = "text";//响应消息类型:图片publicstaticfinalString RESP_MESSAGE_TYPE_IMAGE = "image";//响应消息类型:语音publicstaticfinalString RESP_MESSAGE_TYPE_VOICE = "voice";//响应消息类型:视频publicstaticfinalString RESP_MESSAGE_TYPE_VIDEO = "video";//响应消息类型:音乐publicstaticfinalString RESP_MESSAGE_TYPE_MUSIC = "music";//响应消息类型:图文publicstaticfinalString RESP_MESSAGE_TYPE_NEWS = "news";/*** 解析微信发来的请求(XML)
*
*@paramrequest
*@returnMap<String, String>
*@throwsException*/@SuppressWarnings("unchecked")publicstaticMap<String, String> parseXml(HttpServletRequest request)throwsException {//将解析结果存储在HashMap中Map<String, String> map =newHashMap<String, String>();//从request中取得输入流InputStream inputStream =request.getInputStream();//读取输入流SAXReader reader =newSAXReader();
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;returnmap;
}/*** 扩展xstream使其支持CDATA*/privatestaticXStream xstream =newXStream(newXppDriver() {publicHierarchicalStreamWriter createWriter(Writer out) {returnnewPrettyPrintWriter(out) {//对所有xml节点的转换都增加CDATA标记booleancdata =true;
@SuppressWarnings("unchecked")publicvoidstartNode(String name, Class clazz) {super.startNode(name, clazz);
}protectedvoidwriteText(QuickWriter writer, String text) {if(cdata) {
writer.write("<![CDATA[");
writer.write(text);
writer.write("]]>");
}else{
writer.write(text);
}
}
};
}
});/*** 文本消息对象转换成xml
*
*@paramtextMessage 文本消息对象
*@returnxml*/publicstaticString messageToXml(TextMessage textMessage) {
xstream.alias("xml", textMessage.getClass());returnxstream.toXML(textMessage);
}/*** 图片消息对象转换成xml
*
*@paramimageMessage 图片消息对象
*@returnxml*/publicstaticString messageToXml(ImageMessage imageMessage) {
xstream.alias("xml", imageMessage.getClass());returnxstream.toXML(imageMessage);
}/*** 语音消息对象转换成xml
*
*@paramvoiceMessage 语音消息对象
*@returnxml*/publicstaticString messageToXml(VoiceMessage voiceMessage) {
xstream.alias("xml", voiceMessage.getClass());returnxstream.toXML(voiceMessage);
}/*** 视频消息对象转换成xml
*
*@paramvideoMessage 视频消息对象
*@returnxml*/publicstaticString messageToXml(VideoMessage videoMessage) {
xstream.alias("xml", videoMessage.getClass());returnxstream.toXML(videoMessage);
}/*** 音乐消息对象转换成xml
*
*@parammusicMessage 音乐消息对象
*@returnxml*/publicstaticString messageToXml(MusicMessage musicMessage) {
xstream.alias("xml", musicMessage.getClass());returnxstream.toXML(musicMessage);
}/*** 图文消息对象转换成xml
*
*@paramnewsMessage 图文消息对象
*@returnxml*/publicstaticString messageToXml(NewsMessage newsMessage) {
xstream.alias("xml", newsMessage.getClass());
xstream.alias("item",newArticle().getClass());returnxstream.toXML(newsMessage);
}
}
使用CoreServlet 类完成消息的接受与响应:
packagecom.souvc.weixin.servlet;importjava.io.IOException;importjava.io.PrintWriter;importjavax.servlet.ServletException;importjavax.servlet.http.HttpServlet;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;importcom.souvc.weixin.service.CoreService;importcom.souvc.weixin.util.SignUtil;/*** 类名: CoreServlet </br>
* 描述: 来接收微信服务器传来信息 </br>
* 开发人员: souvc</br>
* 创建时间:2015-9-29 </br>
* 发布版本:V1.0 </br>*/publicclassCoreServletextendsHttpServlet {privatestaticfinallongserialVersionUID = 4323197796926899691L;/*** 确认请求来自微信服务器*/publicvoiddoGet(HttpServletRequest request, HttpServletResponse response)throwsServletException, 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;
}/*** 处理微信服务器发来的消息*/publicvoiddoPost(HttpServletRequest request, HttpServletResponse response)throwsServletException, 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();
}
}
使用CoreService类完成消息的处理:
packagecom.souvc.weixin.service;importjava.util.Date;importjava.util.Map;importjavax.servlet.http.HttpServletRequest;importcom.souvc.weixin.message.resp.TextMessage;importcom.souvc.weixin.util.MessageUtil;/*** 类名: CoreService </br>
* 描述: 核心服务类 </br>
* 开发人员: souvc </br>
* 创建时间: 2015-9-30 </br>
* 发布版本:V1.0 </br>*/publicclassCoreService {/*** 处理微信发来的请求
*@paramrequest
*@returnxml*/publicstaticString 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 =newTextMessage();
textMessage.setToUserName(fromUserName);
textMessage.setFromUserName(toUserName);
textMessage.setCreateTime(newDate().getTime());
textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);//文本消息if(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {
respContent= "您发送的是文本消息!";
}//图片消息elseif(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) {
respContent= "您发送的是图片消息!";
}//语音消息elseif(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)) {
respContent= "您发送的是语音消息!";
}//视频消息elseif(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VIDEO)) {
respContent= "您发送的是视频消息!";
}//视频消息elseif(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_SHORTVIDEO)) {
respContent= "您发送的是小视频消息!";
}//地理位置消息elseif(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)) {
respContent= "您发送的是地理位置消息!";
}//链接消息elseif(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)) {
respContent= "您发送的是链接消息!";
}//事件推送elseif(msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {//事件类型String eventType = requestMap.get("Event");//关注if(eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {
respContent= "谢谢您的关注!";
}//取消关注elseif(eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) {//TODO 取消订阅后用户不会再收到公众账号发送的消息,因此不需要回复}//扫描带参数二维码elseif(eventType.equals(MessageUtil.EVENT_TYPE_SCAN)) {//TODO 处理扫描带参数二维码事件}//上报地理位置elseif(eventType.equals(MessageUtil.EVENT_TYPE_LOCATION)) {//TODO 处理上报地理位置事件}//自定义菜单elseif(eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {//TODO 处理菜单点击事件}
}//设置文本消息的内容textMessage.setContent(respContent);//将文本消息对象转换成xmlrespXml =MessageUtil.messageToXml(textMessage);
}catch(Exception e) {
e.printStackTrace();
}returnrespXml;
}
}
然后部署到我们的BAE上面,体验一下。(部署方法请参照 第二篇 :微信公众平台开发实战之开启开发者模式,接入微信公众平台开发)。
效果如下: