責任鏈模式和工廠模式在處理被動響應訊息中的應用
在公眾號建設中,傳送被動響應訊息是最核心的環節,使用者主動發給微信的訊息經微信伺服器處理後,統一變成xml格式的報文,微信公眾平臺後臺需要對這些報文進行分別處理,然後組織響應報文響應給使用者,同時針對某些特殊操作的行為需要修改資料庫的某些資訊。
綜合來看,微信公眾平臺對上行訊息的處理流程分為以下幾個部分:1)上行訊息入庫;2)資料庫狀態修改;3)返回應答訊息;4)應答訊息入庫。
這四個部分是一個序列流程,很適合用責任鏈模式處理,責任鏈模式的相關內容這裡不仔細講解了(讀者感興趣可以上網去查),它的使用大致可以總結為:1)定義抽象類,例如AbstractMessageHandler,持有自己的引用,定義公用的抽象方法handleMessage();2)定義具體處理類,例如資料庫處理類、狀態處理器類、應答訊息處理器類等,分別整合抽象類,實現各自的處理方法;3)使用時需要制定責任鏈模式前驅物件的後繼物件,才能將下一步操作轉交出去。
(1)責任鏈模式的實際應用如下:
定義抽象類: (可以看到它持有自己的引用)
定義具體實現類之一:訊息入庫/** * * @類名: AbstracMessageHandler.java * @描述:責任鏈模式的抽象處理器 * @作者: mxyanx * @修改日期: 2015年3月2日 */ public abstract class AbstractMessageHandler { protected AbstractMessageHandler successor; public abstract String handleMessage(String requestXmlData,BaseMessage baseMessage,String responseMessage) throws IOException; public AbstractMessageHandler getSuccessor() { return successor; } public void setSuccessor(AbstractMessageHandler successor) { this.successor = successor; } }
/** * * @類名: Message2DBHandler.java * @描述:責任鏈模式處理的第一個環節,專門針對訊息入庫 * @作者: mxyanx * @修改日期: 2015年3月2日 */ @Component public class Message2DBHandler extends AbstractMessageHandler { private static final Logger logger = Logger.getLogger(Message2DBHandler.class); @Override public String handleMessage(String requestXmlData, BaseMessage baseMessage,String responseMessageStr) throws IOException { //資料庫處理 ...... //如果有後繼處理器,則返回下一個處理器的結果 if(this.getSuccessor() != null){ return this.getSuccessor().handleMessage(requestXmlData, baseMessage,responseMessageStr); }else{ return responseMessageStr; } } }
定義具體實現類之二:狀態處理
/**
*
* @類名: MessageStatusHandler.java
* @描述:責任鏈模式處理的第二個環節,專門針對事件型別的訊息修改狀態
* @作者: mxyanx
* @修改日期: 2015年3月2日
*/
@Component
public class MessageStatusHandler extends AbstractMessageHandler
{
private static final Logger logger = Logger.getLogger(<span style="font-family: Arial, Helvetica, sans-serif;">MessageStatusHandler</span>.class);
@Override
public String handleMessage(String requestXmlData, BaseMessage baseMessage,String responseMessageStr) throws IOException
{
//狀態處理
if (baseMessage.getMsgType().equalsIgnoreCase("event"))
{
......
}
//如果有後繼處理器,則返回下一個處理器的結果
if(this.getSuccessor() != null){
return this.getSuccessor().handleMessage(requestXmlData, baseMessage,responseMessageStr);
}else{
return responseMessageStr;
}
}
}
定義具體實現類之三:組織被動響應訊息返回
/**
*
* @類名: MessageResponseHandler.java
* @描述:責任鏈模式處理的第三個環節,組織被動響應訊息
* @作者: mxyanx
* @修改日期: 2015年3月2日
*/
@Component
public class MessageResponseHandler extends AbstractMessageHandler
{
private static final Logger logger = Logger.getLogger(MessageResponseHandler.class);
@Override
public String handleMessage(String requestXmlData, BaseMessage baseMessage,String responseMessageStr) throws IOException
{
//生成被動響應訊息
......
//如果有後繼處理器,則返回下一個處理器的結果
if(this.getSuccessor() != null){
return this.getSuccessor().handleMessage(requestXmlData, baseMessage,responseMessageStr);
}else{
return responseMessageStr;
}
}
}
最後來看看責任鏈模式的初始化呼叫:(設定了每個處理器的後繼者,正是通過父類持有的引用來實現的)
@Service
public class MessageService
{
private Logger logger = Logger.getLogger(MessageService.class);
/**
*
* 功能描述:根據上行訊息返回下行訊息
*
* @param requestXml
* @return
* @throws StreamException
* @throws IOException
*/
public String getResponseXml(String requestXmlData) throws StreamException, IOException
{
String responseMessageStr = StringUtils.EMPTY;
BaseMessage baseMessage = XmlUtil.getBaseMessage(requestXmlData);
AbstractMessageHandler message2DBHandler = new Message2DBHandler();
AbstractMessageHandler messageStatusHandler = new MessageStatusHandler();
AbstractMessageHandler messageResponseHandler = new MessageResponseHandler();
//設定訊息入庫的後繼操作為修改資料庫狀態
message2DBHandler.setSuccessor(messageStatusHandler);
//設定修改資料庫狀態的後繼操作為返回被動響應訊息
messageStatusHandler.setSuccessor(messageResponseHandler);
message2DBHandler.handleMessage(requestXmlData, baseMessage,responseMessageStr);
logger.info("responseMessageStr:"+responseMessageStr);
return responseMessageStr;
}
}
(2)工廠模式的應用
針對使用者上行的不同型別的報文,我們可以用工廠模式返回不同的處理物件,這些處理物件都繼承了同樣的抽象類,重寫了同一個介面方法,從而在具體方法中處理不同的業務邏輯。這裡抽象類的作用是用來抽取公共方法,全部實現過程如下:
定義訊息處理器介面:
/**
*
* @類名: IMessageProcessor.java
* @描述:處理器介面,用來處理不同的應答訊息
* @作者: mxyanx
* @修改日期: 2015年3月3日
*/
public interface IMessageProcessor
{
void process(String requestXmlData, BaseMessage baseMessage,String responseMessageStr) throws IOException;
}
定義抽象類,實現處理器介面,同時定義公共方法:
/**
*
* @類名: PublicProcessor.java
* @描述:訊息公共處理器,提供各種方法供具體處理器呼叫
* @作者: mxyanx
* @修改日期: 2015年3月5日
*/
@Component
public class PublicProcessor implements IMessageProcessor
{
public void process(String requestXmlData, BaseMessage baseMessage, String responseMessageStr) throws IOException
{
// TODO Auto-generated method stub
}
/**
*
* 功能描述:返回被動響應訊息,主要有兩種型別:文字型別和圖文型別
*
* @return
*/
protected String getResMessageById(String messageId, BaseMessage baseMessage)
{
......
}
/**
*
* 功能描述:應答文字訊息入庫
*
* @param content
*/
protected void insertResTextMessage2DB(String content, BaseMessage baseMessage)
{
......
}
/**
*
* 功能描述:應答圖文訊息入庫
*
* @param articleMessageItems
* @param baseMessage
*/
protected void insertResArticleMessage2DB(List<ArticleMessageItem> articleMessageItems, BaseMessage baseMessage)
{
......
}
/**
* click事件訊息型別返回
*
* 功能描述:返回響應給使用者的訊息,主要有兩種型別:文字型別和圖文型別
*
* @return
*/
protected String getResMessageByName(String messageName, BaseMessage baseMessage)
{
......
}
/**
*
* 功能描述:判斷多客服開關是否啟用
* @param baseMessage
* @return
*/
protected boolean getCustomerServiceFlag(String accountId){
......
}
}
定義工廠類,根據使用者上行訊息的內容返回不同的處理器:
/**
*
* @類名: ProcessorFactory.java
* @描述:處理器工廠類,用來返回不同的處理器
* @作者: mxyanx
* @修改日期: 2015年3月3日
*/
public class ProcessorFactory
{
public static IMessageProcessor getProcessorMessage(String msgType)
{
if (msgType.equalsIgnoreCase("text"))
{
return new TextMessageProcessorImpl();
}
else if (msgType.equalsIgnoreCase("location"))
{
return new LocationMessageProcessorImpl();
}
else if (msgType.equalsIgnoreCase("image"))
{
return new ImageMessageProcessorImpl();
}
else if (msgType.equalsIgnoreCase("event"))
{
return new EventMessageProcessorImpl();
}
else
{
return null;
}
}
}
定義具體的處理器類之一:文字訊息處理器
/**
*
* @類名: TextMessageProcessorImpl.java
* @描述:文字訊息處理器,生成應答訊息和應答訊息入庫
* @作者: mxyanx
* @修改日期: 2015年3月5日
*/
@Component
public class TextMessageProcessorImpl extends PublicProcessor
{
private static final Logger logger = Logger.getLogger(TextMessageProcessorImpl.class);
@Override
public void process(String requestXmlData, BaseMessage baseMessage, String responseMessageStr) throws IOException
{
//處理文字訊息,這裡可能用到抽象類中的方法
......
}
}
定義具體的處理器之二:圖片訊息處理器
/**
*
* @類名: ImageMessageProcessorImpl.java
* @描述:圖片訊息處理器,生成應答訊息和應答訊息入庫
* @作者: mxyanx
* @修改日期: 2015年3月5日
*/
@Component
public class ImageMessageProcessorImpl extends PublicProcessor
{
private static final Logger logger = Logger.getLogger(ImageMessageProcessorImpl.class);
@Override
public void process(String requestXmlData, BaseMessage baseMessage, String responseMessageStr) throws IOException
{
//處理圖片訊息,這裡可能用到抽象類中的方法
......
}
}
定義具體的處理器之三:地理位置訊息處理器
/**
*
* @類名: LocationMessageProcessorImpl.java
* @描述:地理位置訊息處理器,生成應答訊息和應答訊息入庫
* @作者: mxyanx
* @修改日期: 2015年3月5日
*/
@Component
public class LocationMessageProcessorImpl extends PublicProcessor
{
private static final Logger logger = Logger.getLogger(ImageMessageProcessorImpl.class);
@Override
public void process(String requestXmlData, BaseMessage baseMessage, String responseMessageStr) throws IOException
{
//處理地理位置訊息,這裡可能用到抽象類中的方法
......
}
}
......
最後,看一下工廠模式是如何呼叫的:
/**
*
* @類名: MessageResponseHandler.java
* @描述:被動響應訊息處理器,專門返回被動響應訊息
* @作者: mxyanx
* @修改日期: 2015年3月2日
*/
@Component
public class MessageResponseHandler extends AbstractMessageHandler
{
@Override
public String handleMessage(String requestXmlData, BaseMessage baseMessage,String responseMessageStr) throws IOException
{
//使用工廠模式,根據訊息型別返回不同的處理器組裝返回訊息
IMessageProcessor messageProcessor = ProcessorFactory.getProcessorMessage(baseMessage.getMsgType());
messageProcessor.process(requestXmlData, baseMessage, responseMessageStr);
//如果有後繼處理器,則返回下一個處理器的結果
if(this.getSuccessor() != null){
return this.getSuccessor().handleMessage(requestXmlData, baseMessage,responseMessageStr);
}else{
return responseMessageStr;
}
}
}
使用上述兩種設計模式,可以使得業務邏輯變得清晰,程式碼的層次感更強,希望上述介紹對讀者有幫助。