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;