1 package com.zone.weixin4j.dispatcher;
2
3 import com.zone.weixin4j.annotation.WxMessageHandler;
4 import com.zone.weixin4j.annotation.WxMessageInterceptor;
5 import com.zone.weixin4j.exception.HttpResponseException;
6 import com.zone.weixin4j.exception.MessageInterceptorException;
7 import com.zone.weixin4j.exception.WeixinException;
8 import com.zone.weixin4j.handler.DebugMessageHandler;
9 import com.zone.weixin4j.handler.WeixinMessageHandler;
10 import com.zone.weixin4j.interceptor.WeixinMessageInterceptor;
11 import com.zone.weixin4j.request.WeixinMessage;
12 import com.zone.weixin4j.request.WeixinRequest;
13 import com.zone.weixin4j.response.BlankResponse;
14 import com.zone.weixin4j.response.WeixinResponse;
15 import com.zone.weixin4j.service.WeiXin4jContextAware;
16 import com.zone.weixin4j.service.context.WeiXin4jContextAwareImpl;
17 import com.zone.weixin4j.socket.WeixinMessageTransfer;
18 import com.zone.weixin4j.util.ServerToolkits;
19 import com.zone.weixin4j.xml.MessageTransferHandler;
20 import org.apache.commons.logging.Log;
21 import org.apache.commons.logging.LogFactory;
22 import org.springframework.beans.factory.annotation.Autowired;
23 import org.springframework.context.annotation.DependsOn;
24 import org.springframework.stereotype.Component;
25
26 import javax.annotation.PostConstruct;
27 import javax.xml.bind.JAXBContext;
28 import javax.xml.bind.JAXBElement;
29 import javax.xml.bind.JAXBException;
30 import javax.xml.bind.Unmarshaller;
31 import javax.xml.transform.Source;
32 import javax.xml.transform.stream.StreamSource;
33 import java.io.ByteArrayInputStream;
34 import java.util.*;
35 import java.util.concurrent.ConcurrentHashMap;
36
37
38
39
40
41
42
43
44
45
46 @Component
47 @DependsOn({"weiXin4jContextAware"})
48 public class WeixinMessageDispatcher {
49
50 @Autowired
51 private WeiXin4jContextAware weiXin4jContextAware;
52
53 private final Log logger = LogFactory.getLog(getClass());
54
55
56
57
58 private List<WeixinMessageHandler> messageHandlerList = new ArrayList<WeixinMessageHandler>();
59 private WeixinMessageHandler[] messageHandlers;
60
61
62
63
64 private List<WeixinMessageInterceptor> messageInterceptorList = new ArrayList<WeixinMessageInterceptor>();
65 private WeixinMessageInterceptor[] messageInterceptors;
66
67
68
69
70 private WeixinMessageMatcher messageMatcher;
71
72
73
74 private Map<Class<? extends WeixinMessage>, Unmarshaller> messageUnmarshaller;
75
76
77
78 private boolean alwaysResponse;
79
80 public WeixinMessageDispatcher() {
81 this(new DefaultMessageMatcher());
82 }
83
84 public WeixinMessageDispatcher(WeixinMessageMatcher messageMatcher) {
85 this.messageMatcher = messageMatcher;
86 this.messageUnmarshaller = new ConcurrentHashMap<Class<? extends WeixinMessage>, Unmarshaller>();
87 }
88
89 @PostConstruct
90 public void init() {
91 try {
92 this.getMessageHandlers();
93 this.getMessageInterceptors();
94 if (weiXin4jContextAware.isOpenAlwaysResponse()) {
95 this.openAlwaysResponse();
96 }
97 if (weiXin4jContextAware.isUseDebugMessageHandler()) {
98 if(null == messageHandlerList){
99 messageHandlerList = new ArrayList<WeixinMessageHandler>();
100 messageHandlerList.add(DebugMessageHandler.global);
101 }
102 }
103 this.messageMatcher = weiXin4jContextAware.getWeixinMessageMatcher() == null ? new DefaultMessageMatcher() : weiXin4jContextAware.getWeixinMessageMatcher();
104 this.messageUnmarshaller = new ConcurrentHashMap<Class<? extends WeixinMessage>, Unmarshaller>();
105 } catch (Exception e) {
106 e.printStackTrace();
107 }
108 }
109
110
111
112
113
114
115
116 public WeixinResponse doDispatch(final WeixinRequest request) throws WeixinException, HttpResponseException, MessageInterceptorException {
117 WeixinMessageTransfer messageTransfer = MessageTransferHandler.parser(request);
118 WeiXin4jContextAwareImpl.getWeixinMessageTransfer().set(messageTransfer);
119 WeixinMessageKey messageKey = defineMessageKey(messageTransfer, request);
120 Class<? extends WeixinMessage> targetClass = messageMatcher.match(messageKey);
121 WeixinMessage message = messageRead(request.getOriginalContent(), targetClass);
122 logger.info(String.format("define %s matched %s", messageKey, targetClass));
123 MessageHandlerExecutor handlerExecutor = getHandlerExecutor(request, messageKey, message, messageTransfer.getNodeNames());
124 if (handlerExecutor == null || handlerExecutor.getMessageHandler() == null) {
125 return noHandlerFound(request, message);
126 }
127 if (!handlerExecutor.applyPreHandle(request, message)) {
128 throw new MessageInterceptorException(" Interceptor Not Accept !! ");
129 }
130 Exception exception = null;
131 WeixinResponse response = null;
132 try {
133 response = handlerExecutor.getMessageHandler().doHandle(request, message, messageTransfer.getNodeNames());
134 handlerExecutor.applyPostHandle(request, response, message);
135 } catch (Exception e) {
136 exception = e;
137 }
138 handlerExecutor.triggerAfterCompletion(request, response, message, exception);
139 return response;
140 }
141
142
143
144
145
146
147
148
149 protected WeixinMessageKey defineMessageKey(
150 WeixinMessageTransfer messageTransfer, WeixinRequest request) {
151 return new WeixinMessageKey(messageTransfer.getMsgType(),
152 messageTransfer.getEventType(),
153 messageTransfer.getAccountType());
154 }
155
156
157
158
159
160
161
162 protected WeixinResponse noHandlerFound(WeixinRequest request, WeixinMessage message) throws HttpResponseException {
163 logger.warn(String.format("no handler found for %s", request));
164 if (alwaysResponse) {
165 return BlankResponse.global;
166 } else {
167 throw new HttpResponseException(HttpResponseException.HttpResponseStatus.NOT_FOUND);
168 }
169 }
170
171
172
173
174
175
176
177
178
179
180
181
182 protected MessageHandlerExecutor getHandlerExecutor(
183 WeixinRequest request,
184 WeixinMessageKey messageKey, WeixinMessage message,
185 Set<String> nodeNames) throws WeixinException {
186 WeixinMessageHandler[] messageHandlers = getMessageHandlers();
187 if (messageHandlers == null) {
188 return null;
189 }
190 logger.info(String.format("resolve message handlers %s", this.messageHandlerList));
191 List<WeixinMessageHandler> matchedMessageHandlers = new ArrayList<WeixinMessageHandler>();
192 for (WeixinMessageHandler handler : messageHandlers) {
193 if (handler.canHandle(request, message, nodeNames)) {
194 matchedMessageHandlers.add(handler);
195 }
196 }
197 if (matchedMessageHandlers.isEmpty()) {
198 return null;
199 }
200 Collections.sort(matchedMessageHandlers,
201 new Comparator<WeixinMessageHandler>() {
202 @Override
203 public int compare(WeixinMessageHandler m1,
204 WeixinMessageHandler m2) {
205 return m2.weight() - m1.weight();
206 }
207 });
208 logger.info(String.format("matched message handlers %s", matchedMessageHandlers));
209 return new MessageHandlerExecutor(matchedMessageHandlers.get(0), getMessageInterceptors());
210 }
211
212
213
214
215
216
217
218
219 public WeixinMessageHandler[] getMessageHandlers() throws WeixinException {
220 if (this.messageHandlers == null) {
221 String[] beanNamesForAnnotation = this.weiXin4jContextAware.getApplicationContext().getBeanNamesForAnnotation(WxMessageHandler.class);
222 for (String str : beanNamesForAnnotation) {
223 Object bean = this.weiXin4jContextAware.getApplicationContext().getBean(str);
224 if (bean instanceof WeixinMessageHandler) {
225 this.messageHandlerList.add((WeixinMessageHandler) this.weiXin4jContextAware.getApplicationContext().getBean(str));
226 }
227 }
228 }
229 if (messageHandlerList != null && !this.messageHandlerList.isEmpty()) {
230 this.messageHandlers = this.messageHandlerList.toArray(new WeixinMessageHandler[this.messageHandlerList.size()]);
231 }
232 return this.messageHandlers;
233 }
234
235
236
237
238
239
240
241 public WeixinMessageInterceptor[] getMessageInterceptors()
242 throws WeixinException {
243 if (this.messageInterceptors == null) {
244 String[] beanNamesForAnnotation = this.weiXin4jContextAware.getApplicationContext().getBeanNamesForAnnotation(WxMessageInterceptor.class);
245 for (String str : beanNamesForAnnotation) {
246 Object bean = this.weiXin4jContextAware.getApplicationContext().getBean(str);
247 if (bean instanceof WeixinMessageInterceptor) {
248 this.messageInterceptorList.add((WeixinMessageInterceptor) this.weiXin4jContextAware.getApplicationContext().getBean(str));
249 }
250 }
251 }
252 if (this.messageInterceptorList != null && !this.messageInterceptorList.isEmpty()) {
253 Collections.sort(messageInterceptorList,
254 new Comparator<WeixinMessageInterceptor>() {
255 @Override
256 public int compare(WeixinMessageInterceptor m1, WeixinMessageInterceptor m2) {
257 return m2.weight() - m1.weight();
258 }
259 });
260 this.messageInterceptors = this.messageInterceptorList.toArray(new WeixinMessageInterceptor[this.messageInterceptorList.size()]);
261 }
262 logger.info(String.format("resolve message interceptors %s", this.messageInterceptorList));
263 return this.messageInterceptors;
264 }
265
266
267
268
269
270
271
272
273
274 protected <M extends WeixinMessage> M messageRead(String message,
275 Class<M> clazz) throws WeixinException {
276 if (clazz == null) {
277 return null;
278 }
279 try {
280 Source source = new StreamSource(new ByteArrayInputStream(
281 ServerToolkits.getBytesUtf8(message)));
282 JAXBElement<M> jaxbElement = getUnmarshaller(clazz).unmarshal(
283 source, clazz);
284 return jaxbElement.getValue();
285 } catch (JAXBException e) {
286 throw new WeixinException(e);
287 }
288 }
289
290
291
292
293
294
295
296
297 protected Unmarshaller getUnmarshaller(Class<? extends WeixinMessage> clazz)
298 throws WeixinException {
299 Unmarshaller unmarshaller = messageUnmarshaller.get(clazz);
300 if (unmarshaller == null) {
301 try {
302 JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
303 unmarshaller = jaxbContext.createUnmarshaller();
304 messageUnmarshaller.put(clazz, unmarshaller);
305 } catch (JAXBException e) {
306 throw new WeixinException(e);
307 }
308 }
309 return unmarshaller;
310 }
311
312 public void setMessageHandlerList(
313 List<WeixinMessageHandler> messageHandlerList) {
314 this.messageHandlerList = messageHandlerList;
315 }
316
317 public void setMessageInterceptorList(
318 List<WeixinMessageInterceptor> messageInterceptorList) {
319 this.messageInterceptorList = messageInterceptorList;
320 }
321
322 public void registMessageClass(WeixinMessageKey messageKey,
323 Class<? extends WeixinMessage> messageClass) {
324 messageMatcher.regist(messageKey, messageClass);
325 }
326
327 public WeixinMessageMatcher getMessageMatcher() {
328 return this.messageMatcher;
329 }
330
331
332
333
334 public void openAlwaysResponse() {
335 this.alwaysResponse = true;
336 }
337 }