ChannelHandlerContext接口
1 package io.netty.channel;
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接口
1 package io.netty.channel;
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一般需要存儲一些狀態信息,以下是【官方推薦】的方法,使用成員變量。
public class DataServerHandler
extends SimpleChannelHandler {
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;