文章13 | 阅读 5414 | 点赞0
ChannelHandler用于处理Channel产生的IO事件,如服务端和客户端之间的数据读写read、write,客户端发起连接请求connect,服务端绑定监听端口bind等,用户可以自定义ChannelHandler接口的实现来处理IO事件。以及可以将该IO事件往下传给ChannelPipeline中的下一个ChannelHandler。
ChannelHandler的子类型主要是根据IO事件是数据读入还是写出来区分:
ChannelHandler只对定义对Channel产生的IO事件的数据进行处理逻辑,而通过ChannelHandlerContext的包装,增强的功能包括:
ChannelPipeline中每个ChannelHandler经常需要有自己的一些状态数据,先定义一个状态数据类:
public interface Message {
// your methods here
}
ChannelHandler状态管理的实现方式包括:
public class DataServerHandler extends SimpleChannelInboundHandler<Message> {
// 成员变量记录当前连接的Channel是否登录了
private boolean loggedIn;
@Override
public void channelRead0(ChannelHandlerContext ctx, Message message) {
if (message instanceof LoginMessage) {
authenticate((LoginMessage) message);
loggedIn = true;
// 只有连接成功的Channel才能发起获取数据的请求
} else (message instanceof GetDataMessage) {
if (loggedIn) {
ctx.writeAndFlush(fetchSecret((GetDataMessage) message));
} else {
fail();
}
}
}
}
public class DataServerInitializer extends ChannelInitializer<Channel> {
@Override
public void initChannel(Channel channel) {
// 每个Channel都new一个DataServerHandler
channel.pipeline().addLast("handler", new DataServerHandler());
}
}
// 共享注解
@Sharable
public class DataServerHandler extends SimpleChannelInboundHandler<Message> {
// 状态数据的key和value的类型
private final AttributeKey<Boolean> auth = AttributeKey.valueOf("auth");
@Override
public void channelRead(ChannelHandlerContext ctx, Message message) {
// 通过ChannelHandlerContext的attr方法取出
Attribute<Boolean> attr = ctx.attr(auth);
if (message instanceof LoginMessage) {
authenticate((LoginMessage) o);
// 通过Attribute的set方法设值
attr.set(true);
} else (message instanceof GetDataMessage) {
if (Boolean.TRUE.equals(attr.get())) {
ctx.writeAndFlush(fetchSecret((GetDataMessage) o));
} else {
fail();
}
}
}
}
在ChannelInitializer调用:
// 状态数据交个ChannelHandlerContext管理了,所以可以将同一个ChannelHandler添加到多个ChannelPipeline中了,即多个Channel共享同一个ChannelHandler实例
public class DataServerInitializer extends ChannelInitializer<Channel> {
// 静态变量,则由DataServerInitializer初始化的Channel都共享同一个DataServerHandler实例
private static final DataServerHandler SHARED = new DataServerHandler();
@Override
public void initChannel(Channel channel) {
// 不再使用new创建
channel.pipeline().addLast("handler", SHARED);
}
}
@Sharable是一种声明作用,说明可以看:Java @Sharable
在Netty中如果自己使用@Sharable修饰一个ChannelHandler实现,则需保证能被多个Channel共享;在Netty框架自身提供的有@Sharable注解修饰的ChannelHandler则可以只创建new一个实例,在多个Channel中重用这个实例;否则记得每个Channel都要new一个新的ChannelHandler实例再添加到ChannelPipeline中。
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://xieyizun.blog.csdn.net/article/details/85159202
内容来源于网络,如有侵权,请联系作者删除!