Netty 设计最优良的部分就是编码器的架构,可以方便的自定义协议的处理,也可以复用优秀的通用协议。现简单定义一个编码器用来记录。
假设这样一个场景,服务端与客户端希望传输 Map 类型对象,这样足够灵活,尽管效率会很低,但是简单灵活,每一条消息都是个 Map ,每种业务都可以灵活的支持,尽管效率不够高效,但是节省脑细胞。
那么具体的过程是:定义Map消息 -> Map编码至String -> 发送 -> 将String解码为 Map -> 处理 Map 消息
。
这样看需要定义一个编码器和一个解码器
// MapDecoder.java 解码器
public class MapDecoder extends MessageToMessageDecoder<String> {
@Override
protected void decode(ChannelHandlerContext ctx, String msg, List<Object> out) throws Exception {
System.out.println("decode: " + msg);
//PusherCoder.decode可以是任何你喜欢的将json转换成map的工具。
Map<String,Object> map = PusherCoder.decode(msg);
if(map != null && map.size() > 0){
out.add(map);
}
}
}
// MapDecoder.java 解码器
public class MapEncoder extends MessageToMessageEncoder<Map<String,Object>> {
@Override
protected void encode(ChannelHandlerContext ctx, Map<String,Object> msg, List<Object> out) throws Exception {
System.out.println("encode :" + msg);
//PusherCoder.encode可以是任何你喜欢的将map转换成json字符串的工具
String str = PusherCoder.encode(msg);
//因为使用换行符作分隔符
out.add(str + System.getProperty("line.separator"));
}
}
//NettyServiceHandler.java 这是服务端的消息处理器,客户端也是类似的,在这里直接可以处理 map 格式的消息
public class NettyServiceHandler extends SimpleChannelInboundHandler<Map<String, Object>> {
private Integer count = 0;
@Override
protected void channelRead0(ChannelHandlerContext ctx, Map<String, Object> msg) throws Exception {
System.out.println("NettyServiceHandler channelRead0");
System.out.println(msg);
ctx.channel().writeAndFlush(msg);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
super.exceptionCaught(ctx, cause);
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
System.out.println("NettyServiceHandler channelActive");
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
super.channelInactive(ctx);
System.out.println("NettyServiceHandler channelInactive");
}
}
以上,是一个很偷懒的,不够实用的,不够高效的自定义编解码器,但是对于一面设计一面上线,用户量不高的场景来说还是可以用的。