netty学习一:用netty构造http服务的小demo

来源:互联网 发布:提现接口网站 php 编辑:程序博客网 时间:2024/06/11 16:37

概述


netty可以支持http、socket、websocket,本文会做一个小demo,简单介绍一下如何用netty搭建一个http服务。

netty虽然可以提供http服务,但是相比spring mvc、struts2等框架,netty显得比较底层,很多spring mvc提供的功能,netty统统都没有。


步骤


编写netty程序的步骤都比较相似:
1、 启动group监听客户端请求
2、编写Initializer添加handler
3、自定义业务handler


启动group监听客户端请求


package http;import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.ChannelFuture;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.nio.NioServerSocketChannel;public class HttpServer {    public static void main(String[] args) throws InterruptedException {        // 接收连接,但是不处理        EventLoopGroup parentGroup = new NioEventLoopGroup();        // 真正处理连接的group        EventLoopGroup childGroup = new NioEventLoopGroup();        try {            //加载Initializer            ServerBootstrap serverBootstrap = new ServerBootstrap();            serverBootstrap.group(parentGroup, childGroup)                           .channel(NioServerSocketChannel.class)                            //这里的childHandler是服务于childGroup的,如果直接使用                           //handler方法添加处理器,则是服务于parentGroup的                           .childHandler(new HttpServerInitializer());            //绑定监听端口            ChannelFuture channelFuture = serverBootstrap.bind(8899).sync();            channelFuture.channel().closeFuture().sync();        }        finally {            parentGroup.shutdownGracefully();            childGroup.shutdownGracefully();        }    }}

EventLoopGroup类似死循环,一直监听8899端口是否有请求到达。


编写Initializer添加handler


package http;import io.netty.channel.ChannelInitializer;import io.netty.channel.ChannelPipeline;import io.netty.channel.socket.SocketChannel;import io.netty.handler.codec.http.HttpServerCodec;public class HttpServerInitializer extends ChannelInitializer<SocketChannel>{    @Override    protected void initChannel(SocketChannel ch) throws Exception {        ChannelPipeline pipeline = ch.pipeline();        //处理http服务的关键handler        pipeline.addLast("httpServerCodec",new HttpServerCodec());        //自定义的handler        pipeline.addLast("testHttpServerHandler",new HttpServerHandler());    }}

自定义业务handler


package http;import io.netty.buffer.ByteBuf;import io.netty.buffer.Unpooled;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.SimpleChannelInboundHandler;import io.netty.handler.codec.http.DefaultFullHttpResponse;import io.netty.handler.codec.http.HttpHeaderNames;import io.netty.handler.codec.http.HttpObject;import io.netty.handler.codec.http.HttpRequest;import io.netty.handler.codec.http.HttpResponseStatus;import io.netty.handler.codec.http.HttpVersion;import io.netty.util.CharsetUtil;public class HttpServerHandler extends SimpleChannelInboundHandler<HttpObject>{    @Override    protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {        if (msg instanceof HttpRequest) {            HttpRequest httpRequest = (HttpRequest)msg;            System.out.println("请求方法名称:"+httpRequest.method().name());            System.out.println("请求来自:"+ctx.channel().remoteAddress());            ByteBuf content = Unpooled.copiedBuffer("Hello World!",CharsetUtil.UTF_8);            DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,                     HttpResponseStatus.OK,                    content);            response.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/plain");            response.headers().set(HttpHeaderNames.CONTENT_LENGTH,content.readableBytes());            ctx.writeAndFlush(response);            ctx.channel().close();        }    }    @Override    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {        System.out.println("handler add");        super.handlerAdded(ctx);    }    @Override    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {        System.out.println("channel registed");        super.channelRegistered(ctx);    }    @Override    public void channelActive(ChannelHandlerContext ctx) throws Exception {        System.out.println("channel active");        super.channelActive(ctx);    }    @Override    public void channelInactive(ChannelHandlerContext ctx) throws Exception {        System.out.println("channel inactive");        super.channelInactive(ctx);    }    @Override    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {        System.out.println("channel unregisted");        super.channelUnregistered(ctx);    }}

测试


运行main方法启动netty http程序,并使用curl命令测试。

curl ‘http://localhost:8899/’

输出结果如下:

handler add
channel registed
channel active
请求方法名称:GET
请求来自:/0:0:0:0:0:0:0:1:52291
channel inactive
channel unregisted


csdn code 路径


这个项目的源代码放置在csdn code上,欢迎访问。

netty_study