package com.lefu.remote.netty.client; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelInitializer; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.lefu.remote.netty.EventLoopGroupFactory; /** * * @author jiang.li * */ public abstract class AbstractClientConfigure implements NettyClient { private final Logger log = LoggerFactory.getLogger(getClass()); protected Bootstrap bootstrap; protected NioEventLoopGroup bossGroup; protected ChannelInitializer<? extends Channel> channelInitializer; private boolean bossGroupSetted = false; private AtomicBoolean isStarted = new AtomicBoolean(false); private AtomicBoolean isShutdown = new AtomicBoolean(false); private int bossGroupSize = 1; /** * 配置Client options * @param bootstrap */ protected abstract void options(Bootstrap bootstrap); @Override public Channel connect(String host, int port) throws Exception { SocketAddress socketAddress = new InetSocketAddress(host, port); return connect(socketAddress); } @Override public Channel connect(SocketAddress socketAddress) throws Exception { if (!isStarted.get()) { throw new IllegalStateException("Netty client bootstrap is not start!"); } ChannelFuture channelFuture = bootstrap.connect(socketAddress); final CountDownLatch downLatch = new CountDownLatch(1); channelFuture.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { downLatch.countDown(); }}); downLatch.await(); if (!channelFuture.isSuccess()) { throw new RuntimeException("Connect to " + socketAddress.toString() + " fail"); } return channelFuture.channel(); } @Override public void init() throws Exception { if (isStarted.get()) { throw new IllegalStateException("Netty client bootstrap already started!"); } configure(); if (channelInitializer == null) { throw new IllegalStateException("ChannelInitializer is null, unset in configure() ?"); } if (!bossGroupSetted) { bossGroup = EventLoopGroupFactory.newNioLoopGroup(bossGroupSize); } bootstrap = new Bootstrap(); bootstrap.group(bossGroup) .channel(NioSocketChannel.class) .handler(channelInitializer); options(bootstrap); isStarted.set(true); isShutdown.set(false); log.info(String.format("Netty client started with properties -> [BossGroupSize=%1$d]", bossGroup.executorCount())); } @Override public void destroy() { if (isShutdown.get()) { return; } if (bossGroup != null) { bossGroup.shutdownGracefully(); } isStarted.set(false); isShutdown.set(true); bossGroupSetted = false; log.info("Netty client bootstrap is going shutdown!"); } public NioEventLoopGroup getBossGroup() { return bossGroup; } public void setBossGroup(NioEventLoopGroup bossGroup) { if (bossGroup != null) { bossGroupSetted = true; this.bossGroup = bossGroup; } } public void setBossGroupSize(int bossGroupSize) { this.bossGroupSize = bossGroupSize; } protected void setChannelInitializer( ChannelInitializer<? extends Channel> channelInitializer) { this.channelInitializer = channelInitializer; } public boolean getIsStarted() { return isStarted.get(); } public boolean getIsShutdown() { return isShutdown.get(); } public Bootstrap getBootstrap() { return bootstrap; } }