Netty教程入门(一)

Netty主要组成角色

Channel:请求连接通道
ChannelHandler:业务逻辑处理器
ChannelHandlerContext:业务逻辑处理器上下文
ChannelPipeline:用于保存业务逻辑处理器和业务逻辑处理器上下文

引入依赖

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

Netty启动类

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
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.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpRequestDecoder;
import io.netty.handler.codec.http.HttpResponseEncoder;

/**
 * netty服务端
 *
 * @author tom
 * @version V1.0
 * @date 2020/11/21 16:06
 */
public class NettyServer {
    
    

    private final int port;

    public NettyServer(int port) {
    
    
        this.port = port;
    }

    public static void main(String[] args) throws Exception {
    
    
        int port = 1234;
        new NettyServer(port).start();
    }

    public void start() throws Exception {
    
    
        ServerBootstrap server = new ServerBootstrap();
        NioEventLoopGroup group = new NioEventLoopGroup();
        server.group(group)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
    
    
                    @Override
                    public void initChannel(SocketChannel channel){
    
    
                        System.out.println("initChannel ch:" + channel);
                        channel.pipeline() // ChannelPipeline用于存放ChannelHandler的容器
                                // 解码request,数据流进来的时候将字节码转换为消息对象
                                .addLast("decoder", new HttpRequestDecoder())
                                // 编码response,数据流出去的时候将消息对象转换为字节码
                                .addLast("encoder", new HttpResponseEncoder())
                                // 消息聚合器
                                .addLast("aggregator", new HttpObjectAggregator(512 * 1024))
                                // 请求处理器
                                .addLast("handler", new NettyHandler());
                    }
                })
                //存放已完成三次握手的请求的队列的最大长度
                .option(ChannelOption.SO_BACKLOG, 128)
                // 保持连接
                .childOption(ChannelOption.SO_KEEPALIVE, Boolean.TRUE);
        //绑定端口号
        server.bind(port).sync();
    }
    
}

输入数据业务逻辑处理器

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.FullHttpRequest;
import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpHeaderValues;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;

/**
 * ChannelInboundHandler,输入数据处理器
 *
 * @author tom
 * @version V1.0
 * @date 2020/11/21 16:08
 */
public class NettyHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
    
    

    /**
     * 输入数据处理器
     *
     * @param context 通信管道的上下文
     * @param request netty处理channel的时候,只处理消息是FullHttpRequest的Channel,
     *                这样我们就能在一个ChannelHandler中处理一个完整的Http请求了。
     * @throws Exception
     */
    @Override
    protected void channelRead0(ChannelHandlerContext context, FullHttpRequest request) throws Exception {
    
    
        System.out.println("class:" + request.getClass().getName());
        // 生成response,这里使用的DefaultFullHttpResponse,同FullHttpRequest类似,通过这个我们就不用将response拆分成多个channel返回给请求端了。
        DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,
                HttpResponseStatus.OK,
                Unpooled.wrappedBuffer("hello my netty".getBytes()));

        HttpHeaders heads = response.headers();
        // 响应类型
        heads.add(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.TEXT_PLAIN + "; charset=UTF-8");
        // 添加header描述length,没有这一步,你会发现用postman发出请求之后就一直在刷新,因为http请求方不知道返回的数据到底有多长。
        heads.add(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());
        // 设置保持连接
        heads.add(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
        // channel读取完成之后需要输出缓冲流。如果没有这一步,你会发现postman同样会一直在刷新。
        context.write(response);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext context) throws Exception {
    
    
        System.out.println("通道数据读取完毕");
        super.channelReadComplete(context);
        context.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext context, Throwable cause) throws Exception {
    
    
        System.out.println("异常抓取");
        if(null != cause) cause.printStackTrace();
        if(null != context) context.close();
    }
    
}

运行NettyServer
浏览器输入http://localhost:1234/
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43073775/article/details/109909725