public abstract class AbstractServerBootstrap implements ApplicationListener<ContextRefreshedEvent>, DisposableBean {
public static EventLoopGroup workerGroup;
private static Logger logger = LoggerFactory.getLogger(AbstractServerBootstrap.class);
private static final String ZK_PREFIX = TopsConfReader.getConfContent("properties/crawler-autoissue.properties", "zk.prefix", TopsConfEnum.ConfScope.R);
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
if (isRootApplicationContext(event.getApplicationContext())){
new Thread(){
public void run(){
// Configure the server.
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.option(ChannelOption.SO_BACKLOG, 1024);
b.option(ChannelOption.SO_KEEPALIVE, Boolean.TRUE);
b.option(ChannelOption.TCP_NODELAY, Boolean.TRUE);
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(channelInitializer());
Channel ch = b.bind(getBoundIP(), getListeningPort()).sync().channel();
logger.info("启动netty server完成");
registerRPC();
ch.closeFuture().sync();
} catch(Exception e){
logger.error("启动netty server异常", e);
throw new RuntimeException(e);
}finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}.start();
}
}
/**
* 注册netty rpc
* @throws Exception
*/
private void registerRPC() throws Exception{
String rpcAddress = getBoundIP() + ":" + getListeningPort();
String shardId = "0";
String replicaId = RandomStringUtils.randomAlphanumeric(10);
TopsZookeeperBalancer.registerRpc(rpcAddress, ZK_PREFIX, getIssueSite().name(), shardId, replicaId);
}
/**
* 获取netty server 绑定的ip
* @return
*/
private String getBoundIP(){
return TopsAppRegistry.getLocalIP();
}
private boolean isRootApplicationContext(ApplicationContext context) {
return context.getParent() == null;
}
@Override
public void destroy() throws Exception {
}
protected ChannelInitializer<SocketChannel> channelInitializer(){
return new ChannelInitializer<SocketChannel>(){
@Override
public void initChannel(SocketChannel ch) {
channelPipeline(ch);
}
};
}
protected ChannelPipeline channelPipeline(Channel ch){
ChannelPipeline p = ch.pipeline();
p.addLast("httpCodec", new HttpServerCodec());
p.addLast("aggegator", new HttpObjectAggregator(64 * 1024 * 1024));
p.addLast("protocol", new NettyMethodInvokerServerCodec());
return p;
}
protected int getListeningPort(){
return 5566;
}
/**
* 获取比价站点名称
* @return
*/
protected abstract IssueSite getIssueSite();
}
首先,我们可以知道,启动一个ApplicationListener, 通过监视ContextRefreshedEvent,只要发现Spring有文件内容更新,这启动.其中isRootApplicationContext,通过设置是不是第一次刷新.