一.学习Netty之ChannelHandler接口

本文深入探讨Netty中ChannelHandler的作用及其实现方式,解析如何处理读写事件、动态修改pipeline,以及通过AttributeKeys进行状态管理。对比不同场景下DataServerHandler的实例化策略,阐述其在多连接环境中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

他的作用是处理一些io事件,或者阻止一些io操作,并且跳转到ChannelPipeline的下一个handler去

通常情况下,我们不会选择是实现这个接口,而是继承ChannelHandlerAdapter

ChannelHandler 通常会提供一个 ChannelHandlerContext. 所以你会看到ChannelHandler的每一个方法都有一个参数ChannelHandlerContext

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

你可以用他取代成员变量来保存一些信息,他是附属于ChannelHandlerContext

 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();
               }
           }
       }
       ...
   }

下面这个比较有意思

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一个,而这里直接是一个静态的成员变量,也就是说可以共享的.

他们的区别仅仅是,前一节的DataServerHandler 使用了一个private boolean loggedIn; 来保存登录状态,而这里使用了一个AttributeKey.因为前一个DataServerHandler的状态是不能共享的,每个都应该有一个,如果共用一个,岂不是有一个人登录了,所有人都登录了?而AttributeKey是跟上下文绑定在一起,上下文每一个连接都有一个,所以不冲突

另外,我们注意到,@Sharable 这个注解被加在了本节的DataServerHandler 上,这表明他是可以共享的

转载于:https://my.oschina.net/u/1777377/blog/524225

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值