diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/Netty4HttpClient.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/Netty4HttpClient.java index 3dbfcde8..8407b263 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/Netty4HttpClient.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/Netty4HttpClient.java @@ -16,6 +16,7 @@ import io.netty.handler.codec.http.FullHttpResponse; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpVersion; import io.netty.handler.ssl.SslHandler; +import io.netty.handler.timeout.ReadTimeoutHandler; import java.io.IOException; import java.net.InetAddress; @@ -25,6 +26,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map.Entry; import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; @@ -91,6 +93,12 @@ public class Netty4HttpClient extends AbstractHttpClient { sslEngine.setUseClientMode(true); channel.pipeline().addFirst( new SslHandler(sslEngine)); + if (params != null && params.getReadTimeout() > 0) { + channel.pipeline().addFirst( + new ReadTimeoutHandler(params + .getReadTimeout(), + TimeUnit.MILLISECONDS)); + } } channel.pipeline().addLast(new RequestHandler(future)); channel.writeAndFlush(uriRequest); diff --git a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/Netty4HttpClientFactory.java b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/Netty4HttpClientFactory.java index 6fe5c99a..e6977016 100644 --- a/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/Netty4HttpClientFactory.java +++ b/weixin4j-base/src/main/java/com/foxinmy/weixin4j/http/factory/Netty4HttpClientFactory.java @@ -39,26 +39,30 @@ public class Netty4HttpClientFactory extends HttpClientFactory { this.workerThreads = workerThreads; } + private volatile Bootstrap bootstrap; + @Override public HttpClient newInstance() { - Bootstrap b = new Bootstrap(); - b.option(ChannelOption.SO_KEEPALIVE, true).option( - ChannelOption.TCP_NODELAY, true); - EventLoopGroup workerGroup = new NioEventLoopGroup(workerThreads); - b.group(workerGroup).channel(NioSocketChannel.class) - .handler(new ChannelInitializer() { - @Override - protected void initChannel(SocketChannel channel) - throws Exception { - ChannelPipeline pipeline = channel.pipeline(); - pipeline.addLast(new HttpClientCodec()); - pipeline.addLast(new HttpContentDecompressor()); - pipeline.addLast(new ChunkedWriteHandler()); - pipeline.addLast(new HttpResponseDecoder()); - pipeline.addLast(new HttpObjectAggregator( - Integer.MAX_VALUE)); - } - }); - return new Netty4HttpClient(b); + if (bootstrap == null) { + bootstrap = new Bootstrap(); + bootstrap.option(ChannelOption.SO_KEEPALIVE, true).option( + ChannelOption.TCP_NODELAY, true); + EventLoopGroup workerGroup = new NioEventLoopGroup(workerThreads); + bootstrap.group(workerGroup).channel(NioSocketChannel.class) + .handler(new ChannelInitializer() { + @Override + protected void initChannel(SocketChannel channel) + throws Exception { + ChannelPipeline pipeline = channel.pipeline(); + pipeline.addLast(new HttpClientCodec()); + pipeline.addLast(new HttpContentDecompressor()); + pipeline.addLast(new ChunkedWriteHandler()); + pipeline.addLast(new HttpResponseDecoder()); + pipeline.addLast(new HttpObjectAggregator( + Integer.MAX_VALUE)); + } + }); + } + return new Netty4HttpClient(bootstrap); } } diff --git a/weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/MenuTest.java b/weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/MenuTest.java index 65bc42c6..78beddad 100644 --- a/weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/MenuTest.java +++ b/weixin4j-mp/src/test/java/com/foxinmy/weixin4j/mp/test/MenuTest.java @@ -43,15 +43,13 @@ public class MenuTest extends TokenTest { buttons.add(new Button("个人中心", domain + "/user", ButtonType.view)); Button button = new Button("小哥介绍", domain, ButtonType.view); - button.pushSub(new Button( - "小哥介绍", - "http://x.eqxiu.com/s/89oy462U", + button.pushSub(new Button("小哥介绍", "http://x.eqxiu.com/s/89oy462U", ButtonType.view)); - button.pushSub(new Button( - "小哥官网", - "http://www.jdxiaoge.com", + button.pushSub(new Button("小哥官网", "http://www.jdxiaoge.com", + ButtonType.view)); + button.pushSub(new Button("兴趣部落", + "http://buluo.qq.com/p/barindex.html?from=share&bid=282651", ButtonType.view)); - button.pushSub(new Button("兴趣部落", "http://buluo.qq.com/p/barindex.html?from=share&bid=282651", ButtonType.view)); button.pushSub(new Button("服务流程", "FLOW", ButtonType.click)); button.pushSub(new Button("在线客服", "KF", ButtonType.click)); buttons.add(button); @@ -107,15 +105,15 @@ public class MenuTest extends TokenTest { JsonResult result = menuApi.createCustomMenu(buttons, matchRule); Assert.assertEquals(0, result.getCode()); } - + @Test public void testGetAllMenus() throws WeixinException { List menus = menuApi.getAllMenu(); System.err.println(menus); } - + @Test - public void testMatchMenu()throws WeixinException{ + public void testMatchMenu() throws WeixinException { List