由于微信服务器发送过来的消息分为文本消息、事件消息、图片消息、声音消息、链接消息、位置消息,处理不同的消息
需要不同的处理方式,但是基本流程差不多,所以我设计了一个处理链,不同的消息由不同的消息处理器来处理,达到可扩展性
和维护性的利好。设计一个处理消息的接口MessageHandler
/**
* 处理消息的抽象接口,责任链模式
* @author xsy
*
*/
public interface MessageHandler {
/**
* 该你处理就处理消息的函数
* @param requestMap
* @return
*/
public abstract BaseMessage handleMessage(Map<String, String> requestMap);
/**
* 设置你不能处理后续处理的对象
* @param messageHandler
*/
public abstract void setNextMessageHandler(MessageHandler nextMessageHandler);
}
其中handleMessage是消息处理器的核心方法,用于处理公众号的消息。requestMap用于封装接收到的消息的信息。
BaseMessage是一个JavaBean,是所有响应消息的基类。setNextMessageHandler用于设置下游处理器。
/**
* 消息基类(公众帐号-> 普通用户)
*
* @author 熊诗言
* @date 2015-09-05
*/
public class BaseMessage {
// 接收方帐号(收到的OpenID)
private String ToUserName;
// 开发者微信号
private String FromUserName;
// 消息创建时间(整型)
private long CreateTime;
// 消息类型(text/music/news)
private String MsgType;
// 位0x0001 被标志时,星标刚收到的消息
private int FuncFlag;
。。。。
}
又由于所有的处理器的基本处理流程是一致的,所以利用模板方法设计模式将基本的处理流程抽取形成DefaultMessageHandler,
子类的消息处理器只需要给出你能处理的消息的条件(canDo方法提供)和你的具体处理方法(handleByMe方法给出)即可。
以后要扩展自己的消息处理器只需要继承该类就行了。
public abstract class DefaultMessageHandler implements MessageHandler {
protected MessageHandler nextMessageHandler;
private MessageHandler finalMessageHandler;
// 发送方帐号(open_id)
protected String fromUserName ;
// 公众帐号
protected String toUserName ;
public DefaultMessageHandler() {
this.finalMessageHandler = FinalMessageHandler.sharedFinalMessageHandler();//默认的最终处理器,自己也可以通过setter方法改变
}
public void setFinalMessageHandler(MessageHandler finalMessageHandler) {
this.finalMessageHandler = finalMessageHandler;
}
/**
* 模板方法模式实现主要的逻辑,是自己处理还是交给下游处理
*/
public BaseMessage handleMessage(Map<String, String> requestMap) {
// 发送方帐号(open_id)
fromUserName = requestMap.get("FromUserName");
// 公众帐号
toUserName = requestMap.get("ToUserName");
if(canDo(requestMap)){
/*try {
return handleByMe(requestMap);
} catch (Exception e) {
e.printStackTrace();
requestMap.put("error", e.fillInStackTrace().toString());
return finalMessageHandler.handleMessage(requestMap);
}*/
return handleByMe(requestMap);
}else {
return nextMessageHandler.handleMessage(requestMap);
}
}
public void setNextMessageHandler(MessageHandler nextMessageHandler) {
this.nextMessageHandler = nextMessageHandler;
}
/**
* 给出你处理的条件
* @return
*/
public abstract boolean canDo(Map<String, String> requestMap);
/**
* 你具体的处理
* @param requestMap
* @return
*/
public abstract BaseMessage handleByMe(Map<String, String> requestMap);
}
FinalMessageHandler是最终的默认处理器,表示你的处理链处理不了了我的最终处理办法。由于全系统只需要一个这种处理器,所以设计成单例模式。
/**
* 其他消息处理类处理不了的请求全部有这个类处理,返回一个失败信息
* @author 熊诗言
*
*/
public class FinalMessageHandler extends DefaultMessageHandler {
private static final FinalMessageHandler _instance = new FinalMessageHandler();
private FinalMessageHandler(){}
public static FinalMessageHandler sharedFinalMessageHandler(){
return _instance;
}
@Override
public boolean canDo(Map<String, String> requestMap) {
return true;
}
@Override
public BaseMessage handleByMe(Map<String, String> requestMap) {
return MessageFactory.createTextMessage(fromUserName, toUserName,
"sorry,你发送的什么玩意儿,我处理不了,抱歉!!\n"+requestMap.get("error"));
}
}
下面画一个UML图大体上表达一下意思:
有了以上的处理器之后,就可以构建我们的消息处理器链了
/**
* 核心服务类
*
* @author 熊诗言
* @date 2015-09-05
*/
public class WeiXinService {
/**
* 处理微信发来的请求,利用责任链模式和模板方法模式设计
*
* @param request
* @return
*/
public static String processRequest3(HttpServletRequest request) {
BaseMessage message= null;
try {
// xml 请求解析
Map<String, String> requestMap = MessageUtil.parseXml(request);
//构造一个处理所有消息的链
TextMessageHandler textMessageHandler = TextMessageHandler.sharedTextMessageHandler();
EventMessageHandler eventMessageHandler = new EventMessageHandler();
ImageMessageHandler imageMessageHandler = new ImageMessageHandler();
VoiceMessageHandler voiceMessageHandler = new VoiceMessageHandler();
LinkTextMessageHandler linkTextMessageHandler = new LinkTextMessageHandler();
LocationMessageHandler locationMessageHandler = new LocationMessageHandler();
FinalMessageHandler finalMessageHandler = FinalMessageHandler.sharedFinalMessageHandler();
textMessageHandler.setNextMessageHandler(eventMessageHandler);
eventMessageHandler.setNextMessageHandler(imageMessageHandler);
imageMessageHandler.setNextMessageHandler(voiceMessageHandler);
voiceMessageHandler.setNextMessageHandler(linkTextMessageHandler);
linkTextMessageHandler.setNextMessageHandler(locationMessageHandler);
locationMessageHandler.setNextMessageHandler(finalMessageHandler);
message = textMessageHandler.handleMessage(requestMap);
}catch (Exception e) {
System.out.println(e);
}
return MessageUtil.messageToXml(message);
}
//对比以下的两种处理方式,很明显更优雅,具备更好的可维护性。
/**
* 处理微信发来的请求,系统架构更好了
*
* @param request
* @return
*/
@Deprecated
public static String processRequest2(HttpServletRequest request) {
BaseMessage message= null;
try {
// xml 请求解析
Map<String, String> requestMap = MessageUtil.parseXml(request);
//通过dispatchService分发给不同的service返回不同的消息
message = DispatchService.dispatch(requestMap);
}catch (Exception e) {
System.out.println(e);
}
return MessageUtil.messageToXml(message);
}
/**
* 处理微信发来的请求
*
* @param request
* @return
*/
@Deprecated
public static String processRequest(HttpServletRequest request) {
String respMessage = null;
try {
// 默认返回的文本消息内容
String respContent = "功能还未开发,敬请期待!";
// xml 请求解析
Map<String, String> requestMap = MessageUtil.parseXml(request);
// 发送方帐号(open_id)
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);
textMessage.setFuncFlag(0);
// 文本消息
if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {
/**
* 以后在这里着墨应该是最多的,做聊天机器人啊 根据用户的回复关键词做相应的服务啊 比如实现音乐回复
*/
String content = requestMap.get("Content");
if(ContentUtil.isQqFace(content)){
respContent = content;
}else if("?".equals(content)){
respContent = ContentUtil.getMainTips();
}else if("历史上的今天".equals(content)){
respContent = TodayInHistoryService.getTodayInHistoryInfo();
}else if(content.startsWith("翻译")){
String keyWord = content.replaceFirst("^翻译", "");//真正需要翻译的东西
if ("".equals(keyWord)) {
respContent = ContentUtil.getTranslateUsage();//如果为空就返回提示
}else{
respContent = BaiduTranslateService.translate(keyWord);
}
}else {
respContent = "您发送的是文本消息!自行车\ue136 男人\ue138 钱袋\ue12f 情侣\ue428 公共汽车\ue159";
}
}
// 图片消息
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) {
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_VOICE)) {
respContent = "您发送的是音频消息!";
}
// 事件推送
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {
// 事件类型
String eventType = requestMap.get("Event");
// 订阅
if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {
respContent = ContentUtil.getMainTips();
}
// 取消订阅
else if (eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) {
// TODO 取消订阅后用户再收不到公众号发送的消息,因此不需要回复消息
}
// 自定义菜单点击事件
else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {
// TODO 自定义菜单权没有开放,暂不处理该类消息
}
}
textMessage.setContent(respContent);
respMessage = MessageUtil.textMessageToXml(textMessage);
} catch (Exception e) {
e.printStackTrace();
}
return respMessage;
}
}
/**
* 作为分派service,传过来不同的消息由不同的service做处理,以后设计成责任链模式
* @author xsy
*
*/
public class DispatchService {
public static BaseMessage dispatch(Map<String, String> requestMap){
BaseMessage message = null;
// 发送方帐号(open_id)
String fromUserName = requestMap.get("FromUserName");
// 公众帐号
String toUserName = requestMap.get("ToUserName");
// 消息类型
String msgType = requestMap.get("MsgType");
// 文本消息
if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {
/**
* 以后在这里着墨应该是最多的,做聊天机器人啊 根据用户的回复关键词做相应的服务啊 比如实现音乐回复
*/
String content = requestMap.get("Content").trim();
if(ContentUtil.isQqFace(content)){
message = MessageFactory.createTextMessage(fromUserName, toUserName,content);
}else if("?".equals(content)){
message = MessageFactory.createTextMessage(fromUserName, toUserName, ContentUtil.getMainTips());
}else if("历史上的今天".equals(content)){
message = MessageFactory.createTextMessage(fromUserName, toUserName, TodayInHistoryService.getTodayInHistoryInfo());
}else if(content.startsWith("翻译")){
String keyWord = content.replaceFirst("^翻译", "");//真正需要翻译的东西
if ("".equals(keyWord)) {
message = MessageFactory.createTextMessage(fromUserName, toUserName, ContentUtil.getTranslateUsage());//如果为空就返回提示
}else{
message = MessageFactory.createTextMessage(fromUserName, toUserName, BaiduTranslateService.translate(keyWord));
}
}else if(content.startsWith("歌曲")){
// 将歌曲2 个字及歌曲后面的+、空格、-等特殊符号去掉
String keyWord = content.replaceAll("^歌曲[\\+ ~!@#%^-_=]?", "");
// 如果歌曲名称为空
if ("".equals(keyWord)) {
message = MessageFactory.createTextMessage(fromUserName, toUserName, ContentUtil.getMusicUsage());
} else {
String[] kwArr = keyWord.split("@");
// 歌曲名称
String musicTitle = kwArr[0];
// 演唱者默认为空
String musicAuthor = "";
if (2 == kwArr.length)
musicAuthor = kwArr[1];
// 搜索音乐
Music music = BaiduMusicService.searchMusic(musicTitle, musicAuthor);
// 未搜索到音乐
if (null == music) {
message = MessageFactory.createTextMessage(fromUserName, toUserName,
"对不起,没有找到你想听的歌曲<" + musicTitle + ">。");
} else {
message = MessageFactory.createMusicMessage(fromUserName, toUserName, music);
}
}
}else {//作为最终的聊天机器人
message = MessageFactory.createTextMessage(fromUserName, toUserName,
"您发送的是文本消息!自行车\ue136 男人\ue138 钱袋\ue12f 情侣\ue428 公共汽车\ue159");
}
}
// 图片消息
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_IMAGE)) {
message = MessageFactory.createTextMessage(fromUserName, toUserName,"您发送的是图片消息!");
}
// 地理位置消息
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LOCATION)){
message = MessageFactory.createTextMessage(fromUserName, toUserName,"您发送的是地理位置消息!");
}
// 链接消息
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_LINK)) {
message = MessageFactory.createTextMessage(fromUserName, toUserName,"您发送的是链接消息!");
}
// 音频消息
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_VOICE)) {
message = MessageFactory.createTextMessage(fromUserName, toUserName,"您发送的是音频消息!");
}
// 事件推送
else if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_EVENT)) {
// 事件类型
String eventType = requestMap.get("Event");
// 订阅
if (eventType.equals(MessageUtil.EVENT_TYPE_SUBSCRIBE)) {
message = MessageFactory.createTextMessage(fromUserName, toUserName,ContentUtil.getMainTips());
}
// 取消订阅
else if (eventType.equals(MessageUtil.EVENT_TYPE_UNSUBSCRIBE)) {
// TODO 取消订阅后用户再收不到公众号发送的消息,因此不需要回复消息
}
// 自定义菜单点击事件
else if (eventType.equals(MessageUtil.EVENT_TYPE_CLICK)) {
// TODO 自定义菜单权没有开放,暂不处理该类消息
}
}
return message;
}
}