需要实现下面几点
1.spring中启动netty
2.在netty中使用spring中管理的bean,spring的功能
3.netty需要使用spirng中bean处理外部的请求,所以netty的启动必须在spring完整启动后
首先Main类1 public class Main { 2 3 public static void main(String[] args) { 4 SpringApplication.run(ApplicationConfig.class, args); 5 } 6 }
在spring完整启动后再创建netty,开始监听端口,这个需求和spingboot自己的Tomcat启动类似
先看下tomcat在什么地方启动
1 @Override 2 protected void finishRefresh() { 3 super.finishRefresh(); 4 WebServer webServer = startWebServer(); 5 if (webServer != null) { 6 publishEvent(new ServletWebServerInitializedEvent(webServer, this)); 7 } 8 }
调用栈
AnnotationConfigServletWebServerApplicationContext(ServletWebServerApplicationContext).finishRefresh() line: 164 AnnotationConfigServletWebServerApplicationContext(AbstractApplicationContext).refresh() line: 552 AnnotationConfigServletWebServerApplicationContext(ServletWebServerApplicationContext).refresh() line: 142 SpringApplication.refresh(ApplicationContext) line: 775 SpringApplication.refreshContext(ConfigurableApplicationContext) line: 397 SpringApplication.run(String...) line: 316 SpringApplication.run(Class<?>[], String[]) line: 1260 SpringApplication.run(Class<?>, String...) line: 1248 Main.main(String[]) line: 9
可以看到tomcat是在finishRefresh之后才启动的,这时候spring已经做完了所有bean的处理,
但是好像没有给我们预留自定义的处理接口
1 refreshContext(context); 2 afterRefresh(context, applicationArguments); 3 stopWatch.stop(); 4 if (this.logStartupInfo) { 5 new StartupInfoLogger(this.mainApplicationClass) 6 .logStarted(getApplicationLog(), stopWatch); 7 } 8 listeners.started(context); 9 callRunners(context, applicationArguments);
向外层寻找发现了一个callRunners,并且支持自定义
综上,想要在Spring完整启动后,再开启Netty监听端口,最好的方法应该是实现ApplicationRunner
1 private EventLoopGroup bossGroup; 2 private EventLoopGroup workerGroup; 3 4 @Override 5 public void run(ApplicationArguments args) throws Exception { 6 new Thread(this::startNetty, "NettyServer").start(); 7 } 8 9 private void startNetty() { 10 int port = 7788; 11 logger.error("Netty Server Starting..."); 12 bossGroup = new NioEventLoopGroup(); 13 workerGroup = new NioEventLoopGroup(); 14 try { 15 ServerBootstrap b = new ServerBootstrap(); 16 b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) 17 .option(ChannelOption.SO_BACKLOG, 1024) 18 .childHandler(new ChannelInitializer<SocketChannel>() { 19 @Override 20 protected void initChannel(SocketChannel socketChannel) throws Exception { 21 socketChannel.pipeline().addLast(new IdleStateHandler(5, 5, 5, TimeUnit.SECONDS)); 22 socketChannel.pipeline().addLast(new TimeServerHandler()); 23 } 24 }); 25 26 ChannelFuture f = b.bind(port).sync(); 27 logger.error("Netty server build port:" + port); 28 29 f.channel().closeFuture().sync(); 30 } catch (Exception e) { 31 e.printStackTrace(); 32 } finally { 33 workerGroup.shutdownGracefully(); 34 bossGroup.shutdownGracefully(); 35 } 36 logger.error("Netty Server Shutdown completed"); 37 }