一、前言
很久很久以前,在 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項目中,針對定義系統啓動任務,提供了兩種方案,分別是:CommandLineRunner
、ApplicationRunner
。
接下來,就分別來看看這兩種解決方案。
二、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));
}
}
下面,就對這段代碼進行說明,如下:
@Component
註解:表示將MyCommandLineRunner01
類註冊成爲Spring容器中的一個Bean。@Order
註解:表示該啓動任務的執行優先級,因爲,在一個項目中,可能存在着多個啓動任務,所以需要定義優先級。@Order
註解中的整數值越小,優先級越高,默認值是Integer_MAXVALUE
,表示優先級最低。run
方法中,是用來寫啓動任務的核心業務邏輯的,啓動項目時,run
方法會被執行。run
方法中的參數,來自於項目的啓動參數,即項目啓動類中main
方法的參數會被傳遞到此。
【命令行啓動項目】
另一種傳參方式,是先將項目打包,使用命令行啓動項目時,並傳入參數,如下:
java -jar commandlinerunner-0.0.1-SNAPSHOT.jar 武漢加油 中國加油
值得注意的是,這裏傳參沒有key,只有value,所以多個value用空格隔開即可,運行結果如下:
三、ApplicationRunner
其實,CommandLineRunner
和ApplicationRunner
的功能相同,用法也相同,唯一的區別主要體現在對參數的處理上,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結束>>>>>>>>>>>>>>>>");
}
}
和CommandLineRunner
中run
方法相同,都是在項目啓動時被執行,但是不同的是run
方法的參數,關於ApplicationArguments
參數,可以來看看該類型的參數中有哪些方法,作用分別是什麼?
args.getSourceArgs()
:表示獲取所有的參數。args.getNonOptionArgs()
:表示獲取參數中非key-value的參數(與CommandLineRunner
中相同)。args.getOptionNames()
:表示獲取參數中key-value形式的參數的key。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