Netty 将 HttpRequest 转换为 ByteBuf
Netty convert HttpRequest to ByteBuf
在我的应用程序中,我需要在套接字上接收字节数组,将其解析为 HttpRequest
以执行一些检查,如果检查通过,则返回字节数组并做更多工作.
应用程序基于 NETTY(这是要求)。
我的第一个想法是创建一个这样的管道:
HttpRequestDecoder
(从ByteBuf
解码为HttpRequest
)
MyHttpRequestHandler
(我自己检查 HttpRequest
)
HttpRequestEncoder
(将HttpRequest
编码为ByteBuf
)
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);
}
在我的应用程序中,我需要在套接字上接收字节数组,将其解析为 HttpRequest
以执行一些检查,如果检查通过,则返回字节数组并做更多工作.
应用程序基于 NETTY(这是要求)。
我的第一个想法是创建一个这样的管道:
HttpRequestDecoder
(从ByteBuf
解码为HttpRequest
)MyHttpRequestHandler
(我自己检查HttpRequest
)HttpRequestEncoder
(将HttpRequest
编码为ByteBuf
)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);
}