前言
微信在接到消息後,會想設定好的url位址發送post形式的請求,開發者隻要接收這個請求,解析之後做出響應的操作,然後按照響應的格式,把資料響應回去就好了。如果響應失敗,微信沒有接收到來自伺服器的響應資訊,或者響應的格式不對的話,前端會出現“目标伺服器服務出現故障”等類似的提示;
正文
首先是程式的入口,在servlet的doPost()方法中來處理這個請求。并傳回響應的xml字元串;
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 調用核心業務類接收消息、處理消息
String respXml = MessageControl.getControl().processMessageRequest(request);
//System.out.println("respxml"+respXml);
// 響應消息
PrintWriter out = response.getWriter();
out.print(respXml);
out.close();
return;
}
邏輯很簡單,因為代碼量很少,就分兩步,先是調用核心業務處理類MessageControl處理消息對象,然後得到的結果通過out流寫出到頁面;
在MessageControl類中,寫的大多是對于消息類型的判斷還有對事件類型的判斷,然後做出響應。
package com.wx.control;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import com.wx.service.ImageMsgService;
import com.wx.service.LinkMsgService;
import com.wx.service.LocationMsgService;
import com.wx.service.MenuService;
import com.wx.service.TextMsgService;
import com.wx.service.VideoMsgService;
import com.wx.service.VoiceMsgService;
import com.wx.service.impl.ImageMsgServiceImpl;
import com.wx.service.impl.LinkMsgServiceImpl;
import com.wx.service.impl.LocationMsgServiceImpl;
import com.wx.service.impl.MenuServiceImpl;
import com.wx.service.impl.TextMsgServiceImpl;
import com.wx.service.impl.VideoMsgServiceImpl;
import com.wx.service.impl.VoiceMsgServiceImpl;
import com.wx.util.MessageUtil;
import life.book.util.LogPersist;
import life.book.util.LogPersist.Path;
import life.book.util.Utils;
/**
* User:Jiahengfei --> [email protected]
* create by 2018年4月29日 from Eclipse.
* describe:消息接收與回應控制器
*/
public class MessageControl implements Path{
private static MessageControl control;
private MessageControl(){}
public static MessageControl getControl(){if(control==null){control=new MessageControl();}return control;}
private TextMsgService text = new TextMsgServiceImpl();
private VideoMsgService video = new VideoMsgServiceImpl();
private ImageMsgService image = new ImageMsgServiceImpl();
private VoiceMsgService link = new VoiceMsgServiceImpl();
private LocationMsgService location = new LocationMsgServiceImpl();
private LinkMsgService voice = new LinkMsgServiceImpl();
private MenuService menu = new MenuServiceImpl();
/**
* 處理微信發來的請求
* @param request
* @return xml
*/
public String processMessageRequest(HttpServletRequest request) {
// xml格式的消息資料
String respXml = null;
try {
// 調用parseXml方法解析請求消息
Map<String, String> map = MessageUtil.parseXml(request);
// 消息類型
String msgType = map.get("MsgType");
//持久化日志
String[] params = {Utils.getTime(),map.get("MsgType"),map.get("FromUserName"),map.get("Content")};
LogPersist.getOperation().log().csv(this, params);
System.out.println("AE:"+map.get("MsgType"));
// 文本消息
if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {
respXml = text.dispose(map);
}
// 圖檔消息
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) {
respXml = image.dispose(map);
}
// 語音消息
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)) {
respXml = voice.dispose(map);
}
// 視訊消息
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VIDEO)) {
respXml = video.dispose(map);
}
// 視訊消息
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_SHORTVIDEO)) {
respXml = video.dispose(map);
}
// 地理位置消息
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)) {
respXml = location.dispose(map);
}
// 連結消息
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)) {
respXml = link.dispose(map);
}
// 事件推送
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {
// 事件類型
String eventType = map.get("Event");
// 關注
if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {
respXml = MessageUtil.Default.text(map, "謝謝你那麼有才華還關注我
}
// 取消關注
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 處理菜單點選事件
String key = map.get("EventKey");
if (key!=null) {
respXml = menu.rstOnclickMenu(key, map);
}
}
}
if (respXml==null) {respXml = MessageUtil.Default.text(map, "您目前發送的資訊暫無法自動識别,已移交客服處理,請等待客服回複,感謝您對我們的支援和了解!");}
} catch (Exception e) {
e.printStackTrace();
}
return respXml;
}
@Override
public String gainPath() {
return LogPersist.getOperation().path("wx/textmsg");
}
}
這個寫的是不不知到抽什麼風了,就是寫出來顯示不全,害我重寫了好幾遍!!!
總結一下,使用者發出資訊之後,先傳遞給微信服務端,微信服務端把消息包裝之後,傳遞給對應的開發者服務端進行資料的處理,開發者服務端接收之後,會對消息進行解析處理,解析成一個map集合,然後對于消息的類型進行判斷,判斷之後響應對應的服務來處理資料,處理結果包裝成一個xml格式的字元串,返還給微信服務端,微信服務端解析資料之後再傳遞給用戶端展示;
在這個控制類中,我們做了幾乎所有微信消息類型和事件推送類型的判斷,并分别開啟了相應的服務來處理這些問題,是以這個控制類寫好之後,一般後面開發的過程中需求再怎麼變,業務再怎麼增加,這個類都不太會改變的。
這就是處理微信公衆号消息的全過程,至于具體的處理,下一章我以一個文本消息處理的案例進行解釋;