我正在开发一个应用服务器,其中一部分将基于Netty 4.0。但是,我遇到了频道共享变量的问题 我已经读过在我需要使用的其他上下文处理程序中使用这些变量
而不仅仅是
将我的变量附加到当前频道。
像这里:
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();
}
答案 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
}
}
}