在不同的上下文处理程序中使用通道属性



我正在开发一个应用服务器,其中一部分将基于Netty 4.0。然而,我遇到了一个通道共享变量的问题
我已经读到,要在其他上下文处理程序中使用这样的变量,我需要使用

  • context.channel().attr(键).set()

而不仅仅是

  • context.attr(键).set()

将我的变量附加到当前频道
像这里:

 public class HadlePackets extends ChannelInboundHandlerAdapter {
private static final Logger LOG = LoggerFactory.getLogger(HadlePackets.class);
public AttributeKey<Integer> clientIDattrKey = new AttributeKey<Integer>  ("ClientID");
@Override
public void channelRead(ChannelHandlerContext ctx, Object message) throws Exception {
 ...
ctx.channel().attr(clientIDattrKey).set(IDnum); //bind ID to channel
...
}
}

但是,如何在另一个上下文处理程序中检索变量的值?属性键仍然需要,我无法从附加变量的处理程序中获取它。

public class StorageHandler extends ChannelInboundHandlerAdapter{
private static final Logger LOG = LoggerFactory.getLogger(StorageSaveHandler.class);
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
    Integer clientID = (Integer)ctx.channel().attr(null).get(); //How can i get proper key for this channel attribute?
    ctx.fireChannelInactive();
}

这应该可以工作,因为它是public static:

@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
    Integer clientID = (Integer) ctx.channel().attr(HandlePackets.clientIDattrKey).get();
    ctx.fireChannelInactive();
}

下面是我如何使用它的一个小例子。不过这只是一个代码摘录:

public class NettyServer implements Runnable {
final static AttributeKey<Long> CHECKSUMKEY = AttributeKey.valueOf("calcchecksum");
final static AttributeKey<Command> COMMANDKEY = AttributeKey.valueOf("command");
final static AttributeKey<Long> FILEHANDLEKEY = AttributeKey.valueOf("filehandle");
final static AttributeKey<File> PATHKEY = AttributeKey.valueOf("destpath");
final static AttributeKey<FileOutputStream> OUTPUTSTREAM = AttributeKey.valueOf("stream");
@Override
public void run() {
    try {
        EventLoopGroup bossGroup = new NioEventLoopGroup(BOSS_THREADS);
        EventLoopGroup workerGroup = new NioEventLoopGroup(calculateThreadCount());
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            // This option will allow binding to an already bound ip:port
            // combination.
            // This is usually used to be able to restart a server if it
            // crashed/got killed
            // (so while the socket is still in the TIME_WAIT state).
            bootstrap.option(ChannelOption.SO_REUSEADDR, true);
            bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                public void initChannel(SocketChannel ch) throws Exception {
                    ch.pipeline().addLast("ObjectDecoder", new ObjectDecoder(ClassResolvers.cacheDisabled(null)));
                    ch.pipeline().addLast("ObjectEncoder", new ObjectEncoder());
                    ch.pipeline().addLast("CommandHandler", new ServerCommandHandler(server, logger));
                    ch.pipeline().addLast("FileHandler", new ServerFileHandler(server, logger));
                    ch.pipeline().addLast("ChecksumHandler", new ServerChecksumHandler(server, logger));
                }
            });
            try {
                // Bind and start to accept incoming connections.
                bootstrap.bind(port).sync().channel().closeFuture().sync();
            } catch (InterruptedException e) {
                logger.debug(Message.CMDTRANSFER_INTERRUPTED_DEBUG, e.getMessage());
            }
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    } catch (Exception e) {
        logger.error(Message.CMDTRANSFER_CONNECT_ERROR, e.getMessage());
    }
}
}

正如您所看到的,我有几个处理程序共享通道的属性。

public class ServerCommandHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ctx.channel().attr(NettyServer.COMMANDKEY).set(clCommand);
        ctx.fireChannelRead(msg);
    }
}
public class ServerChecksumHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if ctx.channel().attr(NettyServer.COMMANDKEY).getAndRemove() == referenceCommand {
            //do something
        }
    }
}

最新更新