SpringBoot定义系统启动任务,你会几种?

一、前言

很久很久以前,在 servlet / jsp 项目中,如果是涉及到系统启动任务,例如:在项目刚启动的时候进行一些数据初始化操作,这类操作都有着一个共性,那就是只在项目刚启动时执行一次,后面不再执行。

当然,那些经历过 servlet / jsp 的朋友,脑袋立马能浮现Web基础中的三大组件(Servlet、Filter、Listener)中的Listener(监听器)。一般情况,定义一个ServletContextListener,便可以监听到项目的启动、销毁,这样方便对数据进行初始化、销毁操作。如下:

public class MyListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        //启动后执行,在这里做数据初始化操作
    }
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        //销毁前执行,可以在这里做数据备份操作
    }
}

上面提到只是基础的Web项目解决方案,现在使用了SpringBoot项目,这种操作更简单了。在SpringBoot项目中,针对定义系统启动任务,提供了两种方案,分别是:CommandLineRunnerApplicationRunner

接下来,就分别来看看这两种解决方案。

二、CommandLineRunner

首先,我们创建一个MyCommandLineRunner01类,并且实现CommandLineRunner接口,如下:

@Component
@Order(100)
public class MyCommandLineRunner01 implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.err.println("MyCommandLineRunner01>>>" + Arrays.toString(args));
    }
}

下面,就对这段代码进行说明,如下:

  1. @Component注解:表示将MyCommandLineRunner01类注册成为Spring容器中的一个Bean。
  2. @Order注解:表示该启动任务的执行优先级,因为,在一个项目中,可能存在着多个启动任务,所以需要定义优先级。@Order注解中的整数值越小,优先级越高,默认值是Integer_MAXVALUE,表示优先级最低。
  3. run方法中,是用来写启动任务的核心业务逻辑的,启动项目时,run方法会被执行。
  4. run方法中的参数,来自于项目的启动参数,即项目启动类中main方法的参数会被传递到此。

命令行启动项目

另一种传参方式,是先将项目打包,使用命令行启动项目时,并传入参数,如下:

java -jar commandlinerunner-0.0.1-SNAPSHOT.jar 武汉加油 中国加油

值得注意的是,这里传参没有key,只有value,所以多个value用空格隔开即可,运行结果如下:
在这里插入图片描述

三、ApplicationRunner

其实,CommandLineRunnerApplicationRunner的功能相同,用法也相同,唯一的区别主要体现在对参数的处理上,ApplicationRunner可以接收更多类型的参数(ApplicationRunner除了可以接收CommandLineRunner中类型的参数外,还能接收key-value形式的参数)。

使用ApplicationRunner除了实现的接口不同之外,其他用法和CommandLineRunner都是一样的,如下:

@Component
@Order(100)
public class MyApplicationRunner01 implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        String[] sourceArgs = args.getSourceArgs();
        System.err.println("sourceArgs>>>"+ Arrays.toString(sourceArgs));
        List<String> nonOptionArgs = args.getNonOptionArgs();
        System.err.println("nonOptionArgs>>>"+nonOptionArgs);
        Set<String> optionNames = args.getOptionNames();
        System.err.println(">>>>>>>>>>>>>>>>MyApplicationRunner01开始>>>>>>>>>>>>>>>>>");
        for (String optionName : optionNames) {
            System.err.println(optionName+":"+args.getOptionValues(optionName));
        }
        System.err.println(">>>>>>>>>>>>>>>>>MyApplicationRunner01结束>>>>>>>>>>>>>>>>");
    }
}

CommandLineRunnerrun方法相同,都是在项目启动时被执行,但是不同的是run方法的参数,关于ApplicationArguments参数,可以来看看该类型的参数中有哪些方法,作用分别是什么?

  1. args.getSourceArgs():表示获取所有的参数。
  2. args.getNonOptionArgs():表示获取参数中非key-value的参数(与CommandLineRunner中相同)。
  3. args.getOptionNames():表示获取参数中key-value形式的参数的key。
  4. args.getOptionValues():表示获取参数中key-value形式的参数的value。

ApplicationArguments定义完成后,传启动参数也是两种方式,非key-value形式的参数和CommandLineRunner中相同,对于key-value形式的参数,IDEA中如此定义,如下:

java -jar applicationrunner-0.0.1-SNAPSHOT.jar --name=mango --address=www.mango.com 武汉加油 中国加油

注意,这里的key-value形式的参数格式为:--key=value,非key-value形式参数与CommandLineRunner中相同,运行结果如下:
在这里插入图片描述

四、总结

经过两种方式的实践,可以看出两者之间主要在于对参数的处理不同,ApplicationRunner > CommandLineRunner,至于如何选择,就看项目中具体的需求了。

五、源码地址

CommandLineRunner源码地址:CommandLineRunner
ApplicationRunner源码地址:ApplicationRunner

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章