文章目录

  • Springboot中 启动netty的几种方法
  • 1.CommandLineRunner
  • 1.在Application中使用
  • 2.在netty的启动类中使用
  • 2.ApplicationListener
  • 3.PostConstruct


Springboot中 启动netty的几种方法

1.CommandLineRunner

CommandLineRunner这个接口是springboot提供用来实现数据预加载,当springboot项目启动的时候,便可以通过该接口跟随springboot执行代码逻辑 ,且在整个生命周期中 只会执行一次

1.在Application中使用

@SpringBootApplication
@ComponentScan(basePackages = {"com.ait.cloud", "org.n3r.idworker"})
public class CloudApplication implements CommandLineRunner {

    //将springutils交由spring进行管理
    @Bean
    public SpringUtil getSpringUtil(){
        return new SpringUtil();
    }

    public static void main(String[] args) {
        SpringApplication.run(CloudApplication.class, args);
    }

    @Autowired
    private NettyServer nettyServer;

    @Override
    public void run(String... args) throws Exception {

        this.nettyServer.start();

    }
}

如上代码是springboot的启动器实现了CommandLineRunner接口 ,并将该接口中的run方法重写

@Component
@Slf4j
public class NettyServer {

    private static NettyServer nettyServer;


    @PostConstruct
    public void init(){
        nettyServer = this;
    }

    @Value("${netty.port}")
    private  int port;


    private static class SingletionNettyServer{
        static final NettyServer instance = new NettyServer();
    }

    public static NettyServer getInstance(){
        return SingletionNettyServer.instance;
    }

    private EventLoopGroup mainGroup;
    private EventLoopGroup subGroup;
    private ServerBootstrap server;
    private ChannelFuture future;



    public NettyServer(){
        mainGroup = new NioEventLoopGroup();
        subGroup = new NioEventLoopGroup();
        server = new ServerBootstrap();
        server.group(mainGroup,subGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new NettyServerInitializer());
    }


    public void start(){
        log.info("通道配置");
        this.future = server.bind(nettyServer.port);
        log.info("netty server 启动完毕,启动端口为:"+nettyServer.port);
    }

}

将netty的服务端启动类交由spring进行管理 ,可以在application中直接注入 ,调用是西安写好的启动方法便可以将netty服务进行启动

启动项目可见 控制台已提示启动成功

2019-09-19 10:35:39.290  INFO 6752 --- [  restartedMain] c.a.c.modules.netty.sever.NettyServer    : 通道配置
2019-09-19 10:35:41.008  INFO 6752 --- [  restartedMain] c.a.c.modules.netty.sever.NettyServer    : netty server 启动完毕,启动端口为:10086
2019-09-19 10:35:41.710  INFO 6752 --- [  restartedMain] c.a.d.s.b.a.DruidDataSourceAutoConfigure : Init DruidDataSource
2019-09-19 10:35:42.213  INFO 6752 --- [  restartedMain] com.alibaba.druid.pool.DruidDataSource   : {dataSource-1} inited
2019-09-19 10:35:43.205  INFO 6752 --- [  restartedMain] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2019-09-19 10:35:43.774  INFO 6752 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2019-09-19 10:35:43.847  INFO 6752 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8086 (http) with context path '/api'
2019-09-19 10:35:43.852  INFO 6752 --- [  restartedMain] com.ait.cloud.CloudApplication           : Started CloudApplication in 17.151 seconds (JVM running for 20.083)

2.在netty的启动类中使用

@Component
@Slf4j
public class NettyServer implements CommandLineRunner {

    private static NettyServer nettyServer;


    @PostConstruct
    public void init(){
        nettyServer = this;
    }

    @Value("${netty.port}")
    private  int port;



    private static class SingletionNettyServer{
        static final NettyServer instance = new NettyServer();
    }

    public static NettyServer getInstance(){
        return SingletionNettyServer.instance;
    }

    private EventLoopGroup mainGroup;
    private EventLoopGroup subGroup;
    private ServerBootstrap server;
    private ChannelFuture future;



    public NettyServer(){
        mainGroup = new NioEventLoopGroup();
        subGroup = new NioEventLoopGroup();
        server = new ServerBootstrap();
        server.group(mainGroup,subGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new NettyServerInitializer());
    }


    public void start(){
        log.info("通道配置");
        this.future = server.bind(nettyServer.port);
        log.info("netty server 启动完毕,启动端口为:"+nettyServer.port);
    }


    @Override
    public void run(String... args) throws Exception {
        this.start();
    }


}

如上 直接将netty的启动类是实现CommandLineRunner并且复写run方法

启动项目

2019-09-19 13:30:30.532  INFO 6112 --- [  restartedMain] com.alibaba.druid.pool.DruidDataSource   : {dataSource-1} inited
2019-09-19 13:30:31.944  INFO 6112 --- [  restartedMain] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2019-09-19 13:30:32.603  INFO 6112 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2019-09-19 13:30:32.680  INFO 6112 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8086 (http) with context path '/api'
2019-09-19 13:30:32.685  INFO 6112 --- [  restartedMain] com.ait.cloud.CloudApplication           : Started CloudApplication in 8.264 seconds (JVM running for 10.749)
2019-09-19 13:30:32.687  INFO 6112 --- [  restartedMain] c.a.c.modules.netty.sever.NettyServer    : 通道配置
2019-09-19 13:30:33.985  INFO 6112 --- [  restartedMain] c.a.c.modules.netty.sever.NettyServer    : netty server 启动完毕,启动端口为:10086

除此之外 CommandLineRunner的实现类上还可以通过**@Order**这个注解来定义方法的启动顺序

例如 我们新建一个类来实现接口 并将@order注解加上 设置为1

@Slf4j
@Component
@Order(1)
public class test implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        log.info("我是第一个启动的方法");
    }
}

之后我们将netty的启动类上加上@order注解并设置为2

@Component
@Slf4j
@Order(2)
public class NettyServer implements CommandLineRunner {
@Override
    public void run(String... args) throws Exception {
        log.info("我是第二个启动的方法");
        this.start();
    }

之后我们启动项目 通过控制台可以看见 @Order注解中所配置的数字越小 其启动时候的优先级越高

2019-09-19 13:42:50.933  INFO 2340 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8086 (http) with context path '/api'
2019-09-19 13:42:50.937  INFO 2340 --- [  restartedMain] com.ait.cloud.CloudApplication           : Started CloudApplication in 7.87 seconds (JVM running for 10.365)
2019-09-19 13:42:50.940  INFO 2340 --- [  restartedMain] com.ait.cloud.modules.netty.sever.test   : 我是第一个启动的方法
2019-09-19 13:42:50.940  INFO 2340 --- [  restartedMain] c.a.c.modules.netty.sever.NettyServer    : 我是第二个启动的方法
2019-09-19 13:42:50.940  INFO 2340 --- [  restartedMain] c.a.c.modules.netty.sever.NettyServer    : 通道配置
2019-09-19 13:42:52.245  INFO 2340 --- [  restartedMain] c.a.c.modules.netty.sever.NettyServer    : netty server 启动完毕,启动端口为:10086

2.ApplicationListener

@Component
public class NettyBooter implements ApplicationListener<ContextRefreshedEvent> {
    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {

        if (contextRefreshedEvent.getApplicationContext().getParent() == null){
            try {
                //获取server实例  
                NettyServer.getInstance().start();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }
}

ContextRefreshedEvent

ApplicationContext 被初始化或刷新时,该事件被发布。这也可以在 ConfigurableApplicationContext接口中使用 **refresh()**方法来发生。此处的初始化是指:所有的Bean被成功装载,后处理Bean被检测并激活,所有Singleton Bean 被预实例化,ApplicationContext容器已就绪可用

2019-09-19 19:21:28.988  INFO 15368 --- [  restartedMain] c.a.c.modules.netty.sever.NettyServer    : 通道配置
2019-09-19 19:21:30.920  INFO 15368 --- [  restartedMain] c.a.c.modules.netty.sever.NettyServer    : netty server 启动完毕,启动端口为:10086
2019-09-19 19:21:30.959  INFO 15368 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8086 (http) with context path '/api'
2019-09-19 19:21:30.964  INFO 15368 --- [  restartedMain] com.ait.cloud.CloudApplication           : Started CloudApplication in 15.682 seconds (JVM running for 18.797)

3.PostConstruct

@PostConstruct
    public void start(){
        log.info("通道配置");
        this.future = server.bind(nettyServer.port);
        log.info("netty server 启动完毕,启动端口为:"+nettyServer.port);
    }

将server中的启动方法添加@PostConstruct注解 便可以在项目启动的时候进行方法的调用

2019-09-19 19:27:30.580  INFO 15868 --- [  restartedMain] c.a.c.modules.netty.sever.NettyServer    : 通道配置
2019-09-19 19:27:31.853  INFO 15868 --- [  restartedMain] c.a.c.modules.netty.sever.NettyServer    : netty server 启动完毕,启动端口为:10086
2019-09-19 19:27:32.294  INFO 15868 --- [  restartedMain] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2019-09-19 19:27:33.026  INFO 15868 --- [  restartedMain] o.s.b.d.a.OptionalLiveReloadServer       : LiveReload server is running on port 35729
2019-09-19 19:27:33.101  INFO 15868 --- [  restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8086 (http) with context path '/api'
2019-09-19 19:27:33.105  INFO 15868 --- [  restartedMain] com.ait.cloud.CloudApplication           : Started CloudApplication in 9.988 seconds (JVM running for 14.559)

— [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8086 (http) with context path ‘/api’
2019-09-19 19:27:33.105 INFO 15868 — [ restartedMain] com.ait.cloud.CloudApplication : Started CloudApplication in 9.988 seconds (JVM running for 14.559)