使用Netty的HTTP请求

时间:2013-11-18 06:13:09

标签: java httprequest netty

我刚开始使用netty,我对目前的文档感到非常失望 他们的网站。

我正在尝试使用Netty连接到URL。我从他们的网站上获取了时间客户端示例并根据我的要求进行了更改..

代码:

public class NettyClient {

      public static void main(String[] args) throws Exception {
          String host = "myUrl.com/v1/parma?param1=value";
            int port = 443;
            EventLoopGroup workerGroup = new NioEventLoopGroup();

            try {
                Bootstrap b = new Bootstrap();             
                b.group(workerGroup); 
                b.channel(NioSocketChannel.class); 
                b.option(ChannelOption.SO_KEEPALIVE, true); 
                b.handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    public void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new ClientHandler());
                        ch.pipeline().addLast("encoder", new HttpRequestEncoder());
                    }
                });

                // Start the client.
                ChannelFuture f = b.connect(host, port).sync(); 

                // Wait until the connection is closed.
                f.channel().closeFuture().sync();
            } finally {
                workerGroup.shutdownGracefully();
            }
        }
}

但问题是它只需要没有查询参数的url ..如何通过URL传递查询参数? 请给我一些关于Netty 4的好文档的链接..

修改

在参考答案中提到的示例后的客户端代码:

URI uri = new URI("myUrl.com/v1/parma?param1=value");          
           String scheme = uri.getScheme() == null? "http" : uri.getScheme();
           String host = "myUrl.com";
            int port = 443;



            boolean ssl = "https".equalsIgnoreCase(scheme);

         // Configure the client.
            EventLoopGroup group = new NioEventLoopGroup();
            try {
                Bootstrap b = new Bootstrap();
                b.group(group)
                 .channel(NioSocketChannel.class)
                 .handler(new NettyClientInitializer(ssl));
                // Make the connection attempt.
                Channel ch = b.connect(host, port).sync().channel();
                // Prepare the HTTP request.
                HttpRequest request = new DefaultHttpRequest(
                        HttpVersion.HTTP_1_1, HttpMethod.GET, uri.getRawPath());
                request.headers().set(HttpHeaders.Names.HOST, host);
                request.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.CLOSE);
                //request.headers().set(HttpHeaders.Names.ACCEPT_ENCODING, HttpHeaders.Values.GZIP);

                /*// Set some example cookies.
                request.headers().set(
                        HttpHeaders.Names.COOKIE,
                        ClientCookieEncoder.encode(
                                new DefaultCookie("my-cookie", "foo"),
                                new DefaultCookie("another-cookie", "bar")));
*/
                // Send the HTTP request.
                ch.writeAndFlush(request);

                // Wait for the server to close the connection.
                ch.closeFuture().sync();
            } finally {
                // Shut down executor threads to exit.
                group.shutdownGracefully();
            }

处理程序代码:

public class ClientHandler extends SimpleChannelInboundHandler<HttpObject> {

    @Override
    public void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
        if (msg instanceof HttpResponse) {
            HttpResponse response = (HttpResponse) msg;

            System.out.println("STATUS: " + response.getStatus());
            System.out.println("VERSION: " + response.getProtocolVersion());
            System.out.println();

            if (!response.headers().isEmpty()) {
                for (String name: response.headers().names()) {
                    for (String value: response.headers().getAll(name)) {
                        System.out.println("HEADER: " + name + " = " + value);
                    }
                }
                System.out.println();
            }

            if (HttpHeaders.isTransferEncodingChunked(response)) {
                System.out.println("CHUNKED CONTENT {");
            } else {
                System.out.println("CONTENT {");
            }
        }
        if (msg instanceof HttpContent) {
            HttpContent content = (HttpContent) msg;

            System.out.print(content.content().toString(CharsetUtil.UTF_8));
            System.out.flush();

            if (content instanceof LastHttpContent) {
                System.out.println("} END OF CONTENT");
            }
        }
    }

    @Override
    public void exceptionCaught(
            ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }


}

初始化代码:

public class NettyClientInitializer extends ChannelInitializer<SocketChannel> {

    private final boolean ssl;

    public NettyClientInitializer(boolean ssl) {
        this.ssl = ssl;
    }

    @Override
    public void initChannel(SocketChannel ch) throws Exception {
        // Create a default pipeline implementation.
        ChannelPipeline p = ch.pipeline();

        p.addLast("log", new LoggingHandler(LogLevel.INFO));
        // Enable HTTPS if necessary.
        /*
        if (ssl) {
            SSLEngine engine =
                SecureChatSslContextFactory.getClientContext().createSSLEngine();
            engine.setUseClientMode(true);

            p.addLast("ssl", new SslHandler(engine));
        }
*/
        p.addLast("codec", new HttpClientCodec());

        // Remove the following line if you don't want automatic content decompression.
       // p.addLast("inflater", new HttpContentDecompressor());

        // Uncomment the following line if you don't want to handle HttpChunks.
        p.addLast("aggregator", new HttpObjectAggregator(1048576));
        p.addLast("handler", new ClientHandler());
    }
}

3 个答案:

答案 0 :(得分:4)

您的代码目前仅处理低级别连接。实际上,在这个级别只能使用主机名和端口。

对于HTTP请求您必须构造一个HttpRequest对象并通过该通道发送它。在此请求对象中,您可以定义查询参数和所有此类内容。

在Netty网站上有一堆关于HTTP客户端功能的示例代码 - have a a look

答案 1 :(得分:3)

在此示例中,问题在于uri.getRawPath()的DefaultHttpRequest参数的构造函数。调用此方法不会返回查询参数。它适用于这种情况,因为Snoop示例中没有查询参数。通过替换uri.toASCIIString(),返回带有查询参数的已编码uri。为了向自己证明这一点,而不是在方法调用中进行方法调用(出于这个原因一个坏主意,添加语句

String url = uri.getRawPath();

并查看字符串url。

我遇到了完全相同的问题。我已经在servlet中本地完成了多年,但现在尝试在Netty应用程序中完成它。

因此新代码将是:

String path = uri.toASCIIString();
// Prepare the HTTP request.
HttpRequest request = new DefaultFullHttpRequest(
        HttpVersion.HTTP_1_1, HttpMethod.GET, path);

答案 2 :(得分:0)

构建请求时,需要将查询添加到路径。代替

  

uri.getRawPath()

使用

  

uri.getRawPath()+“?” + uri.getRawQuery()