我正在开发一个应用服务器,其中一部分将基于 Netty 4.0。但是,我遇到了 channel 共享变量的问题。
我读过要在我需要使用的其他上下文处理程序中使用此类变量
- context.channel().attr(key).set()
不仅仅是
- context.attr(key).set()
将我的变量附加到当前 channel 。
喜欢这里:
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());
}
}
}
如您所见,我有几个共享 channel 属性的处理程序。
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
}
}
}
关于java - 在不同的上下文处理程序中使用 channel 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25932352/