| @@ -0,0 +1,19 @@ | |||||
| package me.chanjar.weixin.common.util; | |||||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||||
| import org.slf4j.Logger; | |||||
| import org.slf4j.LoggerFactory; | |||||
| public class LogExceptionHandler implements WxErrorExceptionHandler { | |||||
| private Logger log = LoggerFactory.getLogger(WxErrorExceptionHandler.class); | |||||
| @Override | |||||
| public void handle(WxErrorException e) { | |||||
| log.error("Error happens", e); | |||||
| } | |||||
| } | |||||
| @@ -0,0 +1,12 @@ | |||||
| package me.chanjar.weixin.common.util; | |||||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||||
| /** | |||||
| * WxErrorException处理器 | |||||
| */ | |||||
| public interface WxErrorExceptionHandler { | |||||
| public void handle(WxErrorException e); | |||||
| } | |||||
| @@ -1,5 +1,6 @@ | |||||
| package me.chanjar.weixin.cp.api; | package me.chanjar.weixin.cp.api; | ||||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||||
| import me.chanjar.weixin.common.session.WxSession; | import me.chanjar.weixin.common.session.WxSession; | ||||
| import me.chanjar.weixin.common.session.WxSessionManager; | import me.chanjar.weixin.common.session.WxSessionManager; | ||||
| import me.chanjar.weixin.cp.bean.WxCpXmlMessage; | import me.chanjar.weixin.cp.bean.WxCpXmlMessage; | ||||
| @@ -24,6 +25,6 @@ public interface WxCpMessageHandler { | |||||
| public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, | public WxCpXmlOutMessage handle(WxCpXmlMessage wxMessage, | ||||
| Map<String, Object> context, | Map<String, Object> context, | ||||
| WxCpService wxCpService, | WxCpService wxCpService, | ||||
| WxSessionManager sessionManager); | |||||
| WxSessionManager sessionManager) throws WxErrorException; | |||||
| } | } | ||||
| @@ -1,5 +1,6 @@ | |||||
| package me.chanjar.weixin.cp.api; | package me.chanjar.weixin.cp.api; | ||||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||||
| import me.chanjar.weixin.common.session.WxSessionManager; | import me.chanjar.weixin.common.session.WxSessionManager; | ||||
| import me.chanjar.weixin.cp.bean.WxCpXmlMessage; | import me.chanjar.weixin.cp.bean.WxCpXmlMessage; | ||||
| @@ -24,6 +25,6 @@ public interface WxCpMessageInterceptor { | |||||
| public boolean intercept(WxCpXmlMessage wxMessage, | public boolean intercept(WxCpXmlMessage wxMessage, | ||||
| Map<String, Object> context, | Map<String, Object> context, | ||||
| WxCpService wxCpService, | WxCpService wxCpService, | ||||
| WxSessionManager sessionManager); | |||||
| WxSessionManager sessionManager) throws WxErrorException; | |||||
| } | } | ||||
| @@ -1,6 +1,9 @@ | |||||
| package me.chanjar.weixin.cp.api; | package me.chanjar.weixin.cp.api; | ||||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||||
| import me.chanjar.weixin.common.session.*; | import me.chanjar.weixin.common.session.*; | ||||
| import me.chanjar.weixin.common.util.LogExceptionHandler; | |||||
| import me.chanjar.weixin.common.util.WxErrorExceptionHandler; | |||||
| import me.chanjar.weixin.common.util.WxMessageDuplicateChecker; | import me.chanjar.weixin.common.util.WxMessageDuplicateChecker; | ||||
| import me.chanjar.weixin.common.util.WxMessageInMemoryDuplicateChecker; | import me.chanjar.weixin.common.util.WxMessageInMemoryDuplicateChecker; | ||||
| import me.chanjar.weixin.cp.bean.WxCpXmlMessage; | import me.chanjar.weixin.cp.bean.WxCpXmlMessage; | ||||
| @@ -62,11 +65,14 @@ public class WxCpMessageRouter { | |||||
| private WxSessionManager sessionManager; | private WxSessionManager sessionManager; | ||||
| private WxErrorExceptionHandler exceptionHandler; | |||||
| public WxCpMessageRouter(WxCpService wxCpService) { | public WxCpMessageRouter(WxCpService wxCpService) { | ||||
| this.wxCpService = wxCpService; | this.wxCpService = wxCpService; | ||||
| this.executorService = Executors.newFixedThreadPool(DEFAULT_THREAD_POOL_SIZE); | this.executorService = Executors.newFixedThreadPool(DEFAULT_THREAD_POOL_SIZE); | ||||
| this.messageDuplicateChecker = new WxMessageInMemoryDuplicateChecker(); | this.messageDuplicateChecker = new WxMessageInMemoryDuplicateChecker(); | ||||
| this.sessionManager = new StandardSessionManager(); | this.sessionManager = new StandardSessionManager(); | ||||
| this.exceptionHandler = new LogExceptionHandler(); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -143,12 +149,12 @@ public class WxCpMessageRouter { | |||||
| futures.add( | futures.add( | ||||
| executorService.submit(new Runnable() { | executorService.submit(new Runnable() { | ||||
| public void run() { | public void run() { | ||||
| rule.service(wxMessage, wxCpService, sessionManager); | |||||
| rule.service(wxMessage, wxCpService, sessionManager, exceptionHandler); | |||||
| } | } | ||||
| }) | }) | ||||
| ); | ); | ||||
| } else { | } else { | ||||
| res = rule.service(wxMessage, wxCpService, sessionManager); | |||||
| res = rule.service(wxMessage, wxCpService, sessionManager, exceptionHandler); | |||||
| // 在同步操作结束,session访问结束 | // 在同步操作结束,session访问结束 | ||||
| log.debug("End session access: async=false, sessionId={}", wxMessage.getFromUserName()); | log.debug("End session access: async=false, sessionId={}", wxMessage.getFromUserName()); | ||||
| sessionEndAccess(wxMessage); | sessionEndAccess(wxMessage); | ||||
| @@ -425,22 +431,35 @@ public class WxCpMessageRouter { | |||||
| * @param wxMessage | * @param wxMessage | ||||
| * @return true 代表继续执行别的router,false 代表停止执行别的router | * @return true 代表继续执行别的router,false 代表停止执行别的router | ||||
| */ | */ | ||||
| protected WxCpXmlOutMessage service(WxCpXmlMessage wxMessage, WxCpService wxCpService, WxSessionManager sessionManager) { | |||||
| Map<String, Object> context = new HashMap<String, Object>(); | |||||
| // 如果拦截器不通过 | |||||
| for (WxCpMessageInterceptor interceptor : this.interceptors) { | |||||
| if (!interceptor.intercept(wxMessage, context, wxCpService, sessionManager)) { | |||||
| return null; | |||||
| protected WxCpXmlOutMessage service(WxCpXmlMessage wxMessage, | |||||
| WxCpService wxCpService, | |||||
| WxSessionManager sessionManager, | |||||
| WxErrorExceptionHandler exceptionHandler) { | |||||
| try { | |||||
| Map<String, Object> context = new HashMap<String, Object>(); | |||||
| // 如果拦截器不通过 | |||||
| for (WxCpMessageInterceptor interceptor : this.interceptors) { | |||||
| if (!interceptor.intercept(wxMessage, context, wxCpService, sessionManager)) { | |||||
| return null; | |||||
| } | |||||
| } | } | ||||
| } | |||||
| // 交给handler处理 | |||||
| WxCpXmlOutMessage res = null; | |||||
| for (WxCpMessageHandler handler : this.handlers) { | |||||
| // 返回最后handler的结果 | |||||
| res = handler.handle(wxMessage, context, wxCpService, sessionManager); | |||||
| // 交给handler处理 | |||||
| WxCpXmlOutMessage res = null; | |||||
| for (WxCpMessageHandler handler : this.handlers) { | |||||
| // 返回最后handler的结果 | |||||
| res = handler.handle(wxMessage, context, wxCpService, sessionManager); | |||||
| } | |||||
| return res; | |||||
| } catch (WxErrorException e) { | |||||
| exceptionHandler.handle(e); | |||||
| } | } | ||||
| return res; | |||||
| return null; | |||||
| } | } | ||||
| } | } | ||||
| @@ -1,5 +1,6 @@ | |||||
| package me.chanjar.weixin.mp.api; | package me.chanjar.weixin.mp.api; | ||||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||||
| import me.chanjar.weixin.common.session.WxSessionManager; | import me.chanjar.weixin.common.session.WxSessionManager; | ||||
| import me.chanjar.weixin.mp.bean.WxMpXmlMessage; | import me.chanjar.weixin.mp.bean.WxMpXmlMessage; | ||||
| import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage; | import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage; | ||||
| @@ -23,6 +24,6 @@ public interface WxMpMessageHandler { | |||||
| public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, | public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, | ||||
| Map<String, Object> context, | Map<String, Object> context, | ||||
| WxMpService wxMpService, | WxMpService wxMpService, | ||||
| WxSessionManager sessionManager); | |||||
| WxSessionManager sessionManager) throws WxErrorException; | |||||
| } | } | ||||
| @@ -1,5 +1,6 @@ | |||||
| package me.chanjar.weixin.mp.api; | package me.chanjar.weixin.mp.api; | ||||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||||
| import me.chanjar.weixin.common.session.WxSessionManager; | import me.chanjar.weixin.common.session.WxSessionManager; | ||||
| import me.chanjar.weixin.mp.bean.WxMpXmlMessage; | import me.chanjar.weixin.mp.bean.WxMpXmlMessage; | ||||
| @@ -24,6 +25,6 @@ public interface WxMpMessageInterceptor { | |||||
| public boolean intercept(WxMpXmlMessage wxMessage, | public boolean intercept(WxMpXmlMessage wxMessage, | ||||
| Map<String, Object> context, | Map<String, Object> context, | ||||
| WxMpService wxMpService, | WxMpService wxMpService, | ||||
| WxSessionManager sessionManager); | |||||
| WxSessionManager sessionManager) throws WxErrorException; | |||||
| } | } | ||||
| @@ -1,7 +1,12 @@ | |||||
| package me.chanjar.weixin.mp.api; | package me.chanjar.weixin.mp.api; | ||||
| import me.chanjar.weixin.common.api.WxConsts; | |||||
| import me.chanjar.weixin.common.session.*; | |||||
| import me.chanjar.weixin.common.exception.WxErrorException; | |||||
| import me.chanjar.weixin.common.session.InternalSession; | |||||
| import me.chanjar.weixin.common.session.InternalSessionManager; | |||||
| import me.chanjar.weixin.common.session.StandardSessionManager; | |||||
| import me.chanjar.weixin.common.session.WxSessionManager; | |||||
| import me.chanjar.weixin.common.util.LogExceptionHandler; | |||||
| import me.chanjar.weixin.common.util.WxErrorExceptionHandler; | |||||
| import me.chanjar.weixin.common.util.WxMessageDuplicateChecker; | import me.chanjar.weixin.common.util.WxMessageDuplicateChecker; | ||||
| import me.chanjar.weixin.common.util.WxMessageInMemoryDuplicateChecker; | import me.chanjar.weixin.common.util.WxMessageInMemoryDuplicateChecker; | ||||
| import me.chanjar.weixin.mp.bean.WxMpXmlMessage; | import me.chanjar.weixin.mp.bean.WxMpXmlMessage; | ||||
| @@ -61,11 +66,14 @@ public class WxMpMessageRouter { | |||||
| private WxSessionManager sessionManager; | private WxSessionManager sessionManager; | ||||
| private WxErrorExceptionHandler exceptionHandler; | |||||
| public WxMpMessageRouter(WxMpService wxMpService) { | public WxMpMessageRouter(WxMpService wxMpService) { | ||||
| this.wxMpService = wxMpService; | this.wxMpService = wxMpService; | ||||
| this.executorService = Executors.newFixedThreadPool(DEFAULT_THREAD_POOL_SIZE); | this.executorService = Executors.newFixedThreadPool(DEFAULT_THREAD_POOL_SIZE); | ||||
| this.messageDuplicateChecker = new WxMessageInMemoryDuplicateChecker(); | this.messageDuplicateChecker = new WxMessageInMemoryDuplicateChecker(); | ||||
| this.sessionManager = new StandardSessionManager(); | this.sessionManager = new StandardSessionManager(); | ||||
| this.exceptionHandler = new LogExceptionHandler(); | |||||
| } | } | ||||
| /** | /** | ||||
| @@ -142,12 +150,12 @@ public class WxMpMessageRouter { | |||||
| futures.add( | futures.add( | ||||
| executorService.submit(new Runnable() { | executorService.submit(new Runnable() { | ||||
| public void run() { | public void run() { | ||||
| rule.service(wxMessage, wxMpService, sessionManager); | |||||
| rule.service(wxMessage, wxMpService, sessionManager, exceptionHandler); | |||||
| } | } | ||||
| }) | }) | ||||
| ); | ); | ||||
| } else { | } else { | ||||
| res = rule.service(wxMessage, wxMpService, sessionManager); | |||||
| res = rule.service(wxMessage, wxMpService, sessionManager, exceptionHandler); | |||||
| // 在同步操作结束,session访问结束 | // 在同步操作结束,session访问结束 | ||||
| log.debug("End session access: async=false, sessionId={}", wxMessage.getFromUserName()); | log.debug("End session access: async=false, sessionId={}", wxMessage.getFromUserName()); | ||||
| sessionEndAccess(wxMessage); | sessionEndAccess(wxMessage); | ||||
| @@ -409,22 +417,33 @@ public class WxMpMessageRouter { | |||||
| * @param wxMessage | * @param wxMessage | ||||
| * @return true 代表继续执行别的router,false 代表停止执行别的router | * @return true 代表继续执行别的router,false 代表停止执行别的router | ||||
| */ | */ | ||||
| protected WxMpXmlOutMessage service(WxMpXmlMessage wxMessage, WxMpService wxMpService, WxSessionManager sessionManager) { | |||||
| Map<String, Object> context = new HashMap<String, Object>(); | |||||
| // 如果拦截器不通过 | |||||
| for (WxMpMessageInterceptor interceptor : this.interceptors) { | |||||
| if (!interceptor.intercept(wxMessage, context, wxMpService, sessionManager)) { | |||||
| return null; | |||||
| protected WxMpXmlOutMessage service(WxMpXmlMessage wxMessage, | |||||
| WxMpService wxMpService, | |||||
| WxSessionManager sessionManager, | |||||
| WxErrorExceptionHandler exceptionHandler) { | |||||
| try { | |||||
| Map<String, Object> context = new HashMap<String, Object>(); | |||||
| // 如果拦截器不通过 | |||||
| for (WxMpMessageInterceptor interceptor : this.interceptors) { | |||||
| if (!interceptor.intercept(wxMessage, context, wxMpService, sessionManager)) { | |||||
| return null; | |||||
| } | |||||
| } | } | ||||
| // 交给handler处理 | |||||
| WxMpXmlOutMessage res = null; | |||||
| for (WxMpMessageHandler handler : this.handlers) { | |||||
| // 返回最后handler的结果 | |||||
| res = handler.handle(wxMessage, context, wxMpService, sessionManager); | |||||
| } | |||||
| return res; | |||||
| } catch (WxErrorException e) { | |||||
| exceptionHandler.handle(e); | |||||
| } | } | ||||
| // 交给handler处理 | |||||
| WxMpXmlOutMessage res = null; | |||||
| for (WxMpMessageHandler handler : this.handlers) { | |||||
| // 返回最后handler的结果 | |||||
| res = handler.handle(wxMessage, context, wxMpService, sessionManager); | |||||
| } | |||||
| return res; | |||||
| return null; | |||||
| } | } | ||||
| } | } | ||||
| @@ -35,7 +35,7 @@ public class DemoGuessNumberHandler implements WxMpMessageHandler, WxMpMessageMa | |||||
| @Override | @Override | ||||
| public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, | public WxMpXmlOutMessage handle(WxMpXmlMessage wxMessage, Map<String, Object> context, WxMpService wxMpService, | ||||
| WxSessionManager sessionManager) { | |||||
| WxSessionManager sessionManager) throws WxErrorException { | |||||
| if (isUserWantGuess(wxMessage)) { | if (isUserWantGuess(wxMessage)) { | ||||
| letsGo(wxMessage, wxMpService, sessionManager); | letsGo(wxMessage, wxMpService, sessionManager); | ||||
| @@ -49,7 +49,7 @@ public class DemoGuessNumberHandler implements WxMpMessageHandler, WxMpMessageMa | |||||
| } | } | ||||
| protected void letsGo(WxMpXmlMessage wxMessage, WxMpService wxMpService, WxSessionManager sessionManager) { | |||||
| protected void letsGo(WxMpXmlMessage wxMessage, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException { | |||||
| WxSession session = sessionManager.getSession(wxMessage.getFromUserName()); | WxSession session = sessionManager.getSession(wxMessage.getFromUserName()); | ||||
| if (session.getAttribute("guessing") == null) { | if (session.getAttribute("guessing") == null) { | ||||
| WxMpCustomMessage m = WxMpCustomMessage | WxMpCustomMessage m = WxMpCustomMessage | ||||
| @@ -57,22 +57,14 @@ public class DemoGuessNumberHandler implements WxMpMessageHandler, WxMpMessageMa | |||||
| .toUser(wxMessage.getFromUserName()) | .toUser(wxMessage.getFromUserName()) | ||||
| .content("请猜一个100以内的数字") | .content("请猜一个100以内的数字") | ||||
| .build(); | .build(); | ||||
| try { | |||||
| wxMpService.customMessageSend(m); | |||||
| } catch (WxErrorException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| wxMpService.customMessageSend(m); | |||||
| } else { | } else { | ||||
| WxMpCustomMessage m = WxMpCustomMessage | WxMpCustomMessage m = WxMpCustomMessage | ||||
| .TEXT() | .TEXT() | ||||
| .toUser(wxMessage.getFromUserName()) | .toUser(wxMessage.getFromUserName()) | ||||
| .content("放弃了吗?那请重新猜一个100以内的数字") | .content("放弃了吗?那请重新猜一个100以内的数字") | ||||
| .build(); | .build(); | ||||
| try { | |||||
| wxMpService.customMessageSend(m); | |||||
| } catch (WxErrorException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| wxMpService.customMessageSend(m); | |||||
| } | } | ||||
| session.setAttribute("guessing", Boolean.TRUE); | session.setAttribute("guessing", Boolean.TRUE); | ||||
| @@ -80,7 +72,7 @@ public class DemoGuessNumberHandler implements WxMpMessageHandler, WxMpMessageMa | |||||
| } | } | ||||
| protected void giveHint(WxMpXmlMessage wxMessage, WxMpService wxMpService, WxSessionManager sessionManager) { | |||||
| protected void giveHint(WxMpXmlMessage wxMessage, WxMpService wxMpService, WxSessionManager sessionManager) throws WxErrorException { | |||||
| WxSession session = sessionManager.getSession(wxMessage.getFromUserName()); | WxSession session = sessionManager.getSession(wxMessage.getFromUserName()); | ||||
| @@ -100,11 +92,7 @@ public class DemoGuessNumberHandler implements WxMpMessageHandler, WxMpMessageMa | |||||
| .toUser(wxMessage.getFromUserName()) | .toUser(wxMessage.getFromUserName()) | ||||
| .content("小了") | .content("小了") | ||||
| .build(); | .build(); | ||||
| try { | |||||
| wxMpService.customMessageSend(m); | |||||
| } catch (WxErrorException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| wxMpService.customMessageSend(m); | |||||
| } else if (guessNumber > answer) { | } else if (guessNumber > answer) { | ||||
| WxMpCustomMessage m = WxMpCustomMessage | WxMpCustomMessage m = WxMpCustomMessage | ||||
| @@ -112,23 +100,15 @@ public class DemoGuessNumberHandler implements WxMpMessageHandler, WxMpMessageMa | |||||
| .toUser(wxMessage.getFromUserName()) | .toUser(wxMessage.getFromUserName()) | ||||
| .content("大了") | .content("大了") | ||||
| .build(); | .build(); | ||||
| try { | |||||
| wxMpService.customMessageSend(m); | |||||
| } catch (WxErrorException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| wxMpService.customMessageSend(m); | |||||
| } else { | } else { | ||||
| WxMpCustomMessage m = WxMpCustomMessage | WxMpCustomMessage m = WxMpCustomMessage | ||||
| .TEXT() | .TEXT() | ||||
| .toUser(wxMessage.getFromUserName()) | .toUser(wxMessage.getFromUserName()) | ||||
| .content("Bingo!") | .content("Bingo!") | ||||
| .build(); | .build(); | ||||
| try { | |||||
| session.removeAttribute("guessing"); | |||||
| wxMpService.customMessageSend(m); | |||||
| } catch (WxErrorException e) { | |||||
| e.printStackTrace(); | |||||
| } | |||||
| session.removeAttribute("guessing"); | |||||
| wxMpService.customMessageSend(m); | |||||
| } | } | ||||
| } | } | ||||