Java 网络框架 Netty(二) —— HTTP 服务之 Hello Netty

步骤:

  1. 一个服务端的 Handler:用于处理连接创建后和接收到信息后的业务,构建一个 FullHttpResponse 对象输出。
  2. Server:配置服务器的启动代码

也就是说我们只需要写一个处理者程序,然后写一个配置启动服务的 main 程序就可以构建一个 Web 服务了。

引入 Netty

我这里是使用 Maven 构建项目,当然你也可以通过下载引入 Jar 包的方式来构建

<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
    <version>4.1.27.Final</version>
</dependency>

代码清单

  • Handler.java
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.DefaultHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;

// @Sharable 标识这类的实例之间可以在 channel 里面共享
@Sharable
public class Handler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if(msg instanceof HttpRequest) {
            DefaultHttpRequest req = (DefaultHttpRequest) msg;
            // 输出 request
            System.out.println(req.toString());
        }
        String ret = "Hello Netty!";
        // 将所接收的消息返回给发送者(输出)。注意,这还没有冲刷数据
        FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,
                HttpResponseStatus.OK, 
                Unpooled.wrappedBuffer(ret.getBytes()));
        response.headers().set("content-type", "text/html");
        response.headers().set("content-length",
                response.content().readableBytes());
        ctx.write(response);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        // 冲刷所有待审消息到远程节点。关闭通道后,操作完成
        ctx.writeAndFlush(Unpooled.EMPTY_BUFFER)
            .addListener(ChannelFutureListener.CLOSE);
    }

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

}
  • server.java
import java.net.InetSocketAddress;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;

public class Server {
    private static final int port = 3000; // 监听端口

    public static void main(String[] args) throws Exception {
        NioEventLoopGroup group = new NioEventLoopGroup(); // 创建 EventLoopGroup
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(group) // 创建 ServerBootstrap
                    .channel(NioServerSocketChannel.class) // 制定使用 NIO 的传输 Channel
                    .localAddress(new InetSocketAddress(port)) // 设置端口
                    .childHandler(new ChannelInitializer<SocketChannel>() { 
                        // 将我们的 Handler 添加到 ChannelPipeline
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                            // server端发送的是httpResponse,所以要使用HttpResponseEncoder进行编码
                            ch.pipeline().addLast(new HttpResponseEncoder());
                            // server端接收到的是httpRequest,所以要使用HttpRequestDecoder进行解码
                            ch.pipeline().addLast(new HttpRequestDecoder());
                            ch.pipeline().addLast(new Handler());
                        }
                    });

            ChannelFuture f = b.bind().sync(); // 绑定的服务器,sync() 等待服务关闭
            System.out.println("Server started and listen on " + f.channel().localAddress());
            f.channel().closeFuture().sync();
        } finally {
            group.shutdownGracefully().sync(); // 关闭 EventLoopGroup
        }
    }

}

启动 Server

控制台输出

Server started and listen on /0:0:0:0:0:0:0:0:3000

浏览器访问 127.0.0.1:3000

Hello Netty!

猜你喜欢

转载自blog.csdn.net/xiaoping0915/article/details/81189532