Spring Boot 2 - 使用CommandLineRunner與ApplicationRunner

本篇文章我們將探討CommandLineRunner和ApplicationRunner的使用雌澄。

在閱讀本篇文章之前内斯,你可以新建一個(gè)工程匆笤,寫一些關(guān)于本篇內(nèi)容代碼纷跛,這樣會(huì)加深你對(duì)本文內(nèi)容的理解,關(guān)于如何快速創(chuàng)建新工程惋戏,可以參考我的這篇博客:

Spring Boot 2 - 創(chuàng)建新工程

概述

CommandLineRunner和ApplicationRunner是Spring Boot所提供的接口领追,他們都有一個(gè)run()方法。所有實(shí)現(xiàn)他們的Bean都會(huì)在Spring Boot服務(wù)啟動(dòng)之后自動(dòng)地被調(diào)用响逢。

由于這個(gè)特性绒窑,它們是一個(gè)理想地方去做一些初始化的工作,或者寫一些測(cè)試代碼舔亭。

CommandLineRunner

使用Application實(shí)現(xiàn)

在我們新建好工程后些膨,為了簡(jiǎn)單我們直接使用Application類實(shí)現(xiàn)CommandLineRunner接口,這個(gè)類的注解@SpringBootApplication會(huì)為我們自動(dòng)配置分歇。

package cn.examplecode.sb2runner;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Sb2runnerApplication implements CommandLineRunner {

    private static Logger logger = LoggerFactory.getLogger(Sb2runnerApplication.class);

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

    @Override
    public void run(String... args) throws Exception {
        logger.info("服務(wù)已啟動(dòng)傀蓉,執(zhí)行command line runner。");

        for (int i = 0; i < args.length; ++i) {
            logger.info("args[{}]: {}", i, args[i]);
        }
    }
}

接下來(lái)我們直接啟動(dòng)服務(wù)职抡,查看日志如下葬燎,發(fā)現(xiàn)run()方法被正常地執(zhí)行了:

Tomcat started on port(s): 8080 (http) with context path ''
Started Sb2runnerApplication in 2.204 seconds (JVM running for 3.161)
服務(wù)已啟動(dòng),執(zhí)行command line runner缚甩。

參數(shù)傳遞

run()方法有個(gè)可變參數(shù)args谱净,這個(gè)參數(shù)是用來(lái)接收命令行參數(shù)的,我們下面來(lái)加入?yún)?shù)來(lái)測(cè)試一下:


-w1070

然后重啟服務(wù)擅威,觀察日志壕探,可以看到參數(shù)被正常地接收到了:

Tomcat started on port(s): 8080 (http) with context path ''
Started Sb2runnerApplication in 1.888 seconds (JVM running for 2.41)
服務(wù)已啟動(dòng),執(zhí)行command line runner郊丛。
args[0]: --param=sth

命令行參數(shù)傳遞

之前我們說過使用Spring Boot的一大優(yōu)勢(shì)就是可以將工程直接打包成一個(gè)jar包而不需要單獨(dú)部署李请。打包成jar包后可以直接執(zhí)行該jar包進(jìn)行服務(wù)的啟動(dòng),這樣在執(zhí)行jar包時(shí)我們就可以傳入命令行參數(shù)厉熟,讓CommandLineRunner接收參數(shù)导盅。

這種場(chǎng)景在服務(wù)器上特別常用。比如我們想執(zhí)行某個(gè)操作揍瑟,又不想對(duì)外部暴露白翻,此時(shí)可以使用CommandLineRunner作為該操作的入口。

下面我們就打成jar包來(lái)演示一下绢片。

  1. 進(jìn)入終端界面滤馍,開始打包


    -w430
  2. 打包完成后岛琼,執(zhí)行該jar包,記得先把IDE的服務(wù)停掉巢株。


    -w1217

可以從日志中看到我們也正常地獲取到了參數(shù)槐瑞。通過傳遞參數(shù),在業(yè)務(wù)邏輯上我們可以根據(jù)不同的參數(shù)而執(zhí)行不同的操作纯续。

上面我們提到的只是一個(gè)CommandLineRunner随珠,如果我們有多個(gè)CommandLineRunner怎么辦呢?怎么控制它們執(zhí)行的順序呢猬错?

下面我們就來(lái)介紹如何指定執(zhí)行的順序。

指定執(zhí)行順序

Spring Boot為我們提供了一個(gè)注解"@Order"茸歧,可以用來(lái)指定執(zhí)行的順序倦炒,比如我們工程里面有三個(gè)CommandLineRunner:

@Component
@Order(1)
public class CommandRunner1 implements CommandLineRunner {

    private static Logger logger = LoggerFactory.getLogger(CommandRunner1.class);

    @Override
    public void run(String... args) throws Exception {
        logger.info("執(zhí)行第一個(gè)command line runner...");
    }

}


@Component
@Order(2)
public class CommandRunner2 implements CommandLineRunner {

    private static Logger logger = LoggerFactory.getLogger(CommandRunner2.class);

    @Override
    public void run(String... args) throws Exception {
        logger.info("執(zhí)行第二個(gè)command line runner...");
    }
    
}

@Component
@Order(3)
public class CommandRunner3 implements CommandLineRunner {

    private static Logger logger = LoggerFactory.getLogger(CommandRunner3.class);

    @Override
    public void run(String... args) throws Exception {
        logger.info("執(zhí)行第三個(gè)command line runner...");
    }
    
}

我們可以在該類的上面直接加入@Order注解,然后Spring Boot就會(huì)按照我們注解指定的順序從小到大的執(zhí)行了软瞎。很簡(jiǎn)單逢唤,是不是?

Tomcat started on port(s): 8080 (http) with context path ''
Started Sb2runnerApplication in 1.764 seconds (JVM running for 2.292)
執(zhí)行第一個(gè)command line runner...
執(zhí)行第二個(gè)command line runner...
執(zhí)行第三個(gè)command line runner...

ApplicationRunner

ApplicationRunner與CommandLineRunner做的事情是一樣的涤浇,也是在服務(wù)啟動(dòng)之后其run()方法會(huì)被自動(dòng)地調(diào)用鳖藕,唯一不同的是ApplicationRunner會(huì)封裝命令行參數(shù),可以很方便地獲取到命令行參數(shù)和參數(shù)值只锭。

@Component
public class ApplicationRunner1 implements ApplicationRunner {

    private static Logger logger = LoggerFactory.getLogger(ApplicationRunner1.class);

    @Override
    public void run(ApplicationArguments args) throws Exception {
        logger.info("執(zhí)行application runner...");
        logger.info("獲取到參數(shù): " + args.getOptionValues("param"));
    }
}

執(zhí)行結(jié)果:


-w533

我們可以發(fā)現(xiàn)著恩,通過run()方法的參數(shù)ApplicationArguments可以很方便地獲取到命令行參數(shù)的值。

所以如果你的工程需要獲取命令行參數(shù)的話蜻展,建議你使用ApplicationRunner喉誊。

總結(jié)

無(wú)論是CommandLineRunner還是ApplicationRunner,它們的目的都是在服務(wù)啟動(dòng)之后執(zhí)行一些操作纵顾。如果需要獲取命令行參數(shù)時(shí)則建議使用ApplicationRunner伍茄。

另一種場(chǎng)景是我們?cè)诜?wù)器上需要執(zhí)行某個(gè)操作,比如修正數(shù)據(jù)庫(kù)用戶的數(shù)據(jù)施逾,而又找不到合適的執(zhí)行入口敷矫,那么這就是它們理想的使用場(chǎng)景了。

我的博客中其他關(guān)于Spring Boot的所有文章可以點(diǎn)擊這里找到汉额,歡迎關(guān)注曹仗!

如果有問題可以留言,或者給我發(fā)郵件lloyd@examplecode.cn闷愤,期待我們共同學(xué)習(xí)與成長(zhǎng)整葡!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市讥脐,隨后出現(xiàn)的幾起案子遭居,更是在濱河造成了極大的恐慌啼器,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件俱萍,死亡現(xiàn)場(chǎng)離奇詭異端壳,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)枪蘑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門损谦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人岳颇,你說我怎么就攤上這事照捡。” “怎么了话侧?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵栗精,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我瞻鹏,道長(zhǎng)悲立,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任新博,我火速辦了婚禮薪夕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘赫悄。我一直安慰自己原献,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布涩蜘。 她就那樣靜靜地躺著嚼贡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪同诫。 梳的紋絲不亂的頭發(fā)上粤策,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音误窖,去河邊找鬼叮盘。 笑死,一個(gè)胖子當(dāng)著我的面吹牛霹俺,可吹牛的內(nèi)容都是我干的柔吼。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼丙唧,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼愈魏!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤培漏,失蹤者是張志新(化名)和其女友劉穎溪厘,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體牌柄,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡畸悬,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了珊佣。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蹋宦。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖咒锻,靈堂內(nèi)的尸體忽然破棺而出冷冗,到底是詐尸還是另有隱情,我是刑警寧澤虫碉,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布贾惦,位于F島的核電站,受9級(jí)特大地震影響敦捧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜碰镜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一兢卵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧绪颖,春花似錦秽荤、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至牍氛,卻和暖如春晨继,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背搬俊。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工紊扬, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人唉擂。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓餐屎,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親玩祟。 傳聞我的和親對(duì)象是個(gè)殘疾皇子腹缩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容