在上一篇文章中,咱們實現了文本消息的接收與響應。能夠在用戶發送任何內容的時候,回覆一段固定的文字。本章節中,咱們將對上一章節的代碼進行適當的完善,同時實現【被關注回覆與關鍵詞回覆】功能。html
一、微信可提供的消息類型java
在上一篇文章中,在咱們的Servalet中,咱們有這樣的一段代碼:微信
咱們說這是用於判斷接收的消息類型是否爲text,便是否爲文本消息時,將用戶發送的給信息拼接後返回。但這個這個功能如今不足以知足咱們的時候,咱們將重寫代碼,實現被關注時自動回覆,以及根據關鍵詞自動回覆。而首先,咱們須要瞭解微信公衆平臺支持的消息類型以及對應的事件關鍵字:app
1、可接收消息類型:微信公衆平臺
文本消息——text,語音消息——voice,圖片消息——image,框架
視頻消息——video,連接消息——link,位置消息——location,dom
消息視頻消息——shortvideo,ide
二、支持的事件推送——event工具
關注——subscribe,取消關注——unsubscribe,上傳地理位置——location學習
菜單點擊——點擊菜單獲取消息時觸發click/點擊菜單跳轉連接時觸發view
掃描帶參數二維碼——未關注時觸發subscribe/已關注時觸發scan
那咱們能夠清楚的看到,微信可接收的消息類型以及可觸發的事件類型有不少種,而每種類型都對應着詳細的XML包,在微信公衆平臺開發文檔中有詳細解析,此處不作贅述,詳情可參考開發文檔內容:
可接受消息類型:
http://mp.weixin.qq.com/wiki/10/79502792eef98d6e0c6e1739da387346.html
可支持事件類型:
http://mp.weixin.qq.com/wiki/2/5baf56ce4947d35003b86a9805634b1e.html
2、實現被關注自動回覆
根據上述消息類型的描述,咱們能夠重寫一下咱們上週的MessageUtil類,讓咱們的工具類能夠提供更完善的功能:
一、根據消息類型,提供各類常量:
在咱們的工具類中提供各類常量,方便在使用不一樣消息類型的時候,能夠直接調用:
二、修改Servlet中的文本消息判斷方式
有了這樣的一些常量呢,咱們就須要將上週判斷文本消息的代碼,替換爲用常量判斷
替換爲
同時,添加一種類型判斷,判斷接收的消息類型,是否爲事件類型,添加完後,if-else結構框架以下:
而在傳入事件過程當中,咱們知道又細分爲關注、取消關注、點擊菜單等多種功能,那如何細分呢?咱們能夠在else if 中繼續作判斷,經過咱們上週將xml轉換爲的map中,直接get(「Event」),從而取到詳細的事件類型,而後能夠進一步判斷事件爲subscribe仍是unsubscribe等,詳細以下:
經過上述if結構,咱們能夠精確的判斷到關注時所觸發的事件,也就是說咱們能夠在用戶關注時,推送一條消息主菜單,那麼咱們須要在MessageUtil類中,新建兩個方法:
3、撰寫拼接主菜單方法&初始化消息方法
① 拼接主菜單方法,此方法比較簡單,只是簡單地字符串拼接,方便後期頻繁使用:
② 初始化消息方法,此方法用於傳入接收用戶、發送用戶、消息內容,進而進行拼接組裝,並轉換爲XML結構:
完成上述兩個方法後,咱們就能夠在用戶關注的if結構中,調用initText方法,傳入咱們拼接的主菜單,在用戶關注時,推送咱們的功能主菜單:
截止到這,咱們就完成了用戶關注時,推送主菜單的功能,實現效果以下:
三、實現關鍵詞自動回覆
有了上述關注自動回覆的基礎,咱們再實現關鍵詞自動回覆,就會很是的簡單,只須要在原始判斷消息類型爲Text的if條件中,繼續進行二次判斷,判斷用戶發送的消息爲「1」、「2」、「?」仍是其餘內容,固然爲了更好地體驗,咱們斷定中英文?均會調出主菜單,詳細實現代碼以下:
經過上述代碼,咱們就順利的完成了關鍵詞回覆功能,詳細實現效果以下:
至此,咱們本篇文章的「被關注回覆與關鍵詞回覆」功能就已經介紹並開發完畢。同窗們可下載源碼或加入傑瑞教育開發交流QQ羣(452379712),進行進一步的學習交流。
【附】源碼參考:
一、MessageUtil類:
package com.jredu.util;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import com.jredu.entity.TextMessage;
import com.thoughtworks.xstream.XStream;
public class MessageUtil {
public static final String MESSAGE_TEXT = "text";
public static final String MESSAGE_IMAGE = "image";
public static final String MESSAGE_VOICE = "voice";
public static final String MESSAGE_VIDEO = "video";
public static final String MESSAGE_SHORTVIDEO = "shortvideo";
public static final String MESSAGE_LINK = "link";
public static final String MESSAGE_LOCATION = "location";
public static final String MESSAGE_EVENT = "event";
public static final String MESSAGE_SUBSCRIBE = "subscribe";
public static final String MESSAGE_UNSUBSCRIBE = "unsubscribe";
public static final String MESSAGE_CLICK = "CLICK";
public static final String MESSAGE_VIEW = "VIEW";
public static final String MESSAGE_SCAN = "SCAN";
/**
* 將XML轉爲MAP集合
* @param request
* @return
* @throws IOException
* @throws DocumentException
*/
public static Map<String , String> xmlToMap(HttpServletRequest request) throws IOException, DocumentException{
Map<String , String> map = new HashMap<String, String>();
SAXReader reader = new SAXReader();
//從request對象中獲取輸入流
InputStream ins = request.getInputStream();
//使用reader對象讀取輸入流,解析爲XML文檔
Document doc = reader.read(ins);
//獲取XML根元素
Element root = doc.getRootElement();
//將根元素的全部節點,放入列表中
List<Element> list = root.elements();
//遍歷list對象,並保存到集合中
for (Element element : list) {
map.put(element.getName(), element.getText());
}
ins.close();
return map;
}
/**
* 將文本消息對象轉成XML
* @param text
* @return
*/
public static String textMessageToXml(TextMessage textMessage){
XStream xstream = new XStream();
//將xml的根節點替換成<xml> 默認爲TextMessage的包名
xstream.alias("xml", textMessage.getClass());
return xstream.toXML(textMessage);
}
/**
* 拼接關注主菜單
*/
public static String menuText(){
StringBuffer sb = new StringBuffer();
sb.append("歡迎關注史上最帥公衆號,請選擇:\n\n");
sb.append("一、姜浩真帥。\n");
sb.append("二、姜浩並不帥。\n\n");
sb.append("回覆?調出主菜單。\n\n");
return sb.toString();
}
/**
* 初始化回覆消息
*/
public static String initText(String toUSerName,String fromUserName,String content){
TextMessage text = new TextMessage();
text.setFromUserName(toUSerName);
text.setToUserName(fromUserName);
text.setMsgType(MESSAGE_TEXT);
text.setCreateTime(new Date().getTime()+"");
text.setContent(content);
return MessageUtil.textMessageToXml(text);
}
}
2、Servlet中的doPost方法:
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
try {
Map<String , String> map = MessageUtil.xmlToMap(request);
String ToUserName = map.get("ToUserName");
String FromUserName = map.get("FromUserName");
String CreateTime = map.get("CreateTime");
String MsgType = map.get("MsgType");
String Content = map.get("Content");
String MsgId = map.get("MsgId ");
String message = null;
if (MsgType.equals(MessageUtil.MESSAGE_TEXT)) {//判斷是否爲文本消息類型
if (Content.equals("1")) {
message = MessageUtil.initText(ToUserName, FromUserName,
"對啊!我也是這麼以爲!姜浩帥哭了!");
} else if(Content.equals("2")){
message = MessageUtil.initText(ToUserName, FromUserName,
"好可憐啊!你年級輕輕地就瞎了!");
} else if(Content.equals("?") || Content.equals("?")){
message = MessageUtil.initText(ToUserName, FromUserName,
MessageUtil.menuText());
} else {
message = MessageUtil.initText(ToUserName, FromUserName,
"沒讓你選的就別瞎嘚瑟!!!");
}
}else if(MsgType.equals(MessageUtil.MESSAGE_EVENT)){//判斷是否爲事件類型
//從集合中,或許是哪種事件傳入
String eventType = map.get("Event");
//關注事件
if (eventType.equals(MessageUtil.MESSAGE_SUBSCRIBE)) {
message = MessageUtil.initText(ToUserName, FromUserName,
MessageUtil.menuText());
}
}
System.out.println(message);
out.print(message);
} catch (DocumentException e) {
e.printStackTrace();
}finally{
out.close();
}