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 }
.JPG)
ChannelHandlerContext接口UML類(lèi)
ChannelHandlerContext接口的幾個(gè)重要方法
ChannelPipeline pipeline();
返回屬于當(dāng)前ChannelHandlerContext的ChannelPipeline。
EventExecutor executor();
EnventExcutor用于調(diào)度EventLoop中的event,這個(gè)方法返回當(dāng)前的EventExecutor。
一個(gè)Handler可以有多個(gè)Context
一個(gè)Handler可以被添加到多個(gè)ChannelPipeline。這就意味著一個(gè)ChannelHandler可以有多個(gè)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 }
.JPG)
ChannelHandler類(lèi)UML圖
ChannelHandler中的幾個(gè)重要方法
ChannelHandler有兩個(gè)子接口,ChannelUpstreamHandler和ChannelDownstreamHandler。
1. ChannelUpstreamHandler用于處理和攔截upstream中的ChannelEvent
2. ChannelDownstreamHandler用于處理和攔截downstream中的ChannelEvent
狀態(tài)信息
ChannelHandler一般需要存儲(chǔ)一些狀態(tài)信息,以下是【官方推薦】的方法,使用成員變量。
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());
}
}
備注:因?yàn)楣P者開(kāi)始寫(xiě)Netty源碼分析的時(shí)候,Netty 4.0還是處于Alpha階段,之后的API可能還會(huì)有改動(dòng),筆者將會(huì)及時(shí)更改。使用開(kāi)源已經(jīng)有好幾年的時(shí)間了,一直沒(méi)有時(shí)間和精力來(lái)具體研究某個(gè)開(kāi)源項(xiàng)目的具體實(shí)現(xiàn),這次是第一次寫(xiě)開(kāi)源項(xiàng)目的源碼分析,如果文中有錯(cuò)誤的地方,歡迎讀者可以留言指出。對(duì)于轉(zhuǎn)載的讀者,請(qǐng)注明文章的出處。 希望和廣大的開(kāi)發(fā)者/開(kāi)源愛(ài)好者進(jìn)行交流,歡迎大家的留言和討論。
-----------------------------------------------------
Silence, the way to avoid many problems;
Smile, the way to solve many problems;