AttributeMap属性.docx
- 文档编号:29179621
- 上传时间:2023-07-21
- 格式:DOCX
- 页数:5
- 大小:16.49KB
AttributeMap属性.docx
《AttributeMap属性.docx》由会员分享,可在线阅读,更多相关《AttributeMap属性.docx(5页珍藏版)》请在冰豆网上搜索。
AttributeMap属性
AttributeMap属性
本来没打算研究这个东西的,一开始觉得没啥用,甚至觉得这个东西有点鸡肋,不过慢慢接触之后,发现了这个AttributeMap的重要性初学这个东西,我们还是先理解AttributeMap的用法吧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:
我们可以这样使用:
1)首先定义一个AttributeKey:
[java]viewplaincopypublicstaticfinalAttributeKey<NettyChannel>NETTY_CHANNEL_KEY=AttributeKey.valueOf("netty.channel");我们AttributeMap中存储的是NettyChannel,这是我们自定义的一个类:
[java]viewplaincopypackagety.attributeMap;importjava.util.Date;publicclassNettyChannel{privateStringname;privateDatecreateDate;publicNettyChannel(Stringname,DatecreateDate){this.name=name;this.createDate=createDate;}publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}publicDategetCreateDate(){returncreateDate;}publicvoidsetCreateDate(DatecreateDate){this.createDate=createDate;}}那么我们可以这么使用ChannelHandler中这么使用:
[java]viewplaincopy@OverridepublicvoidchannelActive(ChannelHandlerContextctx){Attribute<NettyChannel>attr=ctx.attr(NETTY_CHANNEL_KEY);NettyChannelnChannel=attr.get();if(nChannel==null){NettyChannelnewNChannel=newNettyChannel("HelloWorld0Client",newDate());nChannel=attr.setIfAbsent(newNChannel);}else{System.out.println("attributeMap中是有值的");System.out.println(nChannel.getName()+"======="+nChannel.getCreateDate());}System.out.println("HelloWorldC0ientHandlerActive");ctx.fireChannelActive();}channelActive方法中的ChannelHandlerContext方法可以使用attr方法传入AttributeKey获取一个Attribute,如果我们之前没有赋值,那么此时的Attribute值应该是null,我们就创建一个NettyChannel,并使用setIfAbsent这个方法,这个方法是线程安全的,大体的使用方法就是如此现在我们举两个简单的例子1)测试ChannelHandler上的AttributeMap是不是上下文绑定的------------首先我们在客户端写两个自定义的ChannelHandler方法,这两个方法的的ChannelActive都会在ChannelHandlerContext上的AttributeMap上写一些属性,然后在对应的ChannelRead方法上读取对应的值,看其是否能读取到:
我们先贴服务端的代码。
很简单:
[java]viewplaincopypackagety.attributeMap;importty.bootstrap.ServerBootstrap;importty.channel.ChannelFuture;importty.channel.ChannelInitializer;importty.channel.ChannelOption;importty.channel.EventLoopGroup;importty.channel.nio.NioEventLoopGroup;importty.channel.socket.SocketChannel;importty.channel.socket.nio.NioServerSocketChannel;importty.handler.codec.string.StringDecoder;importty.handler.codec.string.StringEncoder;import.InetSocketAddress;publicclassHelloWorldServer{privateintport;publicHelloWorldServer(intport){this.port=port;}publicvoidstart(){EventLoopGroupbossGroup=newNioEventLoopGroup
(1);EventLoopGroupworkerGroup=newNioEventLoopGroup();try{ServerBootstrapsbs=newServerBootstrap().group(bossGroup,workerGroup).channel(NioServerSocketChannel.class).localAddress(newInetSocketAddress(port)).childHandler(newChannelInitializer<SocketChannel>(){protectedvoidinitChannel(SocketChannelch)throwsException{ch.pipeline().addLast("decoder",newStringDecoder());ch.pipeline().addLast("encoder",newStringEncoder());ch.pipeline().addLast(newHelloWorldServerHandler());};}).option(ChannelOption.SO_BACKLOG,128).childOption(ChannelOption.SO_KEEPALIVE,true);//绑定端口,开始接收进来的连接ChannelFuturefuture=sbs.bind(port).sync();System.out.println("Serverstartlistenat"+port);future.channel().closeFuture().sync();}catch(Exceptione){bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}publicstaticvoidmain(String[]args)throwsException{intport;if(args.length>0){port=Integer.parseInt(args[0]);}else{port=8080;}newHelloWorldServer(port).start();}}Channel:
[java]viewplaincopypackagety.attributeMap;importty.channel.ChannelHandlerContext;importty.channel.ChannelInboundHandlerAdapter;publicclassHelloWorldServerHandlerextendsChannelInboundHandlerAdapter{@OverridepublicvoidchannelRead(ChannelHandlerContextctx,Objectmsg)throwsException{System.out.println("serverchannelRead..");System.out.println(ctx.channel().remoteAddress()+"->Server:
"+msg.toString());ctx.write("serverwrite"+msg);ctx.flush();}@OverridepublicvoidexceptionCaught(ChannelHandlerContextctx,Throwablecause)throwsException{cause.printStackTrace();ctx.close();}}客户端的bootstrap代码:
[java]viewplaincopypackagety.attributeMap;importty.bootstrap.Bootstrap;importty.channel.ChannelFuture;importty.channel.ChannelInitializer;importty.channel.ChannelOption;importty.channel.ChannelPipeline;importty.channel.EventLoopGroup;importty.channel.nio.NioEventLoopGroup;importty.channel.socket.SocketChannel;importty.channel.socket.nio.NioSocketChannel;importty.handler.codec.string.StringDecoder;importty.handler.codec.string.StringEncoder;publicclassHelloWorldClient{staticfinalStringHOST=System.getProperty("host","127.0.0.1");staticfinalintPORT=Integer.parseInt(System.getProperty("port","8080"));staticfinalintSIZE=Integer.parseInt(System.getProperty("size","256"));publicstaticvoidmain(String[]args)throwsException{initChannel();}publicstaticvoidinitChannel()throwsInterruptedException{//Configuretheclient.EventLoopGroupgroup=newNioEventLoopGroup();try{Bootstrapb=newBootstrap();b.group(group).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY,true).handler(newChannelInitializer<SocketChannel>(){@OverridepublicvoidinitChannel(SocketChannelch)throwsException{ChannelPipelinep=ch.pipeline();p.addLast("decoder",newStringDecoder());p.addLast("encoder",newStringEncoder());p.addLast(newHelloWorldClientHandler());p.addLast(newHelloWorld2ClientHandler());}});ChannelFuturefuture=b.connect(HOST,PORT).sync();future.channel().writeAndFlush("helloNetty,TestattributeMap");future.channel().closeFuture().sync();}finally{group.shutdownGracefully();}}}一个常量类:
[java]viewplaincopypackagety.attributeMap;importty.util.AttributeKey;publicclassAttributeMapConstant{publicstaticfinalAttributeKey<NettyChannel>NETTY_CHANNEL_KEY=AttributeKey.valueOf("netty.channel");}两个客户端的handler:
[java]viewplaincopypackagety.attributeMap;importstaticty.attributeMap.AttributeMapConstant.NETTY_CHANNEL_KEY;importty.channel.ChannelHandlerContext;importty.channel.ChannelInboundHandlerAdapter;importty.util.Attribute;importjava.util.Date;publicclassHelloWorldClientHandlerextendsChannelInboundHandlerAdapter{@OverridepublicvoidchannelActive(ChannelHandlerContextctx){Attribute<NettyChannel>attr=ctx.attr(NETTY_CHANNEL_KEY);NettyChannelnChannel=attr.get();if(nChannel==null){NettyChannelnewNChannel=newNettyChannel("HelloWorld0Client",newDate());nChannel=attr.setIfAbsent(newNChannel);}else{System.out.println("channelActiveattributeMap中是有值的");System.out.println(nChannel.getName()+"======="+nChannel.getCreateDate());}System.out.println("HelloWorldC0ientHandlerActive");ctx.fireChannelActive();}@OverridepublicvoidchannelRead(ChannelHandlerContextctx,Objectmsg){Attribute<NettyChannel>attr=ctx.attr(NETTY_CHANNEL_KEY);NettyChannelnChannel=attr.get();if(nChannel==null){NettyChannelnewNChannel=newNettyChannel("HelloWorld0Client",newDate());nChannel=attr.setIfAbsent(newNChannel);}else{System.out.println("channelReadattributeMap中是有值的");System.out.println(nChannel.getName()+"======="+nChannel.getCreateDate());}System.out.println("HelloWorldClientHandlerreadMessage:
"+msg);ctx.fireChannelRead(msg);}@OverridepublicvoidexceptionCaught(ChannelHandlerContextctx,Throwablecause){cause.printStackTrace();ctx.close();}}handler2:
[java]viewplaincopypackagety.attributeMap;importstaticty.attributeMap.AttributeMapConstant.NETTY_CHANNEL_KEY;importty.channel.ChannelHandlerContext;importty.channel.ChannelInboundHandlerAdapter;importty.util.Attribute;importjava.util.Date;publicclassHelloWorld2ClientHandlerextendsChannelInboundHandlerAdapter{@OverridepublicvoidchannelActive(ChannelHandlerContextctx){Attribute<NettyChannel>attr=ctx.attr(NETTY_CHANNEL_KEY);NettyChannelnChannel=attr.get();if(nChannel==null){NettyChannelnewNChannel=newNettyChannel("HelloWorld2Client",newDate());nChannel=attr.setIfAbsent(newNChannel);}else{System.out.println("channelActiveattributeMap中是有值的");System.out.println(nChannel.getName()+"======="+nChannel.getCreateDate());}System.out.println("HelloWorldC2ientHandlerActive");ctx.fireChannelActive();}@OverridepublicvoidchannelRead(ChannelHandlerContextctx,Objectmsg){Attribute<NettyChannel>attr=ctx.attr(NETTY_CHANNEL_KEY);NettyChannelnChannel=attr.get();if(nChannel==null){NettyChannelnewNChannel=newNettyChannel("HelloWorld0Client",newDate());nChannel=attr.setIfAbsent(newNChannel);}else{System.out.println("channelReadattributeMap中是有值的");System.out.println(nChannel.getName()+"======="+nChannel.getCreateDate());}System.out.println("HelloWorldClientHandlerreadMessage:
"+msg);}@OverridepublicvoidexceptionCaught(ChannelHandlerContextctx,Throwablecause){cause.printStackTrace();ctx.close();}}我们先运行服务器端:
客户端控制台:
这说明每个ChannelHandlerContext上的AttributeMap是相互不影响的2)测试Channel上的Attr
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- AttributeMap 属性