天天看點

三、微信公衆号開發--闡述消息的處理與接收流程

前言

        微信在接到消息後,會想設定好的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格式的字元串,返還給微信服務端,微信服務端解析資料之後再傳遞給用戶端展示;

        在這個控制類中,我們做了幾乎所有微信消息類型和事件推送類型的判斷,并分别開啟了相應的服務來處理這些問題,是以這個控制類寫好之後,一般後面開發的過程中需求再怎麼變,業務再怎麼增加,這個類都不太會改變的。

        這就是處理微信公衆号消息的全過程,至于具體的處理,下一章我以一個文本消息處理的案例進行解釋;

繼續閱讀