All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.foxinmy.weixin4j.startup.WeixinServerBootstrap Maven / Gradle / Ivy

package com.foxinmy.weixin4j.startup;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.foxinmy.weixin4j.dispatcher.BeanFactory;
import com.foxinmy.weixin4j.dispatcher.DefaultMessageMatcher;
import com.foxinmy.weixin4j.dispatcher.WeixinMessageDispatcher;
import com.foxinmy.weixin4j.dispatcher.WeixinMessageKey;
import com.foxinmy.weixin4j.dispatcher.WeixinMessageMatcher;
import com.foxinmy.weixin4j.handler.WeixinMessageHandler;
import com.foxinmy.weixin4j.interceptor.WeixinMessageInterceptor;
import com.foxinmy.weixin4j.request.WeixinMessage;
import com.foxinmy.weixin4j.socket.WeixinServerInitializer;
import com.foxinmy.weixin4j.util.AesToken;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.bootstrap.ServerBootstrapConfig;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.FutureListener;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;

/**
 * 微信netty服务启动程序
 *
 * @className WeixinServerBootstrap
 * @author jinyu([email protected])
 * @date 2014年10月12日
 * @since JDK 1.6
 * @see com.foxinmy.weixin4j.dispatcher.WeixinMessageMatcher
 * @see com.foxinmy.weixin4j.handler.WeixinMessageHandler
 * @see com.foxinmy.weixin4j.interceptor.WeixinMessageInterceptor
 * @see com.foxinmy.weixin4j.dispatcher.WeixinMessageDispatcher
 * @see com.foxinmy.weixin4j.dispatcher.BeanFactory
 */
public final class WeixinServerBootstrap {

    private final InternalLogger logger = InternalLoggerFactory.getInstance(getClass());

    /**
     * boss线程数,默认设置为cpu的核数
     */
    public final static int DEFAULT_BOSSTHREADS;
    /**
     * worker线程数,默认设置为DEFAULT_BOSSTHREADS * 2
     */
    public final static int DEFAULT_WORKERTHREADS;
    /**
     * 服务启动的默认端口
     */
    public final static int DEFAULT_SERVERPORT = 30000;
    /**
     * 消息分发器
     */
    private WeixinMessageDispatcher messageDispatcher;
    /**
     * 消息处理器
     */
    private List messageHandlerList;
    /**
     * 消息拦截器
     */
    private List messageInterceptorList;

    /**
     * aes and token
     *
     */
    private final Map aesTokenMap;

    private ServerBootstrap bootstrap;

    static {
        DEFAULT_BOSSTHREADS = Runtime.getRuntime().availableProcessors();
        DEFAULT_WORKERTHREADS = DEFAULT_BOSSTHREADS * 2;
    }

    /**
     *
     * 明文模式
     *
     * @param token
     *            开发者token
     *
     */
    public WeixinServerBootstrap(String token) {
        this("", token, null);
    }

    /**
     * 明文模式 & 兼容模式 & 密文模式
     * 
* 值得注意的是:企业号服务时需要在服务器URL后面加多一个`encrypt_type=aes`的参数 *
* * @param weixinId * 公众号的应用ID(appid/corpid) 密文&兼容模式下需要填写 * * @param token * 开发者填写的token 无论哪种模式都需要填写 * @param aesKey * 消息加密的密钥 密文&兼容模式下需要填写 */ public WeixinServerBootstrap(String weixinId, String token, String aesKey) { this(new AesToken(weixinId, token, aesKey)); } /** * 多个公众号的支持 *
值得注意的是: *
* 1).企业号服务时需要在服务器URL后面加多一个`encrypt_type=aes`的参数 *
*
* 2).非明文模式下需要在服务器URL后面加多一个`weixin_id=对应的appid/corpid`的参数 *
* * @param aesTokens * 多个公众号 * @return */ public WeixinServerBootstrap(AesToken... aesToken) { this(new DefaultMessageMatcher(), aesToken); } /** * 多个公众号的支持 *
值得注意的是: *
* 1).企业号服务时需要在服务器URL后面加多一个`encrypt_type=aes`的参数 *
*
* 2).非明文模式下需要在服务器URL后面加多一个`weixin_id=对应的appid/corpid`的参数 *
* * @param messageMatcher * 消息匹配器 * @param aesTokens * 公众号信息 * @return */ public WeixinServerBootstrap(WeixinMessageMatcher messageMatcher, AesToken... aesTokens) { if (messageMatcher == null) { throw new IllegalArgumentException("MessageMatcher not be null"); } if (aesTokens == null) { throw new IllegalArgumentException("AesToken not be null"); } this.aesTokenMap = new HashMap(); for (AesToken aesToken : aesTokens) { this.aesTokenMap.put(aesToken.getWeixinId(), aesToken); } this.aesTokenMap.put("", aesTokens[0]); this.messageHandlerList = new ArrayList(); this.messageInterceptorList = new ArrayList(); this.messageDispatcher = new WeixinMessageDispatcher(messageMatcher); } /** * 默认端口(30000)启动服务 * */ public void startup() { startup(DEFAULT_SERVERPORT); } /** * 指定端口启动服务 * */ public void startup(int serverPort) { startup(DEFAULT_BOSSTHREADS, DEFAULT_WORKERTHREADS, serverPort); } /** * 接受参数启动服务 * * @param bossThreads * boss线程数 * @param workerThreads * worker线程数 * @param serverPort * 服务启动端口 * @return * @throws WeixinException */ public void startup(int bossThreads, int workerThreads, final int serverPort) { messageDispatcher.setMessageHandlerList(messageHandlerList); messageDispatcher.setMessageInterceptorList(messageInterceptorList); try { bootstrap = new ServerBootstrap(); bootstrap.option(ChannelOption.SO_BACKLOG, 1024); bootstrap.group(new NioEventLoopGroup(bossThreads), new NioEventLoopGroup(workerThreads)) .channel(NioServerSocketChannel.class).handler(new LoggingHandler()) .childHandler(new WeixinServerInitializer(aesTokenMap, messageDispatcher)); Channel ch = bootstrap.bind(serverPort).addListener(new FutureListener() { @Override public void operationComplete(Future future) throws Exception { if (future.isSuccess()) { logger.info("weixin4j server startup OK:{}", serverPort); } else { logger.info("weixin4j server startup FAIL:{}", serverPort); } } }).sync().channel(); ch.closeFuture().sync(); } catch (InterruptedException e) { throw new RuntimeException(e); } finally { shutdown(false); } } /** * 关闭微信服务 * * @param blocking * 阻塞关闭 * @return */ public boolean shutdown(boolean blocking) { if (bootstrap == null) { return false; } ServerBootstrapConfig c = bootstrap.config(); Future bossF = c.group().shutdownGracefully(); Future workerF = c.childGroup().shutdownGracefully(); if (blocking) { bossF.awaitUninterruptibly(); workerF.awaitUninterruptibly(); } messageHandlerList = null; messageInterceptorList = null; messageDispatcher = null; bootstrap = null; return true; } /** * 添加一个或者多个消息处理器 * * @param messageHandler * 消息处理器 * @return */ public WeixinServerBootstrap addHandler(WeixinMessageHandler... messageHandler) { if (messageHandler == null) { throw new IllegalArgumentException("messageHandler not be null"); } messageHandlerList.addAll(Arrays.asList(messageHandler)); return this; } /** * 插入一个或多个消息拦截器 * * @param messageInterceptor * 消息拦截器 * @return */ public WeixinServerBootstrap addInterceptor(WeixinMessageInterceptor... messageInterceptor) { if (messageInterceptor == null) { throw new IllegalArgumentException("messageInterceptor not be null"); } messageInterceptorList.addAll(Arrays.asList(messageInterceptor)); return this; } /** * 按照包名去添加消息处理器 * * @param messageHandlerPackages * 消息处理器所在的包名 * @return */ public WeixinServerBootstrap handlerPackagesToScan(String... messageHandlerPackages) { if (messageHandlerPackages == null) { throw new IllegalArgumentException("messageHandlerPackages not be null"); } messageDispatcher.setMessageHandlerPackages(messageHandlerPackages); return this; } /** * 按照包名去添加消息拦截器 * * @param messageInterceptorPackages * 消息拦截器所在的包名 * @return */ public WeixinServerBootstrap interceptorPackagesToScan(String... messageInterceptorPackages) { if (messageInterceptorPackages == null) { throw new IllegalArgumentException("messageInterceptorPackages not be null"); } messageDispatcher.setMessageInterceptorPackages(messageInterceptorPackages); return this; } /** * 声明处理器跟拦截器类实例化的构造工厂,否则通过Class.newInstance的方式构造 * * @param beanFactory * Bean构造工厂 * @return */ public WeixinServerBootstrap resolveBeanFactory(BeanFactory beanFactory) { messageDispatcher.setBeanFactory(beanFactory); return this; } /** * 注册消息类型 * * @param messageKey * 消息key * @param messageClass * 消息类 * @return */ public WeixinServerBootstrap registMessageClass(WeixinMessageKey messageKey, Class messageClass) { messageDispatcher.registMessageClass(messageKey, messageClass); return this; } /** * 打开总是响应开关,如未匹配到MessageHandler时回复空白消息 */ public WeixinServerBootstrap openAlwaysResponse() { messageDispatcher.openAlwaysResponse(); return this; } /** * 动态添加aesToken * * @param aesToken * @return */ public boolean addAesToken(AesToken aesToken) { if (bootstrap == null) { return false; } ServerBootstrapConfig c = bootstrap.config(); ((WeixinServerInitializer) c.childHandler()).addAesToken(aesToken); return true; } public final static String VERSION = "1.1.9"; }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy