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

时间:2014-09-19 10:58:15

标签: java netty

我正在开发一个应用服务器,其中一部分将基于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();

}

1 个答案:

答案 0 :(得分:3)

这应该有效,因为它是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
        }
    }
}