public interface ChannelHandler
ChannelPipeline中的下一个处理程序。
ChannelHandler本身并不提供很多方法,但通常必须实现其中一个子类型:
ChannelInboundHandler来处理入站I / O事件和 ChannelOutboundHandler来处理出站I / O操作。 或者,提供以下适配器类以方便您使用:
ChannelInboundHandlerAdapter来处理入站I / O事件, ChannelOutboundHandlerAdapter处理出站I / O操作和 ChannelDuplexHandler处理入站和出站事件 有关更多信息,请参阅每个子类型的文档。
A ChannelHandler提供了一个ChannelHandlerContext对象。 ChannelHandler应该通过上下文对象与它所属的ChannelPipeline进行交互。 使用上下文对象, ChannelHandler可以向上游或下游传递事件,动态修改管道,或存储特定于处理程序的信息(使用AttributeKey )。
ChannelHandler通常需要存储一些有状态的信息。
最简单和推荐的方法是使用成员变量:
public interface Message {
// your methods here
}
public class DataServerHandler extends SimpleChannelInboundHandler<Message> {
private boolean loggedIn;
@Override
public void channelRead0(ChannelHandlerContext ctx, Message message) {
Channel ch = e.getChannel();
if (message instanceof LoginMessage) {
authenticate((LoginMessage) message);
loggedIn = true;
} else (message instanceof GetDataMessage) {
if (loggedIn) {
ch.write(fetchSecret((GetDataMessage) message));
} else {
fail();
}
}
}
...
}
由于处理程序实例具有专用于一个连接的状态变量,因此您必须为每个新通道创建一个新的处理程序实例,以避免未经身份验证的客户端可以获取机密信息的竞争状况:
// Create a new handler instance per channel.
// See ChannelInitializer.initChannel(Channel).
public class DataServerInitializer extends ChannelInitializer<Channel> {
@Override
public void initChannel(Channel channel) {
channel.pipeline().addLast("handler", new DataServerHandler());
}
}
AttributeKey s AttributeKey个 S的被提供ChannelHandlerContext :
public interface Message {
// your methods here
}
@Sharable
public class DataServerHandler extends SimpleChannelInboundHandler<Message> {
private final AttributeKey<Boolean> auth =
AttributeKey.valueOf("auth");
@Override
public void channelRead(ChannelHandlerContext ctx, Message message) {
Attribute<Boolean> attr = ctx.attr(auth);
Channel ch = ctx.channel();
if (message instanceof LoginMessage) {
authenticate((LoginMessage) o);
attr.set(true);
} else (message instanceof GetDataMessage) {
if (Boolean.TRUE.equals(attr.get())) {
ch.write(fetchSecret((GetDataMessage) o));
} else {
fail();
}
}
}
...
}
现在处理程序的状态已连接到ChannelHandlerContext ,您可以将相同的处理程序实例添加到不同的管道:
public class DataServerInitializer extends ChannelInitializer<Channel> {
private static final DataServerHandler SHARED = new DataServerHandler();
@Override
public void initChannel(Channel channel) {
channel.pipeline().addLast("handler", SHARED);
}
}
@Sharable注释 在上面使用AttributeKey的示例中,您可能已经注意到@Sharable注释。
如果ChannelHandler使用@Sharable批注注释,则表示您可以只创建一次该处理程序的实例,并将其添加到一个或多个ChannelPipeline ,而不会出现竞争条件。
如果未指定此注释,则每次将其添加到管道时都必须创建一个新的处理程序实例,因为它具有非共享状态,如成员变量。
此注释仅用于文档目的,就像the JCIP annotations一样。
请参阅ChannelHandler和ChannelPipeline,以了解有关入站和出站操作的更多信息,它们之间存在什么根本区别,它们如何在流水线中流动以及如何处理应用程序中的操作。
| Modifier and Type | Interface and Description |
|---|---|
static interface |
ChannelHandler.Sharable
表示可以将带有注释的 ChannelHandler的相同实例多次添加到一个或多个ChannelPipeline ,而不会出现竞争条件。
|
| Modifier and Type | Method and Description |
|---|---|
void |
exceptionCaught(ChannelHandlerContext ctx, java.lang.Throwable cause)
已过时。
|
void |
handlerAdded(ChannelHandlerContext ctx)
在 ChannelHandler被添加到实际上下文之后调用,并且它已准备好处理事件。
|
void |
handlerRemoved(ChannelHandlerContext ctx)
在 ChannelHandler从实际上下文中移除之后调用,它不再处理事件。
|
void handlerAdded(ChannelHandlerContext ctx) throws java.lang.Exception
ChannelHandler被添加到实际上下文之后调用,并准备好处理事件。
java.lang.Exception
void handlerRemoved(ChannelHandlerContext ctx) throws java.lang.Exception
ChannelHandler已从实际上下文中移除并且不再处理事件之后调用。
java.lang.Exception
@Deprecated void exceptionCaught(ChannelHandlerContext ctx, java.lang.Throwable cause) throws java.lang.Exception
ChannelInboundHandler的一部分
Throwable被抛出,
Throwable被调用。
java.lang.Exception
Copyright © 2008–2018 The Netty Project. All rights reserved.