При использовании ChannelInitializer
следует помнить, что метод initChannel
вызывается для каждого нового открываемого соединения.
Все, что требует уникального состояния, должнобыть построенным внутри этого метода.
Глядя на ваш код, я вижу, что вы правильно создаете новые экземпляры LoggingHandler
, HttpServerCodec
и HttpObjectAggregator
, но вы ссылаетесь на "общий" экземплярваш customHandler
класс.
Хотя вы можете решить свою проблему, просто используя new CustomHandler ()
в методе initChannel
, вы на самом деле демонстрируете различные намерения, используя систему автоматического подключения пружин.
ТамЕсть еще два решения, которые мы можем использовать:
Шаблон фабрики
Вместо прямого автоматического подключения экземпляра ChannelDuplexHandler
, вам необходимо подключить фабрику, которая производит экземпляры этого класса:
public interface ChannelDuplexHandlerFactory {
public ChannelDuplexHandler getChannelDuplexHandler();
}
@Component
public class ChannelDuplexHandlerFactoryImplementation implements ChannelDuplexHandlerFactory {
public ChannelDuplexHandler getChannelDuplexHandler() {
return new CustomHandler();
}
}
public class CustomIniatializer extends ChannelInitializer<SocketChannel> {
@Autowired
private ChannelDuplexHandler customHandler;
@Override
public void initChannel(SocketChannel ch) {
ChannelPipeline p = ch.pipeline();
p.addLast(new LoggingHandler(LogLevel.INFO));
p.addLast(new HttpServerCodec());
p.addLast(new HttpObjectAggregator(8*1024, true));
p.addLast(customHandler.getChannelDuplexHandler());
}
}
Использование полей на основе канала вместо полей класса
Еще одно решение, которое вы можете использовать, - это переменные, хранящиеся внутри текущего канала, это болееЭлектронная продвинутая техника, которая может быть полезна в определенных ситуациях:
@Component
@ChannelHandler.Sharable
public class CustomHandler extends ChannelDuplexHandler {
private static final AttributeKey<StringBuilder> BUF_KEY = AttributeKey.newInstance("BUF_KEY");
private static final AttributeKey<String> FOO_KEY = AttributeKey.newInstance("FOO_KEY");
private static final AttributeKey<String> VAL_KEY = AttributeKey.newInstance("VAL_KEY");
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
Channel ch = ctx.channel();
final StringBuilder buf = ch.attr(BUF_KEY).get();
String foo = ch.attr(FOO_KEY).get();
String val = ch.attr(VAL_KEY).get();
// Parse the request and set the variables
if (foo != null) {
foo = request.getUri()
}
if (val != null) {
val = getQueryParamsOf("key");
}
buf.append(val);
ch.attr(FOO_KEY).set(foo);
ch.attr(VAL_KEY).set(val);
}
}