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.