舒適提示:html
這篇文章是依賴前幾篇的文章的。java
第一篇:微信公衆平臺開發實戰之瞭解微信公衆平臺基礎知識以及資料準備緩存
第二篇 :微信公衆平臺開發實戰之開啓開發者模式,接入微信公衆平臺開發服務器
第三篇 :微信公衆平臺開發實戰之請求消息,響應消息以及事件消息類的封裝微信
首先,咱們看看原來寫的dopost方法:微信公衆平臺
/** * 處理微信服務器發來的消息 */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO 消息的接收、處理、響應 }
doPost方法有兩個參數:框架
1.request中封裝了請求相關的全部內容,能夠從request中取出微信服務器發來的消息;dom
2.response咱們能夠對接收到的消息進行響應,即發送消息。ide
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 </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); } }
使用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(); } }
使用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; } }
而後部署到咱們的BAE上面,體驗一下。(部署方法請參照 第二篇 :微信公衆平臺開發實戰之開啓開發者模式,接入微信公衆平臺開發)。
效果以下:
其餘文章關聯:
第一篇:微信公衆平臺開發實戰Java版之瞭解微信公衆平臺基礎知識以及資料準備
第二篇 :微信公衆平臺開發實戰Java版之開啓開發者模式,接入微信公衆平臺開發
第三篇 :微信公衆平臺開發實戰Java版之請求消息,響應消息以及事件消息類的封裝
第四篇 :微信公衆平臺開發實戰Java版之完成消息接受與相應以及消息的處理
第五篇 :微信公衆平臺開發實戰Java版之如何獲取公衆號的access_token以及緩存access_token
第六篇 :微信公衆平臺開發實戰Java版之如何自定義微信公衆號菜單
第七篇 :微信公衆平臺開發實戰Java版之如何獲取微信用戶基本信息
第八篇 :微信公衆平臺開發實戰Java版之如何網頁受權獲取用戶基本信息