{@code @Sharable}public class DataServerHandler extends {@link SimpleChannelHandler} {{@code @Override}public void messageReceived( {@link ChannelHandlerContext} ctx, {@link MessageEvent} e) {{@link Channel} ch = 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(); } } } ... }Now that the state of the handler is stored as an attachment, you can add the same handler instance to different pipelines:
public class DataServerPipelineFactory implements {@link ChannelPipelineFactory} {private static final DataServerHandler SHARED = new DataServerHandler(); public {@link ChannelPipeline} getPipeline() {return {@link Channels}.pipeline(SHARED); } }
public final class DataServerState { public static final {@link ChannelLocal}<Boolean> loggedIn = new {@link ChannelLocal}<>() { protected Boolean initialValue(Channel channel) { return false; } } ... } {@code @Sharable}public class DataServerHandler extends {@link SimpleChannelHandler} {{@code @Override}public void messageReceived( {@link ChannelHandlerContext} ctx, {@link 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: {@link ChannelGroup} allClientChannels = ...;for ( {@link Channel} ch: allClientChannels) {if (DataServerState.loggedIn.get(ch)) { System.out.println(ch.getRemoteAddress()); } }
In the examples above which used an attachment or a {@link ChannelLocal}, you might have noticed the {@code @Sharable} annotation.
If a {@link ChannelHandler} is annotated with the {@code @Sharable}annotation, it means you can create an instance of the handler just once and add it to one or more {@link ChannelPipeline}s 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.
Please refer to the {@link ChannelEvent} and {@link ChannelPipeline} to findout what a upstream event and a downstream event are, what fundamental differences they have, and how they flow in a pipeline. @apiviz.landmark @apiviz.exclude ^org\.jboss\.netty\.handler\..*$
|
|
|
|