作用
标有@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變成的共享了,是以不要在裡面定義可變的屬性,否則有可能會出現安全問題。