Netty的ChannelHandler,ChannelHandlerContext,ChannelPipeline

In this section, we will learn about the three commonly used components of Netty, ChannelHandler, ChannelHandlerContext, and ChannelPipeline. Without exploring their underlying source code, we will briefly analyze the usage.

 

First of all, let's analyze ChannelHandler. ChannelHandler is the most used component in our daily development. Probably the most commonly written component is Handler. The inheritance diagram is as follows

 

The ones we usually inherit the most are ChannelInboundHandlerAdapter and ChannelOutboundHandlerAdapter. These two are neither interfaces nor abstract classes, so we can just rewrite the methods we need, and there are no methods that must be implemented. Of course, we will also use SimpleChannelInboundHandler. This section also talks a little about its advantages and disadvantages, so I won't go into details here.

 

The relationship between ChannelHandler, ChannelHandlerContext, and ChannelPipeline is very special and complement each other. There can be multiple ChannelHandler instances in a ChannelPipeline, and the bridge between each ChannelHandler instance and ChannelPipeline is the ChannelHandlerContext instance, as shown in the figure:

You can see the importance of ChannelHandlerContext from the picture. If you get an instance of ChannelHandlerContext, you can get everything you want. You can execute the methods in ChannelHandler according to ChannelHandlerContext. For example, we can see API under the ChannelHandlerContext section:

These APIs are used frequently. They all call a method in the same type of channel after the current handler. The same type here refers to the same direction. For example, inbound calls inbound, and outbound calls outbound type channel. Generally speaking, fireChannelActive is called in the ChannelActive method of a channel to trigger the call to the ChannelActive method in the next handler.

 

For example, we modify part of the code in the Helloworld version, and modify the code in the channel in the client

First, let's modify the bootstrap startup class code:

 

[html]  view plain copy  
 
  1. try {  
  2.             Bootstrap b = new Bootstrap();  
  3.             b.group(group)  
  4.              .channel(NioSocketChannel.class)  
  5.              .option(ChannelOption.TCP_NODELAY, true)  
  6.              .handler(new ChannelInitializer<SocketChannel>() {  
  7.                  @Override  
  8.                  public void initChannel(SocketChannel ch) throws Exception {  
  9.                      ChannelPipeline p = ch.pipeline();  
  10.                      p.addLast("decoder", new StringDecoder());  
  11.                      p.addLast("encoder", new StringEncoder());  
  12.                      p.addLast(new BaseClient1Handler());  
  13.                      p.addLast(new BaseClient2Handler());  
  14.                  }  
  15.              });  
  16.   
  17.             ChannelFuture future = b.connect(HOST, PORT).sync();  
  18.             future.channel().writeAndFlush("Hello Netty Server ,I am a common client");  
  19.             future.channel().closeFuture().sync();  
  20.         } finally {  
  21.             group.shutdownGracefully();  
  22.         }  

We added two custom BaseClient1Handler and BaseClient2Handler processors to the channelhandler chain

 

The method of BaseClient1Handler is also very simple:

BaseClient1Handler.java

 

[java]  view plain copy  
 
  1. package com.lyncc.netty.component.channelhandler;  
  2.   
  3. import io.netty.channel.ChannelHandlerContext;  
  4. import io.netty.channel.ChannelInboundHandlerAdapter;  
  5.   
  6. /** 
  7.  *  
  8.  * @author bazingaLyncc 
  9.  * Description: The client's first custom inbound handler 
  10.  * Date May 3, 2016 
  11.  */  
  12. public class BaseClient1Handler extends ChannelInboundHandlerAdapter{  
  13.       
  14.     @Override  
  15.     public void channelActive(ChannelHandlerContext ctx) throws Exception {  
  16.         System.out.println("BaseClient1Handler channelActive");  
  17. //        ctx.fireChannelActive();  
  18.     }  
  19.       
  20.     @Override  
  21.     public void channelInactive(ChannelHandlerContext ctx) throws Exception {  
  22.         System.out.println("BaseClient1Handler channelInactive");  
  23.     }  
  24.   
  25. }  

BaseClient2Handler.java

 

 

[java]  view plain copy  
 
  1. package com.lyncc.netty.component.channelhandler;  
  2.   
  3. import io.netty.channel.ChannelHandlerContext;  
  4. import io.netty.channel.ChannelInboundHandlerAdapter;  
  5.   
  6. /** 
  7.  *  
  8.  * @author bazingaLyncc 
  9.  * Description: The second custom inbound handler for the client 
  10.  * Date May 3, 2016 
  11.  */  
  12. public class BaseClient2Handler extends ChannelInboundHandlerAdapter{  
  13.       
  14.     @Override  
  15.     public void channelActive(ChannelHandlerContext ctx) throws Exception {  
  16.         System.out.println("BaseClient2Handler Active");  
  17.     }  
  18.       
  19.      
  20.   
  21. }  

If the other codes are not modified, we start the server side first, then start the client side, and you will find that the console prints:

 

The output statement in the channelActive method in the BaseClient2Handler class will not be printed. If you want to print, you can uncomment the ctx.fireChannelActive() of channelActive in BaseClient1Handler. Rerun:

That is to say, if there are multiple channelHandlers in a channelPipeline, and these channelHandlers have the same method, such as the channelActive method here, only the channelActive method in the first channelHandler will be called. If you want to call subsequent The method of the same name of the channelHandler needs to call the method starting with "fire", which is very flexible.

 

The benefits of doing this so far:

1) Each handler only needs to pay attention to the method to be processed. If you do not pay attention to the channelActive method, your custom channelhandler does not need to override the channelActive method

2) Exception handling, if the exceptionCaught method is rewritten for each handler, it only needs to have a class to catch it and then deal with it, no need for each handler to process it again

3) Flexibility. For example, as shown in the following figure:

As shown in the figure, in the business logic processing, maybe the first ChannelHandler on the left does not need to manage a business logic at all, but the second ChannelHandler needs to pay attention to processing a business requirement, so it can be flexibly started from the first ChannelHandler. The two ChannelHandlers start processing business, and there is no need to start processing from the first ChannelHandler in the channel, which will make the code seem incomprehensible~

 

The relationship between ChannelHandler, ChannelHandlerContext, and ChannelPipeline that I understand at first glance is summarized as above

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324734859&siteId=291194637