Netty Sharable Handler 使用私有变量
netty中Sharable handler的定义如下
http://netty.io/4.0/api/io/netty/channel/ChannelHandler.Sharable.html
我们不用每次都创建handler,例如下面的代码
public class InitChannel extends ChannelInitializer<SocketChannel> {
private final MessageEncoder messageEncoder = new MessageEncoder();
@Override
public void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline p = socketChannel.pipeline();
p.addLast(new JsonObjectDecoder());
p.addLast(messageEncoder);
}
}
其中messageEncoder就是一个sharable handler,而上面的JsonObjectdecoder不是一个sharable handler,从这里能够看到每次建立的channel时候都需要new 一个JsonObjectDecoder.而messageEncoder不需要。
但是,我们在使用sharable handler的时候,希望知道这个channel是对应的是哪个client的,希望把clientId记录下来。
@ChannelHandler.Sharable
public class SharedHander extends ChannelInboundHandlerAdapter {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(SharedHander.class);
private String client;
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
String s = (String)msg;
if (s.contains("firstMessage")) {
client = s;
} else {
logger.info("client-private: " + client + "\n receive: " + s);
}
}
}
我们利用多个客户端进行发送的时候
打印log 如下
十一月 24, 2015 11:28:42 上午 com.destinym.nettystudy.handler.sharehandlerdifferentvariable.SharedHander channelRead
信息: client-private: firstMessagedeviceId2sendMessage--deviceId2
receive: sendMessage--deviceId2
十一月 24, 2015 11:28:42 上午 com.destinym.nettystudy.handler.sharehandlerdifferentvariable.SharedHander channelRead
信息: client-private: firstMessagedeviceId2sendMessage--deviceId2
receive: sendMessage--deviceId1
十一月 24, 2015 11:28:47 上午 com.destinym.nettystudy.handler.sharehandlerdifferentvariable.SharedHander channelRead
信息: client-private: firstMessagedeviceId2sendMessage--deviceId2
receive: sendMessage--deviceId1
十一月 24, 2015 11:28:47 上午 com.destinym.nettystudy.handler.sharehandlerdifferentvariable.SharedHander channelRead
信息: client-private: firstMessagedeviceId2sendMessage--deviceId2
receive: sendMessage--deviceId2
可以看出来,无论是那个device发送的,最后结果都是deviceId2,因为是sharable的时候,多个channel会共享这个变量。
那么如果想保存自己的 channelId 需要怎么做呢?
我们参考下面的官方文档
http://netty.io/4.0/api/io/netty/channel/ChannelHandler.html
代码修改如下:
private static final InternalLogger logger = InternalLoggerFactory.getInstance(SharedHander.class);
private final AttributeKey<String> clientKey =
AttributeKey.valueOf("client");
private String client;
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
Attribute<String> attr = ctx.attr(clientKey);
String s = (String)msg;
if (s.contains("firstMessage")) {
client = s;
attr.set(s);
} else {
logger.info("client-private: " + client + "\n receive: " + s);
//logger.info("client-key: " + attr.get()+" \n receive :" + s);
}
}
我们再一次看下log:
十一月 24, 2015 11:34:36 上午 com.destinym.nettystudy.handler.sharehandlerdifferentvariable.SharedHander channelRead
信息: client-private: firstMessagedeviceId1sendMessage--deviceId1
receive: sendMessage--deviceId2
十一月 24, 2015 11:34:36 上午 com.destinym.nettystudy.handler.sharehandlerdifferentvariable.SharedHander channelRead
信息: client-key: firstMessagedeviceId2sendMessage--deviceId2
receive :sendMessage--deviceId2
十一月 24, 2015 11:34:36 上午 com.destinym.nettystudy.handler.sharehandlerdifferentvariable.SharedHander channelRead
信息: client-private: firstMessagedeviceId1sendMessage--deviceId1
receive: sendMessage--deviceId1
十一月 24, 2015 11:34:36 上午 com.destinym.nettystudy.handler.sharehandlerdifferentvariable.SharedHander channelRead
信息: client-key: firstMessagedeviceId1sendMessage--deviceId1
receive :sendMessage--deviceId1
看出来,使用attr能够得到我们想要的结果。
(注意对于private string client的内容,和最后赋值的客户端有关系)
全部代码可以在下面下载
https://github.com/destinym/netty.git