一.学习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 上,这代表他是能够共享的

相关文章
相关标签/搜索