Interface ChannelHandler
- All Known Subinterfaces:
ChannelDownstreamHandler,ChannelUpstreamHandler,LifeCycleAwareChannelHandler
- All Known Implementing Classes:
AbstractCodecEmbedder.EmbeddedChannelSink,AbstractTrafficShapingHandler,AutobahnServerHandler,Base64Decoder,Base64Encoder,BigIntegerDecoder,BlockingReadHandler,BufferedWriteHandler,ChannelTrafficShapingHandler,ChunkedWriteHandler,CompatibleMarshallingDecoder,CompatibleMarshallingEncoder,CompatibleObjectEncoder,DelimiterBasedFrameDecoder,DiscardClientHandler,DiscardServerHandler,EchoClientHandler,EchoServerHandler,ExecutionHandler,FactorialClientHandler,FactorialServerHandler,FixedLengthFrameDecoder,FrameDecoder,GlobalChannelTrafficShapingHandler,GlobalTrafficShapingHandler,HexDumpProxyInboundHandler,HexDumpProxyInboundHandler.OutboundHandler,HttpChunkAggregator,HttpClientCodec,HttpClientCodec.Decoder,HttpClientCodec.Encoder,HttpContentCompressor,HttpContentDecoder,HttpContentDecompressor,HttpContentEncoder,HttpHelloWorldServerHandler,HttpMessageDecoder,HttpMessageEncoder,HttpRequestDecoder,HttpRequestEncoder,HttpResponseDecoder,HttpResponseEncoder,HttpServerCodec,HttpSnoopClientHandler,HttpSnoopServerHandler,HttpStaticFileServerHandler,HttpTunnelingClientSocketChannel.ServletChannelHandler,HttpTunnelingServlet.OutboundConnectionHandler,HttpUploadClientHandler,HttpUploadServerHandler,IdleStateAwareChannelHandler,IdleStateAwareChannelUpstreamHandler,IdleStateHandler,IpFilteringHandlerImpl,IpFilterRuleHandler,JdkZlibEncoder,LengthFieldBasedFrameDecoder,LengthFieldPrepender,LineBasedFrameDecoder,LocalTimeClientHandler,LocalTimeServerHandler,LoggingHandler,MarshallingDecoder,MarshallingEncoder,NumberEncoder,ObjectDecoder,ObjectEchoClientHandler,ObjectEchoServerHandler,ObjectEncoder,OneIpFilterHandler,OneToOneDecoder,OneToOneEncoder,OneToOneStrictEncoder,PortUnificationServerHandler,ProtobufDecoder,ProtobufEncoder,ProtobufVarint32FrameDecoder,ProtobufVarint32LengthFieldPrepender,QuoteOfTheMomentClientHandler,QuoteOfTheMomentServerHandler,ReadTimeoutHandler,ReplayingDecoder,RtspMessageDecoder,RtspMessageEncoder,RtspRequestDecoder,RtspRequestEncoder,RtspResponseDecoder,RtspResponseEncoder,SecureChatClientHandler,SecureChatServerHandler,ServerBootstrap.Binder,SimpleChannelDownstreamHandler,SimpleChannelHandler,SimpleChannelUpstreamHandler,SocksAuthRequestDecoder,SocksAuthResponseDecoder,SocksCmdRequestDecoder,SocksCmdResponseDecoder,SocksInitRequestDecoder,SocksInitResponseDecoder,SocksMessageEncoder,SpdyFrameCodec,SpdyHttpCodec,SpdyHttpDecoder,SpdyHttpEncoder,SpdyHttpResponseStreamIdHandler,SpdyOrHttpChooser,SpdySessionHandler,SslHandler,StringDecoder,StringEncoder,TelnetClientHandler,TelnetServerHandler,UptimeClientHandler,WebSocket00FrameDecoder,WebSocket00FrameEncoder,WebSocket07FrameDecoder,WebSocket07FrameEncoder,WebSocket08FrameDecoder,WebSocket08FrameEncoder,WebSocket13FrameDecoder,WebSocket13FrameEncoder,WebSocketClientHandler,WebSocketFrameAggregator,WebSocketServerHandler,WebSocketServerProtocolHandler,WebSocketServerProtocolHandshakeHandler,WriteTimeoutHandler,ZlibDecoder,ZlibEncoder
ChannelEvent, and sends a
ChannelEvent to the next handler in a ChannelPipeline.
Sub-types
ChannelHandler itself does not provide any method. To handle a
ChannelEvent you need to implement its sub-interfaces. There are
two sub-interfaces which handles a received event, one for upstream events
and the other for downstream events:
ChannelUpstreamHandlerhandles and intercepts an upstreamChannelEvent.ChannelDownstreamHandlerhandles and intercepts a downstreamChannelEvent.
The context object
A ChannelHandler is provided with a ChannelHandlerContext
object. A ChannelHandler is supposed to interact with the
ChannelPipeline it belongs to via a context object. Using the
context object, the ChannelHandler can pass events upstream or
downstream, modify the pipeline dynamically, or store the information
(attachment) which is specific to the handler.
State management
AChannelHandler often needs to store some stateful information.
The simplest and recommended approach is to use member variables:
public class DataServerHandler extendsBecause the handler instance has a state variable which is dedicated to one connection, you have to create a new handler instance for each new channel to avoid a race condition where a unauthenticated client can get the confidential information:SimpleChannelHandler{ private boolean loggedIn;@Overridepublic void messageReceived(ChannelHandlerContextctx,MessageEvente) {Channelch = e.getChannel(); Object o = e.getMessage(); if (o instanceof LoginMessage) { authenticate((LoginMessage) o); loggedIn = true; } else (o instanceof GetDataMessage) { if (loggedIn) { ch.write(fetchSecret((GetDataMessage) o)); } else { fail(); } } } ... }
// Create a new handler instance per channel. // SeeBootstrap.setPipelineFactory(ChannelPipelineFactory). public class DataServerPipelineFactory implementsChannelPipelineFactory{ publicChannelPipelinegetPipeline() { returnChannels.pipeline(new DataServerHandler()); } }
Using an attachment
Although it's recommended to use member variables to store the state of a handler, for some reason you might not want to create many handler instances. In such a case, you can use an attachment which is provided byChannelHandlerContext:
Now that the state of the handler is stored as an attachment, you can add the same handler instance to different pipelines:@Sharablepublic class DataServerHandler extendsSimpleChannelHandler{@Overridepublic void messageReceived(ChannelHandlerContextctx,MessageEvente) {Channelch = e.getChannel(); Object o = e.getMessage(); if (o instanceof LoginMessage) { authenticate((LoginMessage) o); ctx.setAttachment(true); } else (o instanceof GetDataMessage) { if (Boolean.TRUE.equals(ctx.getAttachment())) { ch.write(fetchSecret((GetDataMessage) o)); } else { fail(); } } } ... }
public class DataServerPipelineFactory implementsChannelPipelineFactory{ private static final DataServerHandler SHARED = new DataServerHandler(); publicChannelPipelinegetPipeline() { returnChannels.pipeline(SHARED); } }
Using a ChannelLocal
If you have a state variable which needs to be accessed either from other
handlers or outside handlers, you can use ChannelLocal:
public final class DataServerState {
public static final ChannelLocal<Boolean> loggedIn = new ChannelLocal<>() {
protected Boolean initialValue(Channel channel) {
return false;
}
}
...
}
@Sharable
public class DataServerHandler extends SimpleChannelHandler {
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
Channel ch = e.getChannel();
Object o = e.getMessage();
if (o instanceof LoginMessage) {
authenticate((LoginMessage) o);
DataServerState.loggedIn.set(ch, true);
} else (o instanceof GetDataMessage) {
if (DataServerState.loggedIn.get(ch)) {
ctx.getChannel().write(fetchSecret((GetDataMessage) o));
} else {
fail();
}
}
}
...
}
// Print the remote addresses of the authenticated clients:
ChannelGroup allClientChannels = ...;
for (Channel ch: allClientChannels) {
if (DataServerState.loggedIn.get(ch)) {
System.out.println(ch.getRemoteAddress());
}
}
The @Sharable annotation
In the examples above which used an attachment or a ChannelLocal,
you might have noticed the @Sharable annotation.
If a ChannelHandler is annotated with the @Sharable
annotation, it means you can create an instance of the handler just once and
add it to one or more ChannelPipelines multiple times without
a race condition.
If this annotation is not specified, you have to create a new handler instance every time you add it to a pipeline because it has unshared state such as member variables.
This annotation is provided for documentation purpose, just like the JCIP annotations.
Additional resources worth reading
Please refer to the ChannelEvent and ChannelPipeline to find
out what a upstream event and a downstream event are, what fundamental
differences they have, and how they flow in a pipeline.
-
Nested Class Summary
Nested ClassesModifier and TypeInterfaceDescriptionstatic @interfaceIndicates that the same instance of the annotatedChannelHandlercan be added to one or moreChannelPipelines multiple times without a race condition.