一.學習Netty之ChannelHandler接口

他的做用是處理一些io事件,或者阻止一些io操做,而且跳轉到ChannelPipeline的下一個handler去ide

一般狀況下,咱們不會選擇是實現這個接口,而是繼承ChannelHandlerAdapterfetch

ChannelHandler 一般會提供一個 ChannelHandlerContext. 因此你會看到ChannelHandler的每個方法都有一個參數ChannelHandlerContextcode

ChannelHandler能夠處理讀寫事件, 動態的修改pipeline, 存儲一些數據到handler上(用AttributesKey)繼承

狀態管理

一個ChannelHandler一般須要存儲一些狀態信息,最簡單的方式就是保存到成員變量裏,如是否登陸過了?接口

在這裏,是否登陸過了這個狀態信息是每個connection都須要的,因此,咱們要爲每個channel建立一個handler的實例,事件

// Create a new handler instance per channel.
   // See ChannelInitializer.initChannel(Channel).
   public class DataServerInitializer extends ChannelInitializer<Channel> {
        @Override
       public void initChannel(Channel channel) {
           channel.pipeline().addLast("handler", new DataServerHandler());
       }
   }

使用 AttributeKeys

你能夠用他取代成員變量來保存一些信息,他是附屬於ChannelHandlerContextip

public interface Message {
       // your methods here
   }
  
    @Sharable
   public class DataServerHandler extends SimpleChannelInboundHandler<Message> {
       private final AttributeKey<Boolean> auth =
             AttributeKey.valueOf("auth");
  
        @Override
       protected void messageReceived(ChannelHandlerContext ctx, Message message) {
           Attribute<Boolean> attr = ctx.attr(auth);
           Channel ch = ctx.channel();
  
           if (message instanceof LoginMessage) {
               authenticate((LoginMessage) o);
               attr.set(true);
           } else (message instanceof GetDataMessage) {
               if (Boolean.TRUE.equals(attr.get())) {
                   ch.write(fetchSecret((GetDataMessage) o));
               } else {
                   fail();
               }
           }
       }
       ...
   }

下面這個比較有意思get

Now that the state of the handler is attached to the ChannelHandlerContext, you can add the same handler instance to different pipelines:
   public class DataServerInitializer extends ChannelInitializer<Channel> {
  
       private static final DataServerHandler SHARED = new DataServerHandler();
  
        @Override
       public void initChannel(Channel channel) {
           channel.pipeline().addLast("handler", SHARED);
       }
   }

這裏和上一節狀態管理的代碼有些區別,都是DataServerHandler 爲何哪裏的須要每次都new一個,而這裏直接是一個靜態的成員變量,也就是說能夠共享的.it

他們的區別僅僅是,前一節的DataServerHandler 使用了一個private boolean loggedIn; 來保存登陸狀態,而這裏使用了一個AttributeKey.由於前一個DataServerHandler的狀態是不能共享的,每一個都應該有一個,若是共用一個,豈不是有一我的登陸了,全部人都登陸了?而AttributeKey是跟上下文綁定在一塊兒,上下文每個鏈接都有一個,因此不衝突pip

另外,咱們注意到,@Sharable 這個註解被加在了本節的DataServerHandler 上,這代表他是能夠共享的

相關文章
相關標籤/搜索