他的作用是处理一些io事件,或者阻止一些io操作,并且跳转到ChannelPipeline的下一个handler去
通常情况下,我们不会选择是实现这个接口,而是继承ChannelHandlerAdapter
ChannelHandler 通常会提供一个 ChannelHandlerContext. 所以你会看到ChannelHandler的每一个方法都有一个参数ChannelHandlerContext
ChannelHandler可以处理读写事件, 动态的修改pipeline, 存储一些数据到handler上(用AttributesKey)
状态管理
一个ChannelHandler通常需要存储一些状态信息,最简单的方式就是保存到成员变量里,如是否登录过了?
在这里,是否登录过了这个状态信息是每一个connection都需要的,所以,我们要为每一个channel创建一个handler的实例,
// Create a new handler instance per channel.
// See ChannelInitializer.initChannel(Channel).
public class DataServerInitializer extends ChannelInitializer<Channel> {
@Override
public void initChannel(Channel channel) {
channel.pipeline().addLast("handler", new DataServerHandler());
}
}
使用 AttributeKeys
你可以用他取代成员变量来保存一些信息,他是附属于ChannelHandlerContext
public interface Message {
// your methods here
}
@Sharable
public class DataServerHandler extends SimpleChannelInboundHandler<Message> {
private final AttributeKey<Boolean> auth =
AttributeKey.valueOf("auth");
@Override
protected void messageReceived(ChannelHandlerContext ctx, Message message) {
Attribute<Boolean> attr = ctx.attr(auth);
Channel ch = ctx.channel();
if (message instanceof LoginMessage) {
authenticate((LoginMessage) o);
attr.set(true);
} else (message instanceof GetDataMessage) {
if (Boolean.TRUE.equals(attr.get())) {
ch.write(fetchSecret((GetDataMessage) o));
} else {
fail();
}
}
}
...
}
下面这个比较有意思
Now that the state of the handler is attached to the ChannelHandlerContext, you can add the same handler instance to different pipelines:
public class DataServerInitializer extends ChannelInitializer<Channel> {
private static final DataServerHandler SHARED = new DataServerHandler();
@Override
public void initChannel(Channel channel) {
channel.pipeline().addLast("handler", SHARED);
}
}
这里和上一节状态管理的代码有些区别,都是DataServerHandler 为什么哪里的需要每次都new一个,而这里直接是一个静态的成员变量,也就是说可以共享的.
他们的区别仅仅是,前一节的DataServerHandler 使用了一个private boolean loggedIn; 来保存登录状态,而这里使用了一个AttributeKey.因为前一个DataServerHandler的状态是不能共享的,每个都应该有一个,如果共用一个,岂不是有一个人登录了,所有人都登录了?而AttributeKey是跟上下文绑定在一起,上下文每一个连接都有一个,所以不冲突
另外,我们注意到,@Sharable 这个注解被加在了本节的DataServerHandler 上,这表明他是可以共享的