Netty 4.0 源碼分析(五):ChannelHandlerContext和ChannelHandler
ChannelHandlerContext接口
2 import io.netty.buffer.ByteBuf;
3 import io.netty.buffer.MessageBuf;
4 import io.netty.util.AttributeMap;
5 import java.nio.channels.Channels;
6 import java.util.Set;
7 public interface ChannelHandlerContext
8 extends AttributeMap, ChannelFutureFactory,
9 ChannelInboundInvoker, ChannelOutboundInvoker {
10 Channel channel();
11 ChannelPipeline pipeline();
12 EventExecutor executor();
13 String name();
14 ChannelHandler handler();
15 Set<ChannelHandlerType> types();
16 boolean hasInboundByteBuffer();
17 boolean hasInboundMessageBuffer();
18 ByteBuf inboundByteBuffer();
19 <T> MessageBuf<T> inboundMessageBuffer();
20 boolean hasOutboundByteBuffer();
21 boolean hasOutboundMessageBuffer();
22 ByteBuf outboundByteBuffer();
23 <T> MessageBuf<T> outboundMessageBuffer();
24 ByteBuf replaceInboundByteBuffer(ByteBuf newInboundByteBuf);
25 <T> MessageBuf<T> replaceInboundMessageBuffer(MessageBuf<T> newInboundMsgBuf);
26 ByteBuf replaceOutboundByteBuffer(ByteBuf newOutboundByteBuf);
27 <T> MessageBuf<T> replaceOutboundMessageBuffer(MessageBuf<T> newOutboundMsgBuf);
28 boolean hasNextInboundByteBuffer();
29 boolean hasNextInboundMessageBuffer();
30 ByteBuf nextInboundByteBuffer();
31 MessageBuf<Object> nextInboundMessageBuffer();
32 boolean hasNextOutboundByteBuffer();
33 boolean hasNextOutboundMessageBuffer();
34 ByteBuf nextOutboundByteBuffer();
35 MessageBuf<Object> nextOutboundMessageBuffer();
36 boolean isReadable();
37 void readable(boolean readable);
38 }
ChannelHandlerContext接口UML類
ChannelHandlerContext接口的幾個重要方法
ChannelPipeline pipeline();
返回屬于當前ChannelHandlerContext的ChannelPipeline。
EventExecutor executor();
EnventExcutor用于調度EventLoop中的event,這個方法返回當前的EventExecutor。
一個Handler可以有多個Context
一個Handler可以被添加到多個ChannelPipeline。這就意味著一個ChannelHandler可以有多個ChannelHandlerContext。
ChannelHandler接口
2
3 import io.netty.channel.group.ChannelGroup;
4 import java.lang.annotation.Documented;
5 import java.lang.annotation.ElementType;
6 import java.lang.annotation.Inherited;
7 import java.lang.annotation.Retention;
8 import java.lang.annotation.RetentionPolicy;
9 import java.lang.annotation.Target;
10 import java.nio.channels.Channels;
11
12 public interface ChannelHandler {
13 void beforeAdd(ChannelHandlerContext ctx) throws Exception;
14 void afterAdd(ChannelHandlerContext ctx) throws Exception;
15 void beforeRemove(ChannelHandlerContext ctx) throws Exception;
16 void afterRemove(ChannelHandlerContext ctx) throws Exception;
17 void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception;
18 void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception;
19 @Inherited
20 @Documented
21 @Target(ElementType.TYPE)
22 @Retention(RetentionPolicy.RUNTIME)
23 @interface Sharable {
24 // no value
25 }
26 }
ChannelHandler類UML圖
ChannelHandler中的幾個重要方法
ChannelHandler有兩個子接口,ChannelUpstreamHandler和ChannelDownstreamHandler。
1. ChannelUpstreamHandler用于處理和攔截upstream中的ChannelEvent
2. ChannelDownstreamHandler用于處理和攔截downstream中的ChannelEvent
狀態信息
ChannelHandler一般需要存儲一些狀態信息,以下是【官方推薦】的方法,使用成員變量。
private boolean loggedIn;
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
Channel ch = 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.
// See ClientBootstrap#setPipelineFactory(ChannelPipelineFactory).
public class DataServerPipelineFactory implements ChannelPipelineFactory {
public ChannelPipeline getPipeline() {
return Channels.pipeline(new DataServerHandler());
}
}
或者使用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()); } }
備注:因為筆者開始寫Netty源碼分析的時候,Netty 4.0還是處于Alpha階段,之后的API可能還會有改動,筆者將會及時更改。使用開源已經有好幾年的時間了,一直沒有時間和精力來具體研究某個開源項目的具體實現,這次是第一次寫開源項目的源碼分析,如果文中有錯誤的地方,歡迎讀者可以留言指出。對于轉載的讀者,請注明文章的出處。 希望和廣大的開發者/開源愛好者進行交流,歡迎大家的留言和討論。
-----------------------------------------------------
Silence, the way to avoid many problems;
Smile, the way to solve many problems;
posted on 2012-11-25 16:51 Chan Chen 閱讀(12647) 評論(4) 編輯 收藏 所屬分類: Netty