ChannelHandlerContext可以确保一个ChannelHandler和它的pipeline和其他的handler联系起来
- handler可以通知pipeline里的下一个handler
- handler可以动态的修改它的pipeline在运行时
通知: ChannelHandler可以通知同一个ChannelPipeline 中的下一个Handler 修改 pipeline() 通过这个方法,handler可以修改同一个ChannelPipeline最近的一个 handler
保存上下文,以后需要的时候再用
public class MyHandler extends ChannelHandlerAdapter {
private ChannelHandlerContext ctx;
public void beforeAdd(ChannelHandlerContext ctx) {
this.ctx = ctx;
}
public void login(String username, password) {
ctx.write(new LoginMessage(username, password));
}
...
}
3.存储状态类的信息 attr(AttributeKey)
4.一个handler可以有不止一个的context 一个handler可以被添加到多个pipeline,也可以被一个pipeline添加多次
public class FactorialHandler extends ChannelHandlerAdapter {
private final AttributeKey<Integer> counter = AttributeKey.valueOf("counter");
// This handler will receive a sequence of increasing integers starting
// from 1.
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
Attribute<Integer> attr = ctx.getAttr(counter);
Integer a = ctx.getAttr(counter).get();
if (a == null) {
a = 1;
}
attr.set(a * (Integer) msg);
}
}
// Different context objects are given to "f1", "f2", "f3", and "f4" even if
// they refer to the same handler instance. Because the FactorialHandler
// stores its state in a context object (using an AttributeKey), the factorial is
// calculated correctly 4 times once the two pipelines (p1 and p2) are active.
FactorialHandler fh = new FactorialHandler();
ChannelPipeline p1 = Channels.pipeline();
p1.addLast("f1", fh);
p1.addLast("f2", fh);
ChannelPipeline p2 = Channels.pipeline();
p2.addLast("f3", fh);
p2.addLast("f4", fh);
注意: 每个channel都有一个pipeline 每个handler都有一个context
[attr相当于就是session.一开始我有疑惑,每个handler都有一个context, 那么context.attr() 相当于每个handler的attr都不一样了,怎么会像是session的功能呢? 原来,attr是附着在channel上的,而不是context上.context.attr实际上调用的还是channel.attr] ** 上面的理解是错误的,不应该吧attr类比为session. 通常,我们怎么标识客户端呢?一个ip+port ,放在全局的map里作为key.那么这个map才相当于session 而attr要理解为附件,这个附近可以是哪些东西呢,比如一个auth串, 权限验证的东西, 加密的东西等等.**
一个bossGroup是一个线程组,在bind的时候创建ServerChannel,也就意味着即使这是一个线程组, 那么只绑定一个端口的时候,那么也只有一条线程accept用户的接入请求。
handler() childHandler()
handler() 里的handler是在bossGroup里执行的,也就是说当只绑定一个端口的时候,这个handler是和accept在一个线程中的。而childHandler里的handler则是在workerGroup里执行的