Netty 将 HttpRequest 转换为 ByteBuf

Netty convert HttpRequest to ByteBuf

在我的应用程序中,我需要在套接字上接收字节数组,将其解析为 HttpRequest 以执行一些检查,如果检查通过,则返回字节数组并做更多工作.

应用程序基于 NETTY(这是要求)。

我的第一个想法是创建一个这样的管道:

  1. HttpRequestDecoder(从ByteBuf解码为HttpRequest
  2. MyHttpRequestHandler(我自己检查 HttpRequest
  3. HttpRequestEncoder(将HttpRequest编码为ByteBuf
  4. MyButeBufHandler(用ByteBuf做我的作品)

然而,HttpRequestEncoder 扩展了 ChannelOutboundHandlerAdapter,因此不会为入站数据调用它。

我怎样才能完成这个任务? 最好避免对请求进行解码和重新编码。

此致, 马西米利亚诺

MyHttpRequestHandler 中使用 EmbeddedChannel

EmbeddedChannel ch = new EmbeddedChannel(new HttpRequestEncoder()); ch.writeOutbound(消息); ByteBuf 编码 = ch.readOutbound();

您必须将 EmbeddedChannel 保留为 MyHttpRequestEncoder 的成员变量,因为 HttpRequestEncoder 是有状态的。另外,请在使用完后关闭 EmbeddedChannel(可能在您的 channelInactive() 方法中。)

我只需要对一些 HttpObjects 进行编码和解码,并为此付出了一些努力。 decoder/encoder 是有状态的提示非常有价值。

这就是为什么我想在这里添加我的发现。也许对其他人有帮助。

我将 RequestEncoder 和 ResponseDecoder 声明为 class 成员,但它仍然无法正常工作。直到我想起我在其中使用 en/decoders 的特定处理程序是共享的...

这就是我最终让它发挥作用的方式。我的 sequenceNr 是为了区分不同的请求。我为每个请求创建一个编码器和一个解码器,并将它们保存在一个 HashMap 中。使用我的 sequenceNr,我总是能够为相同的请求获得相同的 decoder/encoder。不要忘记在处理完 LastContent 对象后从地图中关闭和移除 de/encoder 个通道。

@ChannelHandler.Sharable
public class HttpTunnelingServerHandler extends ChannelDuplexHandler {
private final Map<Integer, EmbeddedChannel> decoders = Collections.synchronizedMap(new HashMap<Integer, EmbeddedChannel>());
private final Map<Integer, EmbeddedChannel> encoders = Collections.synchronizedMap(new HashMap<Integer, EmbeddedChannel>());
.
.
//Encoding
if (!encoders.containsKey(currentResponse.getSequenceNr())) {
        encoders.put(currentResponse.getSequenceNr(), new EmbeddedChannel(new HttpResponseEncoder()));
    }
    EmbeddedChannel encoderChannel = encoders.get(currentResponse.getSequenceNr());
    encoderChannel.writeOutbound(recievedHttpObject);
    ByteBuf encoded = (ByteBuf) encoderChannel.readOutbound();
.
.
//Decoding
if (!decoders.containsKey(sequenceNr)) {
        decoders.put(sequenceNr, new EmbeddedChannel(new HttpRequestDecoder()));
        }
        EmbeddedChannel decoderChannel = decoders.get(sequenceNr);
        decoderChannel.writeInbound(bb);
        HttpObject httpObject = (HttpObject) decoderChannel.readInbound();

}

如何将 EmbeddedChannel 作为处理程序通道的属性,而不是 HashMap。跟你说的解决statefulencoder/decoder不一样吗?

@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
      ctx.channel().attr(EMBEDED_CH).set( new EmbeddedChannel(new HttpRequestDecoder()));
      super.channelActive(ctx);
}
    
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
      EmbeddedChannel embedCh = ctx.channel().attr(EMBEDED_CH).get();
      if (embedCh != null) {
          embedCh.close();
      }

      super.channelInactive(ctx);
}