1)AttributeMap这是是绑定在Channel或者ChannelHandlerContext上的一个附件,相当于依附在这两个对象上的寄生虫一样,相当于附件一样,如图所示:
这个图还算比较形象地描述了AttributeMap的作用,我们知道每一个ChannelHandlerContext都是ChannelHandler和ChannelPipeline之间连接的桥梁,每一个ChannelHandlerContext都有属于自己的上下文,也就说每一个ChannelHandlerContext上如果有AttributeMap都是绑定上下文的,也就说如果A的ChannelHandlerContext中的AttributeMap,B的ChannelHandlerContext是无法读取到的
但是Channel上的AttributeMap就是大家共享的,每一个ChannelHandler都能获取到
我们再看看AttributeMap的结构:
可以看出这个是线程安全的,所以我们可以放心使用,再看看AttributeMap的结构,其实和Map的格式很像,key是AttributeKey,value是Attribute,我们可以根据AttributeKey找到对应的Attribute,并且我们可以指定Attribute的类型T:
下面截取了两种AttributeKey的用法的部分代码.
private AttributeKey<String> key = AttributeKey.valueOf("Id");
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
Attribute<String> channelAttr = ctx.channel().attr(key);
Attribute<String> contextAttr = ctx.attr(key);
//基于channel的属性
if(channelAttr.get() == null){
channelAttr.set("1");
}else{
System.out.println("channel key :"+channelAttr.get());
}
//基于context的属性
if(contextAttr.get() == null){
contextAttr.set("1");
}else{
System.out.println("contextAttr key :"+contextAttr.get());
}
ByteBuf buf = (ByteBuf) msg;
byte[] req = new byte[buf.readableBytes()];
buf.readBytes(req);
String body = new String(req,"UTF-8").substring(0,
req.length-System.getProperty("line.separator").length());
System.out.println("server channelRead...; received:" + body + ";the counter is" + counter++);
String currentTime = "QUERY TIME ORDDER".equalsIgnoreCase(body)
?new Date(System.currentTimeMillis()).toString():"BAD ORDER";
ByteBuf resp = Unpooled.copiedBuffer(currentTime.getBytes());
ctx.writeAndFlush(resp);
}