作用
标有@Sharable的Handler,代表了他是一个可以被分享的handler,这就是说服务器注册了这个handler后,可以分享给多个客户端使用,如果没有使用该注解,则每次客户端请求时,都必须重新创建一个handler。
报错代码
public class NettyChannelHandler extends ChannelInitializer<SocketChannel> {
private NettyHandler nettyHandler = new NettyHandler();
@Override
protected void initChannel(SocketChannel sc) throws Exception {
sc.pipeline().addLast(nettyHandler);
}
public class NettyHandler extends SimpleChannelInboundHandler {
@Override
public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
//省略逻辑
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
System.out.println("出现错误的,关闭");
ctx.close();
}
}
上述代码,在第一个客户端连接后完全没有问题,但在连接第二个客户端的时候就会出现下面的问题。
14:09:45.619 [nioEventLoopGroup-3-2] WARN io.netty.channel.ChannelInitializer - Failed to initialize a channel.
Closing: [id: 0xe7c2bd73, L:/127.0.0.1:9001 - R:/127.0.0.1:56799]
io.netty.channel.ChannelPipelineException:
com.ysw.netty_demo.Server.NettyHandler is not a @Sharable handler, so can't be added or removed multiple times.
解决
方法一:在每次客户端连接的时候,都重新创建一个Handler。修改继承ChannelInitializer的方法即可。
public class NettyChannelHandler extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel sc) throws Exception {
sc.pipeline().addLast(new NettyHandler());
}
方法二:使用@Sharable注解,使得Handler变成可以共享的。这个方法直接加个注解即可。(建议使用)
@Sharable
public class NettyHandler extends SimpleChannelInboundHandler {
@Override
public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
//省略逻辑
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
System.out.println("出现错误的,关闭");
ctx.close();
}
}
注:使用该方法的handler变成的共享了,所以不要在里面定义可变的属性,否则有可能会出现安全问题。