Nettyå¦Âä½Âå®Âç°èªå®Âä¹ÂéÂÂä¿¡åÂÂè®®
å¨å¦习å®Âå¦Âä½Â设计åÂÂè®®ä¹ÂÃ¥ÂÂï¼ÂæÂÂ们åÂÂ该å¦Âä½Âå¨ Netty ä¸Âå®Âç°èªå®Âä¹ÂçÂÂéÂÂä¿¡åÂÂè®®å¢ï¼Â堶宠Netty ä½Â为ä¸Â个éÂÂ常ä¼Âç§ÂçÂÂç½Âç»ÂéÂÂä¿¡æ¡Âæ¶ï¼Âå·²ç»Â为æÂÂ们æÂÂä¾ÂäºÂéÂÂ常丰å¯ÂçÂÂç¼Â解ç Âæ½象åº类ï¼Â帮å©æÂÂ们æ´æ¹便å°åºäºÂè¿ÂäºÂæ½象åº类æ©å±Âå®Âç°èªå®Âä¹ÂÃ¥ÂÂè®®ãÂÂ
é¦Âå ÂæÂÂ们çÂÂ丠Netty ä¸Â常ç¨çÂÂç¼Â解ç Âå¨æÂÂåªäºÂãÂÂ
ä¸Â次ç¼Â解ç Âå¨åÂÂäºÂ次ç¼Â解ç Âå¨
Nettyä¸ÂçÂÂç¼Â解ç Âå¨åÂÂ为ä¸Â次ç¼Â解ç ÂÃ¥ÂÂäºÂ次ç¼Â解ç ÂãÂÂ
ä¸Â次ç¼Â解ç Âå¨ï¼ÂMessageToByteEncoderãÂÂByteToMessageDecoder/ReplyingDecoder
äºÂ次ç¼Â解ç Âå¨ï¼ÂMessageToMessageEncoderãÂÂMessageToMessageDecoder
以解ç Â为ä¾Âï¼Âä¸Â次解ç Âå¨ç¨äºÂ解å³TCPæÂÂå /ç²Âå é®é¢Âï¼Â解æÂÂå¾Âå°åÂÂèÂÂæ°æ®ãÂÂ
å¦ÂæÂÂéÂÂè¦Â对解æÂÂÃ¥ÂÂçÂÂÃ¥ÂÂèÂÂæ°æ®åÂÂ对象转æ¢ï¼ÂéÂÂè¦Â使ç¨äºÂ次解ç Âå¨ãÂÂÃ¥ÂÂçÂÂï¼Âç¼Âç Âå¨æ¯ç¸åÂÂè¿Âç¨ÂãÂÂ
为ä»Âä¹ÂéÂÂè¦ÂäºÂ次ç Â/ç¼Âç Â
Ã¥ÂÂ设æÂÂ们æÂÂ解å³åÂÂå ç²Âå é®é¢ÂçÂÂ常ç¨ä¸Âç§Â解ç Âå¨å«ä¸Â次解ç Âå¨ï¼Â
é£ä¹ÂæÂÂ们å¨项ç®ä¸Âï¼Âé¤äºÂå¯éÂÂçÂÂçÂÂÃ¥ÂÂ缩解åÂÂ缩ä¹Âå¤Âï¼Âè¿ÂéÂÂè¦Âä¸Âå±Â解ç Âï¼Âå 为ä¸Â次解ç ÂçÂÂç»ÂæÂÂæ¯åÂÂèÂÂï¼ÂéÂÂè¦ÂÃ¥ÂÂ项ç®ä¸ÂæÂÂ使ç¨çÂÂ对象åÂÂ转åÂÂï¼Âæ¹便使ç¨ï¼Âè¿Âå±Â解ç Âå¨å¯以称为âÂÂäºÂ次解ç Âå¨âÂÂãÂÂ
ç¸åºÂçÂÂï¼Â对åºÂçÂÂäºÂ次ç¼Âç Âå¨æ¯为äºÂå° Java 对象转åÂÂæÂÂÃ¥ÂÂèÂÂæµÂæ¹便åÂÂå¨æÂÂä¼ è¾ÂãÂÂ
为ä»Âä¹Âä¸ÂÃ¥ÂÂ并ä¸Â次äºÂ次解ç Âå¨
æÂÂèÂÂï¼Âæ¯ä¸Âæ¯ä¹Âå¯以ä¸ÂæÂ¥å°ä½Âï¼ åÂÂ并 1 次解ç Âï¼Â解å³ç²Âå ãÂÂÃ¥ÂÂå ï¼Âå 2 次解ç Âï¼Â解å³å¯æÂÂä½Âé®é¢Âï¼Â
å¯以ï¼Âä½Âæ¯ä¸Â建议@â¢没æÂÂÃ¥ÂÂå±Âï¼Âä¸Âå¤Â渠æ°;Ã¥ÂÂå±Âå¯以ç»ÂÃ¥ÂÂã â¢è¦åÂÂæ§é«Âï¼Âä¸Â容æÂÂç½®æ¢æ¹æ¡ÂãÂÂ
常ç¨çÂÂç¼Â解ç Âæ¹å¼Â
-Java åºÂÃ¥ÂÂÃ¥ÂÂ
-Marshaling
-XML
-JSON
-MessagePack
-Protobuf
-å ¶ä»Â
éÂÂæ©ç¼Â解ç Âæ¹å¼ÂçÂÂå ç´Â
-空é´ï¼Âç¼Âç ÂÃ¥ÂÂå ç¨空é´ -æ¶é´ï¼Âç¼Â解ç ÂéÂÂ度 -æ¯å¦追æ±Âå¯读æ§ -æ¯å¦æ¯æÂÂå¤Âè¯Âè¨Â,ä¾Âå¦ÂmsgpackçÂÂæ¯æÂÂ:Java\C\PythonçÂÂ
Protobuf
-Protobuf æ¯ä¸Â个çµ活çÂÂãÂÂé«ÂæÂÂçÂÂç¨äºÂåºÂÃ¥ÂÂÃ¥ÂÂæ°æ®çÂÂÃ¥ÂÂè®®ãÂÂ
-ç¸æ¯Âè¾ XML å JSON æ ¼å¼Âï¼ÂProtobuf æ´å°ÂãÂÂæ´快ãÂÂæ´便æ·ãÂÂ
-Protobuf æ¯跨è¯Âè¨ÂçÂÂï¼Â并ä¸Âèª带äºÂä¸Â个ç¼Âè¯Âå¨ï¼Âprotocï¼Âï¼ÂåªéÂÂè¦Âç¨å®Âè¿Âè¡Âç¼Âè¯Âï¼Âå¯以èªå¨çÂÂæ JavaãÂÂpythonãÂÂC++ çÂÂ代ç Âï¼Âä¸ÂéÂÂè¦ÂÃ¥ÂÂÃ¥ÂÂå ¶ä»Â代ç ÂãÂÂ
Protobuf使ç¨æ¥骤
第1æÂ¥ï¼Âå¨Maven 项ç®ä¸Âå¼Âå ¥ Protobuf Ã¥ÂÂæ Âï¼Âä¸Âè½½ç¸堳çÂÂjarå ãÂÂ
å¨pom.xml丠添å ä¾ÂèµÂ
<dependencies>
<dependency>
ÃÂ ÃÂ <groupId>com.google.protobuf</groupId>
ÃÂ ÃÂ <artifactId>protobuf-java</artifactId>
ÃÂ ÃÂ <version>3.6.1</version>
</dependency>
</dependencies>
第 2 æ¥@ç¼ÂÃ¥ÂÂprotoæÂÂ件:Student.protoãÂÂ
Student.protoçÂÂå 容
syntax = "proto3"; //çÂÂæ¬
option java_outer_classname = "StudentPoJO"; //æÂÂå®ÂçÂÂæÂÂçÂÂJavaç±»åÂÂ
//Ã¥ÂÂ
é¨类çÂÂÃ¥ÂÂ称ï¼Âæ¯çÂÂæ£çÂÂPoJo ç±»
message Student{ // message çÂÂè§Âå®ÂçÂÂ
àint32 id = 1; //PoJo ç±»çÂÂå±Âæ§æ°æ®类åÂÂç±»åÂÂå åºÂå·(ä¸Âæ¯å±Âæ§å¼)
ÃÂ string name = 2;
}
第 3 æÂ¥ï¼ÂéÂÂè¿ protoc.exe æ ¹æ®æÂÂè¿°æÂÂ件çÂÂæ Java ç±»ãÂÂ
说æÂÂï¼Âprotoc-3.6.1-win32 æ¯ä»Âç½Âä¸Âä¸Âè½½ç google æÂÂä¾ÂçÂÂæÂÂ件.
cmdæ§è¡Âå½令çÂÂæÂÂStudentPoJO.java: C:\Users\Administrator\Desktop\NettyèµÂæÂÂ\æÂÂçÂÂ\èµÂæÂÂ\protoc-3.6.1-win32\bin>protoc.exe –java_out=. Student.proto
第4æÂ¥ï¼ÂæÂÂçÂÂæÂÂç StudentPoJo.java æ·è´Âå°èª己çÂÂ项ç®ä¸ÂæÂÂå¼ÂãÂÂ
第 5 æÂ¥ï¼Âå¨ Netty ä¸Â使ç¨ãÂÂ
ch.pipeline().addLast(new ProtobufVarint32FrameDecoder());
ch.pipeline().addLast(new ProtobufDecoder(StudentPoJO.Student.getDefaultInstance()));
âÂÂ
ch.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender());
ch.pipeline().addLast(new ProtobufEncoder());
æ½象ç¼Âç Âç±»
æÂÂæÂÂçÂÂ解ç Âå¨é½继æ¿äºÂChannelInBoundHandlerãÂÂå 为解ç Âæ¯éÂÂè¦Â解ç ÂæÂ¥æ¶çÂÂæ°æ®ãÂÂæÂÂ以使ç¨InãÂÂ
æÂÂæÂÂçÂÂç¼Âç Âå¨é½继æ¿äºÂChannelOutBoundHandlerãÂÂå 为ç¼Âç Âæ¯éÂÂè¦Âå°Â对å¤ÂÃ¥ÂÂéÂÂçÂÂæ°æ®ç¼Âç ÂãÂÂæÂÂ以使ç¨OutãÂÂ
éÂÂè¿Âæ½象ç¼Âç Âç±»çÂÂ继æ¿å¾å¯以çÂÂåºç¼Âç Âç±»æ¯ ChanneOutboundHandler çÂÂæ½象类å®Âç°,å ·ä½ÂæÂÂä½ÂçÂÂæ¯ Outbound åºç«Âæ°æ®ãÂÂ
常ç¨ç¼Âç Âå¨类åÂÂ
- MessageToByteEncoder 对象ç¼Âç ÂæÂÂÃ¥ÂÂèÂÂæµÂï¼Â
- MessageToMessageEncoder ä¸Âç§Â对象æ¶Âæ¯类åÂÂç¼Âç ÂæÂÂå¦å¤Âä¸Âç§Â对象æ¶Âæ¯类åÂÂãÂÂ
使ç¨ä¸Â次ç¼Âç Âå¨IntegerEncoderÃ¥ÂÂäºÂ次ç¼Âç Âå¨IntegerToStringEncoder,å°Âæ¶Âæ¯ä»ÂIntegerç¼Âç Â为StringãÂÂ
class IntegerEncoder extends MessageToByteEncoder<Integer> {
ÃÂ ÃÂ @Override
ÃÂ ÃÂ public void encode(ChannelHandlerContext ctx, Integer msg, ByteBuf out) throws Exception {
ÃÂ ÃÂ ÃÂ ÃÂ out.writeInt(msg);
ÃÂ }
}
âÂÂ
class IntegerToStringEncoder extends MessageToMessageEncoder<Integer> {
ÃÂ ÃÂ @Override
ÃÂ ÃÂ public void encode(ChannelHandlerContext ctx, Integer message, List<Object> out) throws Exception {
ÃÂ ÃÂ ÃÂ ÃÂ out.add(message.toString());
ÃÂ }
}
使ç¨ä¸Â次ç¼Âç Âå¨StringEncoderÃ¥ÂÂäºÂ次ç¼Âç Âå¨StringToIntegerEncoder,å°Âæ¶Âæ¯ä»ÂStringç¼Âç Â为IntegerãÂÂ
class StringEncoder extends MessageToByteEncoder<String> {
ÃÂ ÃÂ @Override
ÃÂ ÃÂ public void encode(ChannelHandlerContext ctx, String msg, ByteBuf out) throws Exception {
ÃÂ ÃÂ ÃÂ ÃÂ out.writeCharSequence(msg, Charset.defaultCharset());
ÃÂ }
}
âÂÂ
class StringToIntegerEncoder extends MessageToMessageEncoder<String> {
ÃÂ ÃÂ @Override
ÃÂ ÃÂ public void encode(ChannelHandlerContext ctx, String message, List<Object> out) throws Exception {
ÃÂ ÃÂ ÃÂ ÃÂ out.add(Integer.parseInt(message));
ÃÂ }
}
ç¼Âç Âå¨MessageToByteEncoder
MessageToByteEncoderç¨äºÂå°Â对象ç¼Âç ÂæÂÂÃ¥ÂÂèÂÂæµÂï¼ÂMessageToByteEncoder æÂÂä¾ÂäºÂå¯ä¸Âç encode æ½象æ¹æ³Âï¼ÂæÂÂ们éÂÂè¦Âå®Âç°encode æ¹æ³Âå³å¯å®ÂæÂÂèªå®Âä¹Âç¼Âç ÂãÂÂé£ä¹Âencode() æ¹æ³Âæ¯å¨ä»Âä¹Âæ¶åÂÂ被è°Âç¨çÂÂå¢ï¼Â
æÂÂ们ä¸Âèµ·çÂÂä¸ÂMessageToByteEncoder çÂÂæ ¸å¿ÂæºÂç ÂçÂÂ段ï¼Âå¦Âä¸ÂæÂÂ示ãÂÂ
MessageToByteEncoder继æ¿èªChannelOutboundHandlerAdapterãÂÂ
ChannelOutboundHandlerAdapter å®Âç°亠ChannelOutboundHandleræÂ¥å£,éÂÂÃ¥ÂÂäºÂwriteæ¹æ³ÂãÂÂ
è¿ÂéÂÂ使ç¨äºÂ模æ¿模å¼Â:encodeæ¹æ³Â交ç»Âå ·ä½ÂçÂÂÃ¥ÂÂç±»å®Âç°ãÂÂ
public abstract class MessageToByteEncoder<I> extends ChannelOutboundHandlerAdapter {
âÂÂ
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
ÃÂ ÃÂ ByteBuf buf = null;
ÃÂ ÃÂ try {
à// 1.æ¶Âæ¯类åÂÂæ¯å¦å¹éÂ
 ä¸Âå¹éÂ
Âä¸Âä¼Âå¤ÂçÂÂ
àààà// å³传åÂ
¥çÂÂæ¯String
ÃÂ ÃÂ ÃÂ ÃÂ if (acceptOutboundMessage(msg)) {
àààààà//Iæ¯æ³ÂÃ¥ÂÂ
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ @SuppressWarnings("unchecked")
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ I cast = (I) msg;
àààààà// 2. Ã¥ÂÂéÂ
 ByteBuf èµÂæºÂ
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ buf = allocateBuffer(ctx, cast, preferDirect);
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ try {
àààààà// 3. æ§衠encode æ¹æ³Âå®ÂæÂÂæ°æ®ç¼Âç Â
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ encode(ctx, cast, buf);
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ } finally {
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ReferenceCountUtil.release(cast);
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ }
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ if (buf.isReadable()) {
àààààà// 4. Ã¥ÂÂÃ¥ÂÂä¼ éÂÂÃ¥ÂÂäºÂ件
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ctx.write(buf, promise);
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ } else {
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ buf.release();
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ctx.write(Unpooled.EMPTY_BUFFER, promise);
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ }
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ buf = null;
ÃÂ ÃÂ ÃÂ } else {
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ctx.write(msg, promise);
ÃÂ ÃÂ ÃÂ }
ÃÂ } catch (EncoderException e) {
ÃÂ ÃÂ ÃÂ ÃÂ throw e;
ÃÂ } catch (Throwable e) {
ÃÂ ÃÂ ÃÂ ÃÂ throw new EncoderException(e);
ÃÂ } finally {
ÃÂ ÃÂ ÃÂ ÃÂ if (buf != null) {
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ buf.release();
ÃÂ ÃÂ ÃÂ }
ÃÂ }
}
}
//ä¾ÂÃ¥ÂÂç±»éÂÂÃ¥ÂÂ
protected abstract void encode(ChannelHandlerContext ctx, I msg, ByteBuf out) throws Exception;
MessageToByteEncoder éÂÂÃ¥ÂÂ亠ChanneOutboundHandler ç write() æ¹æ³Âï¼Â堶主è¦Âé»è¾ÂÃ¥ÂÂ为以ä¸Âå 个æ¥骤ï¼Â
- acceptOutboundMessage å¤æÂÂæ¯å¦æÂÂå¹é ÂçÂÂæ¶Âæ¯类åÂÂï¼Âå¦ÂæÂÂå¹é ÂéÂÂè¦Âæ§è¡Âç¼Âç ÂæµÂç¨Âï¼Âå¦ÂæÂÂä¸Âå¹é Âç´æ¥继ç»Âä¼ éÂÂç»Âä¸Âä¸Â个 ChannelOutboundHandlerãÂÂ
- Ã¥ÂÂé  ByteBuf èµÂæºÂï¼Âé»Â认使ç¨å Âå¤Âå åÂÂãÂÂ
- è°Âç¨åÂÂç±»å®Âç°ç encode æ¹æ³Âå®ÂæÂÂæ°æ®ç¼Âç Âï¼Âä¸Âæ¦æ¶Âæ¯被æÂÂÃ¥ÂÂç¼Âç Âï¼Âä¼ÂéÂÂè¿Âè°Âç¨ReferenceCountUtil.release(cast) èªå¨éÂÂæ¾ãÂÂ
- å¦Âæ ByteBuf å¯读ï¼Â说æÂÂå·²ç»ÂæÂÂÃ¥ÂÂç¼Âç Âå¾Âå°æ°æ®ï¼Âç¶åÂÂÃ¥ÂÂå ¥ ChannelHandlerContext 交å°ä¸Âä¸Â个èÂÂç¹ãÂÂå¦Âæ ByteBuf ä¸Âå¯读ï¼ÂÃ¥ÂÂéÂÂæ¾ ByteBuf èµÂæºÂï¼ÂÃ¥ÂÂä¸Âä¼ éÂÂ空ç ByteBuf 对象ãÂÂ
å®Âç°类:StringToByteEncoder
ç¼Âç Âå¨å®Âç°éÂÂ常ç®ÂÃ¥ÂÂï¼Âä¸ÂéÂÂè¦Â堳注æÂÂå /ç²Âå é®é¢ÂãÂÂ
å¦Âä¸Âä¾ÂÃ¥ÂÂï¼Âå±Â示äºÂå¦Âä½Âå°ÂÃ¥ÂÂ符串类åÂÂçÂÂæ°æ®åÂÂå ¥å° ByteBuf å®Âä¾Âï¼ÂByteBuf å®Âä¾Âå°Âä¼ éÂÂç» ChannelPipeline é¾表ä¸ÂçÂÂä¸Âä¸Â个 ChannelOutboundHandlerãÂÂ
package io.netty.example.Encode;
âÂÂ
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
âÂÂ
public class StringToByteEncoder extends MessageToByteEncoder<String> {
âÂÂ
ÃÂ ÃÂ @Override
ÃÂ ÃÂ protected void encode(ChannelHandlerContext channelHandlerContext, String data, ByteBuf byteBuf) throws Exception {
ÃÂ ÃÂ ÃÂ byteBuf.writeBytes(data.getBytes());
ÃÂ }
}
ç¼Âç Âå¨MessageToMessageEncoder
www.javajike.com/book/essentâ¦
MessageToMessageEncoder 丠MessageToByteEncoder 类似ï¼ÂÃ¥ÂÂæ ·åªéÂÂè¦Âå®Âç° encode æ¹æ³ÂãÂÂ
丠MessageToByteEncoder ä¸ÂÃ¥ÂÂçÂÂæ¯ï¼ÂMessageToMessageEncoder æ¯å°Âä¸Âç§Âæ ¼å¼ÂçÂÂæ¶Âæ¯转æ¢为å¦å¤Âä¸Âç§Âæ ¼å¼ÂçÂÂæ¶Âæ¯ãÂÂ
å ¶ä¸Â第äºÂ个 Message æÂÂæÂÂçÂÂå¯以æ¯任æÂÂä¸Â个对象ï¼Âå¦ÂæÂÂ该对象æ¯ ByteBuf ç±»åÂÂï¼Âé£ä¹Âå MessageToByteEncoder çÂÂå®Âç°åÂÂçÂÂæ¯ä¸Âè´çÂÂãÂÂ
MessageToMessageEncoder继æ¿èªChannelOutboundHandlerAdapterãÂÂ
ChannelOutboundHandlerAdapter å®Âç°亠ChannelOutboundHandleræÂ¥å£,éÂÂÃ¥ÂÂäºÂwriteæ¹æ³ÂãÂÂ
è¿ÂéÂÂ使ç¨äºÂ模æ¿模å¼Â:encodeæ¹æ³Â交ç»Âå ·ä½ÂçÂÂÃ¥ÂÂç±»å®Âç°ãÂÂ
ÃÂ ÃÂ @Override
ÃÂ ÃÂ public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
ÃÂ ÃÂ ÃÂ ÃÂ CodecOutputList out = null;
ÃÂ ÃÂ ÃÂ ÃÂ try {
àààààà// 1. æ¶Âæ¯类åÂÂæ¯å¦å¹éÂ
 ä¸Âå¹éÂ
Âä¸Âä¼Âå¤ÂçÂÂ
ààà// å³传åÂ
¥çÂÂæ¯String
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ if (acceptOutboundMessage(msg)) {
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ out = CodecOutputList.newInstance();
àààààààà//Iæ¯æ³ÂÃ¥ÂÂ
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ @SuppressWarnings("unchecked")
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ I cast = (I) msg;
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ try {
àààààààààà//æ§è¡ÂÃ¥ÂÂç±»encodeå®ÂæÂÂÃ¥Â
·ä½Âç¼Âç ÂæÂÂä½Â
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ encode(ctx, cast, out);
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ } finally {
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ReferenceCountUtil.release(cast);
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ }
//å¦ÂæÂÂè¾Âåºç»ÂæÂÂæ¯对象åÂÂ表outæ¯空
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ if (out.isEmpty()) {
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ out.recycle();
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ out = null;
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ throw new EncoderException(" must produce at least one message.");
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ }
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ } else {
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ctx.write(msg, promise);
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ }
ÃÂ ÃÂ ÃÂ } catch (EncoderException e) {
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ throw e;
ÃÂ ÃÂ ÃÂ } catch (Throwable t) {
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ throw new EncoderException(t);
ÃÂ ÃÂ ÃÂ } finally {
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ if (out != null) {
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ final int sizeMinusOne = out.size() - 1;
àààààààà// sizeMinusOneçÂÂäºÂ0说æ outé¿度æ¯1
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ if (sizeMinusOne == 0) {
àààààààààà//Ã¥ÂÂåºå»
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ctx.write(out.getUnsafe(0), promise);
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ } else if (sizeMinusOne > 0) {
àààààààààà//éÂÂÃ¥ÂÂÃ¥ÂÂåºå»
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ if (promise == ctx.voidPromise()) {
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ writeVoidPromise(ctx, out);
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ } else {
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ writePromiseCombiner(ctx, out, promise);
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ }
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ }
àààààààà//Ã¥ÂÂæ¶
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ out.recycle();
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ }
ÃÂ ÃÂ ÃÂ }
ÃÂ }
æ¤夠MessageToByteEncoder çÂÂè¾Âåºç»ÂæÂÂæ¯对象åÂÂ表outï¼Âç¼Âç ÂÃ¥ÂÂçÂÂç»ÂæÂÂå±ÂäºÂä¸Âé´对象ï¼ÂæÂÂç»Âä»Âç¶ä¼Â转åÂÂæ ByteBuf è¿Âè¡Âä¼ è¾ÂãÂÂ
MessageToMessageEncoder 常ç¨çÂÂå®Âç°åÂÂç±»æ StringEncoderãÂÂLineEncoderãÂÂBase64Encoder çÂÂãÂÂ以 StringEncoder 为ä¾ÂçÂÂ丠MessageToMessageEncoder çÂÂç¨æ³ÂãÂÂ
å®Âç°类:StringEncoder
@Sharable
public class StringEncoder extends MessageToMessageEncoder<CharSequence> {
âÂÂ
ÃÂ ÃÂ // TODO Use CharsetEncoder instead.
ÃÂ ÃÂ private final Charset charset;
âÂÂ
ÃÂ ÃÂ /**
ÃÂ ÃÂ * Creates a new instance with the current system character set.
ÃÂ ÃÂ */
ÃÂ ÃÂ public StringEncoder() {
ÃÂ ÃÂ ÃÂ ÃÂ this(Charset.defaultCharset());
ÃÂ }
âÂÂ
ÃÂ ÃÂ /**
ÃÂ ÃÂ * Creates a new instance with the specified character set.
ÃÂ ÃÂ */
ÃÂ ÃÂ public StringEncoder(Charset charset) {
ÃÂ ÃÂ ÃÂ ÃÂ if (charset == null) {
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ throw new NullPointerException("charset");
ÃÂ ÃÂ ÃÂ }
ÃÂ ÃÂ ÃÂ ÃÂ this.charset = charset;
ÃÂ }
âÂÂ
ÃÂ ÃÂ @Override
ÃÂ ÃÂ protected void encode(ChannelHandlerContext ctx, CharSequence msg, List<Object> out) throws Exception {
ÃÂ ÃÂ ÃÂ ÃÂ if (msg.length() == 0) {
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ return;
ÃÂ ÃÂ ÃÂ }
//ç¼Âç Â以åÂÂå åÂ
Â¥outÃ¥ÂÂ表 ç±ç¶类åÂÂåºå³å¯
ÃÂ ÃÂ ÃÂ ÃÂ out.add(ByteBufUtil.encodeString(ctx.alloc(), CharBuffer.wrap(msg), charset));
ÃÂ }
}
âÂÂ
æÂÂèÂÂ:ç°å¨æÂÂ1个Java对象è¦Âç¼Âç Â为jsonÃ¥ÂÂ符串åÂÂ转æ¢为byteä¼ è¾ å¦Âä½ÂÃ¥ÂÂå¢?
1.继æ¿MessageToMessageEncoder
2.éÂÂÃ¥ÂÂencodeæ¹æ³Â
3.å°Â对象åºÂÃ¥ÂÂÃ¥ÂÂ为json
4.å°Âjson转为ByteBufferÃ¥ÂÂéÂÂ:ByteBufUtil.encodeString(ctx.alloc(), CharBuffer.wrap(json), charset)