本文主要讲述了如何在微信公众平台实现消息接收以及消息的处理,使用java语言开发,如今把实现思路和代码整理出来分先给兄弟们,但愿给他们带来帮助。java
舒适提示:服务器
这篇文章是依赖前几篇的文章的。微信
第一篇:微信公众平台开发实战之了解微信公众平台基础知识以及资料准备微信公众平台
第二篇 :微信公众平台开发实战之开启开发者模式,接入微信公众平台开发框架
第三篇 :微信公众平台开发实战之请求消息,响应消息以及事件消息类的封装dom
首先,咱们看看原来写的dopost方法:ide
/**
* 处理微信服务器发来的消息
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// TODO 消息的接收、处理、响应
}
doPost方法有两个参数:工具
1.request中封装了请求相关的全部内容,能够从request中取出微信服务器发来的消息;post
2.response咱们能够对接收到的消息进行响应,即发送消息。ui
1、解析微信服务器传来的消息
由于微信服务器发送过来的是xml格式的消息,因此咱们能够采用 开源框架dom4j去解析xml 。
所用到的jar 包是:dom4j-1.6.1.jar
官网下载地址:http://www.dom4j.org/dom4j-1.6.1/
网盘下载地址:http://yunpan.cn/cQyR8KkIXxHXn 访问密码 0f2e
2、将响应消息转换成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
* 描述: 消息处理工具类
* 开发人员: souvc
* 建立时间: 2015-9-30
* 发布版本:V1.0
*/
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
* @throws Exception
*/
@SuppressWarnings("unchecked")
public static Map parseXml(HttpServletRequest request) throws Exception {
// 将解析结果存储在HashMap中
Map map = new HashMap();
// 从request中取得输入流
InputStream inputStream = request.getInputStream();
// 读取输入流
SAXReader reader = new SAXReader();
Document document = reader.read(inputStream);
// 获得xml根元素
Element root = document.getRootElement();
// 获得根元素的全部子节点
List 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("");
} 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);
}
}
使用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
* 描述: 来接收微信服务器传来信息
* 开发人员: souvc
* 建立时间:2015-9-29
* 发布版本:V1.0
*/
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();
}
}
使用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
* 描述: 核心服务类
* 开发人员: souvc
* 建立时间: 2015-9-30
* 发布版本:V1.0
*/
public class CoreService {
/**
* 处理微信发来的请求
* @param request
* @return xml
*/
public static String processRequest(HttpServletRequest request) {
// xml格式的消息数据
String respXml = null;
// 默认返回的文本消息内容
String respContent = "未知的消息类型!";
try {
// 调用parseXml方法解析请求消息
Map 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;
}
}
而后部署到咱们的BAE上面,体验一下。(部署方法请参照 第二篇 :微信公众平台开发实战之开启开发者模式,接入微信公众平台开发)。
效果以下: