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); }