WeixinMessageDispatcher.java
package com.zone.weixin4j.dispatcher;
import com.zone.weixin4j.annotation.WxMessageHandler;
import com.zone.weixin4j.annotation.WxMessageInterceptor;
import com.zone.weixin4j.exception.HttpResponseException;
import com.zone.weixin4j.exception.MessageInterceptorException;
import com.zone.weixin4j.exception.WeixinException;
import com.zone.weixin4j.handler.DebugMessageHandler;
import com.zone.weixin4j.handler.WeixinMessageHandler;
import com.zone.weixin4j.interceptor.WeixinMessageInterceptor;
import com.zone.weixin4j.request.WeixinMessage;
import com.zone.weixin4j.request.WeixinRequest;
import com.zone.weixin4j.response.BlankResponse;
import com.zone.weixin4j.response.WeixinResponse;
import com.zone.weixin4j.service.WeiXin4jContextAware;
import com.zone.weixin4j.service.context.WeiXin4jContextAwareImpl;
import com.zone.weixin4j.socket.WeixinMessageTransfer;
import com.zone.weixin4j.util.ServerToolkits;
import com.zone.weixin4j.xml.MessageTransferHandler;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import java.io.ByteArrayInputStream;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* 微信消息分发器
*
* @author jinyu(foxinmy@gmail.com)
* @className WeixinMessageDispatcher
* @date 2015年5月7日
* @updateBy Yz(174975857@qq.com)
* @since JDK 1.6
*/
@Component
@DependsOn({"weiXin4jContextAware"})
public class WeixinMessageDispatcher {
@Autowired
private WeiXin4jContextAware weiXin4jContextAware;
private final Log logger = LogFactory.getLog(getClass());
/**
* 消息处理器
*/
private List<WeixinMessageHandler> messageHandlerList = new ArrayList<WeixinMessageHandler>();
private WeixinMessageHandler[] messageHandlers;
/**
* 消息拦截器
*/
private List<WeixinMessageInterceptor> messageInterceptorList = new ArrayList<WeixinMessageInterceptor>();
private WeixinMessageInterceptor[] messageInterceptors;
/**
* 消息匹配
*/
private WeixinMessageMatcher messageMatcher;
/**
* 消息转换
*/
private Map<Class<? extends WeixinMessage>, Unmarshaller> messageUnmarshaller;
/**
* 是否总是响应请求,如未匹配到MessageHandler时回复空白消息
*/
private boolean alwaysResponse;
public WeixinMessageDispatcher() {
this(new DefaultMessageMatcher());
}
public WeixinMessageDispatcher(WeixinMessageMatcher messageMatcher) {
this.messageMatcher = messageMatcher;
this.messageUnmarshaller = new ConcurrentHashMap<Class<? extends WeixinMessage>, Unmarshaller>();
}
@PostConstruct
public void init() {
try {
this.getMessageHandlers();
this.getMessageInterceptors();
if (weiXin4jContextAware.isOpenAlwaysResponse()) {
this.openAlwaysResponse();
}
if (weiXin4jContextAware.isUseDebugMessageHandler()) {
if(null == messageHandlerList){
messageHandlerList = new ArrayList<WeixinMessageHandler>();
messageHandlerList.add(DebugMessageHandler.global);
}
}
this.messageMatcher = weiXin4jContextAware.getWeixinMessageMatcher() == null ? new DefaultMessageMatcher() : weiXin4jContextAware.getWeixinMessageMatcher();
this.messageUnmarshaller = new ConcurrentHashMap<Class<? extends WeixinMessage>, Unmarshaller>();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 对消息进行一系列的处理,包括 拦截、匹配、分发等动作
*
* @param request 微信请求
* @throws WeixinException
*/
public WeixinResponse doDispatch(final WeixinRequest request) throws WeixinException, HttpResponseException, MessageInterceptorException {
WeixinMessageTransfer messageTransfer = MessageTransferHandler.parser(request);
WeiXin4jContextAwareImpl.getWeixinMessageTransfer().set(messageTransfer);
WeixinMessageKey messageKey = defineMessageKey(messageTransfer, request);
Class<? extends WeixinMessage> targetClass = messageMatcher.match(messageKey);
WeixinMessage message = messageRead(request.getOriginalContent(), targetClass);
logger.info(String.format("define %s matched %s", messageKey, targetClass));
MessageHandlerExecutor handlerExecutor = getHandlerExecutor(request, messageKey, message, messageTransfer.getNodeNames());
if (handlerExecutor == null || handlerExecutor.getMessageHandler() == null) {
return noHandlerFound(request, message);
}
if (!handlerExecutor.applyPreHandle(request, message)) {
throw new MessageInterceptorException(" Interceptor Not Accept !! ");
}
Exception exception = null;
WeixinResponse response = null;
try {
response = handlerExecutor.getMessageHandler().doHandle(request, message, messageTransfer.getNodeNames());
handlerExecutor.applyPostHandle(request, response, message);
} catch (Exception e) {
exception = e;
}
handlerExecutor.triggerAfterCompletion(request, response, message, exception);
return response;
}
/**
* 声明messagekey
*
* @param messageTransfer 基础消息
* @param request 请求信息
* @return
*/
protected WeixinMessageKey defineMessageKey(
WeixinMessageTransfer messageTransfer, WeixinRequest request) {
return new WeixinMessageKey(messageTransfer.getMsgType(),
messageTransfer.getEventType(),
messageTransfer.getAccountType());
}
/**
* 未匹配到handler时触发
*
* @param request 微信请求
* @param message 微信消息
*/
protected WeixinResponse noHandlerFound(WeixinRequest request, WeixinMessage message) throws HttpResponseException {
logger.warn(String.format("no handler found for %s", request));
if (alwaysResponse) {
return BlankResponse.global;
} else {
throw new HttpResponseException(HttpResponseException.HttpResponseStatus.NOT_FOUND);
}
}
/**
* MessageHandlerExecutor
*
* @param request 微信请求
* @param messageKey 消息的key
* @param message 微信消息
* @param nodeNames 节点名称集合
* @return MessageHandlerExecutor
* @throws WeixinException
* @see MessageHandlerExecutor
*/
protected MessageHandlerExecutor getHandlerExecutor(
WeixinRequest request,
WeixinMessageKey messageKey, WeixinMessage message,
Set<String> nodeNames) throws WeixinException {
WeixinMessageHandler[] messageHandlers = getMessageHandlers();
if (messageHandlers == null) {
return null;
}
logger.info(String.format("resolve message handlers %s", this.messageHandlerList));
List<WeixinMessageHandler> matchedMessageHandlers = new ArrayList<WeixinMessageHandler>();
for (WeixinMessageHandler handler : messageHandlers) {
if (handler.canHandle(request, message, nodeNames)) {
matchedMessageHandlers.add(handler);
}
}
if (matchedMessageHandlers.isEmpty()) {
return null;
}
Collections.sort(matchedMessageHandlers,
new Comparator<WeixinMessageHandler>() {
@Override
public int compare(WeixinMessageHandler m1,
WeixinMessageHandler m2) {
return m2.weight() - m1.weight();
}
});
logger.info(String.format("matched message handlers %s", matchedMessageHandlers));
return new MessageHandlerExecutor(matchedMessageHandlers.get(0), getMessageInterceptors());
}
/**
* 获取所有的handler
*
* @return handler集合
* @throws WeixinException
* @see com.zone.weixin4j.handler.WeixinMessageHandler
*/
public WeixinMessageHandler[] getMessageHandlers() throws WeixinException {
if (this.messageHandlers == null) {
String[] beanNamesForAnnotation = this.weiXin4jContextAware.getApplicationContext().getBeanNamesForAnnotation(WxMessageHandler.class);
for (String str : beanNamesForAnnotation) {
Object bean = this.weiXin4jContextAware.getApplicationContext().getBean(str);
if (bean instanceof WeixinMessageHandler) {
this.messageHandlerList.add((WeixinMessageHandler) this.weiXin4jContextAware.getApplicationContext().getBean(str));
}
}
}
if (messageHandlerList != null && !this.messageHandlerList.isEmpty()) {
this.messageHandlers = this.messageHandlerList.toArray(new WeixinMessageHandler[this.messageHandlerList.size()]);
}
return this.messageHandlers;
}
/**
* 获取所有的interceptor
*
* @return interceptor集合
* @throws WeixinException
*/
public WeixinMessageInterceptor[] getMessageInterceptors()
throws WeixinException {
if (this.messageInterceptors == null) {
String[] beanNamesForAnnotation = this.weiXin4jContextAware.getApplicationContext().getBeanNamesForAnnotation(WxMessageInterceptor.class);
for (String str : beanNamesForAnnotation) {
Object bean = this.weiXin4jContextAware.getApplicationContext().getBean(str);
if (bean instanceof WeixinMessageInterceptor) {
this.messageInterceptorList.add((WeixinMessageInterceptor) this.weiXin4jContextAware.getApplicationContext().getBean(str));
}
}
}
if (this.messageInterceptorList != null && !this.messageInterceptorList.isEmpty()) {
Collections.sort(messageInterceptorList,
new Comparator<WeixinMessageInterceptor>() {
@Override
public int compare(WeixinMessageInterceptor m1, WeixinMessageInterceptor m2) {
return m2.weight() - m1.weight();
}
});
this.messageInterceptors = this.messageInterceptorList.toArray(new WeixinMessageInterceptor[this.messageInterceptorList.size()]);
}
logger.info(String.format("resolve message interceptors %s", this.messageInterceptorList));
return this.messageInterceptors;
}
/**
* jaxb读取微信消息
*
* @param message xml消息
* @param clazz 消息类型
* @return 消息对象
* @throws WeixinException
*/
protected <M extends WeixinMessage> M messageRead(String message,
Class<M> clazz) throws WeixinException {
if (clazz == null) {
return null;
}
try {
Source source = new StreamSource(new ByteArrayInputStream(
ServerToolkits.getBytesUtf8(message)));
JAXBElement<M> jaxbElement = getUnmarshaller(clazz).unmarshal(
source, clazz);
return jaxbElement.getValue();
} catch (JAXBException e) {
throw new WeixinException(e);
}
}
/**
* xml消息转换器
*
* @param clazz 消息类型
* @return 消息转换器
* @throws WeixinException
*/
protected Unmarshaller getUnmarshaller(Class<? extends WeixinMessage> clazz)
throws WeixinException {
Unmarshaller unmarshaller = messageUnmarshaller.get(clazz);
if (unmarshaller == null) {
try {
JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
unmarshaller = jaxbContext.createUnmarshaller();
messageUnmarshaller.put(clazz, unmarshaller);
} catch (JAXBException e) {
throw new WeixinException(e);
}
}
return unmarshaller;
}
public void setMessageHandlerList(
List<WeixinMessageHandler> messageHandlerList) {
this.messageHandlerList = messageHandlerList;
}
public void setMessageInterceptorList(
List<WeixinMessageInterceptor> messageInterceptorList) {
this.messageInterceptorList = messageInterceptorList;
}
public void registMessageClass(WeixinMessageKey messageKey,
Class<? extends WeixinMessage> messageClass) {
messageMatcher.regist(messageKey, messageClass);
}
public WeixinMessageMatcher getMessageMatcher() {
return this.messageMatcher;
}
/**
* 打开总是响应开关,如未匹配到MessageHandler时回复空白消息
*/
public void openAlwaysResponse() {
this.alwaysResponse = true;
}
}