View Javadoc
1   package com.foxinmy.weixin4j.listener;
2   
3   import javax.servlet.ServletContext;
4   import javax.servlet.ServletContextEvent;
5   import javax.servlet.ServletContextListener;
6   
7   import com.foxinmy.weixin4j.dispatcher.BeanFactory;
8   import com.foxinmy.weixin4j.handler.DebugMessageHandler;
9   import com.foxinmy.weixin4j.startup.WeixinServerBootstrap;
10  import com.foxinmy.weixin4j.util.AesToken;
11  
12  /**
13   * 监听器方式新线程启动微信服务(适用于与web集成
14   *
15   * @className AbstractWeixinServerStartupListener
16   * @author jinyu
17   * @date Jun 28, 2017
18   * @since JDK 1.6
19   * @see
20   */
21  public abstract class AbstractWeixinServerStartupListener implements ServletContextListener {
22      /**
23       * 服务监听端口,目前微信只支持80端口,可以考虑用nginx做转发到此端口
24       *
25       * @return
26       */
27      protected int getPort() {
28          return 30000;
29      }
30  
31      /**
32       * 明文模式:String aesToken = ""; 密文模式:AesToken aesToken = new
33       * AesToken("公众号appid", "公众号token","公众号加密/解密消息的密钥");
34       */
35      protected AesToken getToken() {
36          return new AesToken("weixin4j");
37      }
38  
39      /**
40       * 处理微信消息的全限包名(也可通过addHandler方式一个一个添加)
41       */
42      abstract String[] getHandlerToScan();
43  
44      /**
45       * 拦截微信消息的全限包名(也可通过addInterceptor方式一个一个添加)
46       *
47       * @return
48       */
49      public String[] getInterceptorToScan() {
50          return null;
51      }
52  
53      /**
54       * bean容器
55       *
56       * @param sc
57       *            servlet上下文
58       * @return
59       */
60      abstract BeanFactory getBeanFactory(ServletContext sc);
61  
62      /**
63       * 当没有匹配到消息处理时输出空白回复(公众号不会出现「该公众号无法提供服务的提示」)
64       *
65       * @return
66       */
67      protected boolean getOpenAlwaysResponse() {
68          return true;
69      }
70  
71      /**
72       * 打开调试回复
73       *
74       * @return
75       */
76      protected boolean getOpenDebugResponse() {
77          return true;
78      }
79  
80      /**
81       * 服务启动
82       */
83      private WeixinServerBootstrap bootstrap;
84  
85      @Override
86      public void contextInitialized(ServletContextEvent sce) {
87          final int port = getPort();
88          final AesToken aesToken = getToken();
89          final String[] handlerPackage = getHandlerToScan();
90          final String[] interceptorPackage = getInterceptorToScan();
91          final BeanFactory beanFactory = getBeanFactory(sce.getServletContext());
92          final boolean openAlwaysResponse = getOpenAlwaysResponse();
93          final boolean openDebugResponse = getOpenDebugResponse();
94          /**
95           * 线程启动服务
96           */
97          new Thread(new Runnable() {
98              @Override
99              public void run() {
100                 bootstrap = new WeixinServerBootstrap(aesToken) // 指定开发者token信息
101                         .handlerPackagesToScan(handlerPackage); // 扫描处理消息的包
102                 if (interceptorPackage != null) // 扫描拦截消息的包
103                     bootstrap.interceptorPackagesToScan(interceptorPackage);
104                 if (beanFactory != null)
105                     bootstrap.resolveBeanFactory(beanFactory); // 声明处理消息类由Bean容器去实例化
106                 if (openDebugResponse)
107                     bootstrap.addHandler(DebugMessageHandler.global); // 当没有匹配到消息处理时输出调试信息,开发环境打开
108                 if (openAlwaysResponse)
109                     bootstrap.openAlwaysResponse(); // 是否总是返回响应,正式环境打开
110                 bootstrap.startup(port); // 绑定服务的端口号,即对外暴露(微信服务器URL地址)的服务端口
111             }
112         }).start();
113     }
114 
115     @Override
116     public void contextDestroyed(ServletContextEvent sce) {
117         /**
118          * 关闭服务
119          */
120         bootstrap.shutdown(true);
121     }
122 }