一文詳解SpringBoot中CommandLineRunner接口
前言
Spring Boot的CommandLineRunner接口是一個函數(shù)式接口,用于在Spring Boot應用程序啟動后執(zhí)行一些初始化操作。它提供了一個run方法,該方法在應用程序啟動后被調(diào)用。
使用CommandLineRunner接口,可以在應用程序啟動后執(zhí)行一些必要的初始化操作,例如加載配置文件、初始化數(shù)據(jù)庫連接、創(chuàng)建默認數(shù)據(jù)等。可以通過實現(xiàn)CommandLineRunner接口,并重寫run方法來定義自己的初始化邏輯。
實例
導入庫
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.1.0</version> </parent> <groupId>org.example</groupId> <artifactId>springboot-CommandLineRunner</artifactId> <version>1.0-SNAPSHOT</version> <name>Spring Boot banner</name> <description>Spring Boot and commandLineRunner</description> <properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies>
application.yaml
server: port: 8080 spring: profiles: active: dev
Runner
import lombok.extern.slf4j.Slf4j; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Component; @Component @Slf4j public class Runner implements CommandLineRunner { @Override public void run(String... args) throws Exception { log.info("The Runner start to initialize ..."); } }
SpringBootCommandLineRunnerApplication
import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication @Slf4j public class SpringBootCommandLineRunnerApplication { public static void main(String[] args) { SpringApplication.run(SpringBootCommandLineRunnerApplication.class, args); log.info("The service to end"); } }
執(zhí)行結果
在上面的示例中,我們創(chuàng)建了一個名為MyCommandLineRunner的類,并實現(xiàn)了CommandLineRunner接口。在run方法中,我們可以編寫需要在應用程序啟動后執(zhí)行的初始化邏輯。
需要注意的是,實現(xiàn)CommandLineRunner接口的類需要被Spring容器掃描到,可以使用@Component注解或其他方式將其注冊為Spring Bean。
先后順序示例
可以通過@Order()來設置Runner的先后順序,在上面例子的基礎上增加
OrderRunner1
import lombok.extern.slf4j.Slf4j; import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @Component @Order(1) @Slf4j public class OrderRunner1 implements CommandLineRunner { @Override public void run(String... args) throws Exception { log.info("The OrderRunner1 start to initialize ..."); } }
OrderRunner2
import lombok.extern.slf4j.Slf4j; import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @Component @Order(2) @Slf4j public class OrderRunner2 implements CommandLineRunner { @Override public void run(String... args) throws Exception { log.info("The OrderRunner2 start to initialize ..."); } }
執(zhí)行結果
通常用法
加載初始化數(shù)據(jù)
可以實現(xiàn)CommandLineRunner接口,在run方法中加載一些初始化數(shù)據(jù)到數(shù)據(jù)庫等。適合做一些數(shù)據(jù)預加載工作。
示例
@Component public class DataInitializer implements CommandLineRunner { @Autowired private UserRepository userRepository; @Override public void run(String... args) throws Exception { // 創(chuàng)建初始用戶 User admin = new User("admin", "123456"); userRepository.save(admin); User normalUser = new User("user", "123456"); userRepository.save(normalUser); System.out.println("數(shù)據(jù)加載完畢!"); } }
這里創(chuàng)建了一個 DataInitializer 類,實現(xiàn) CommandLineRunner 接口。在 run() 方法中,我們注入了 UserRepository,然后創(chuàng)建了兩個用戶對象保存到數(shù)據(jù)庫中。這個類會在 Spring Boot 應用啟動完成后執(zhí)行,從而實現(xiàn)了數(shù)據(jù)預加載的效果。通過 CommandLineRunner,我們可以靈活地在 Spring Boot 啟動時進行一些初始化操作,如預先加載測試數(shù)據(jù)、插入管理員賬戶等,很好地增強了應用的功能。
假設我們有一個User模型和用戶Repository,需要在Spring Boot啟動時預加載幾個用戶數(shù)據(jù),可以這樣使用CommandLineRunner:
@Component public class DataInitializer implements CommandLineRunner { @Autowired private UserRepository userRepository; @Override public void run(String... args) throws Exception { // 清除所有數(shù)據(jù) userRepository.deleteAll(); // 創(chuàng)建幾個用戶 User user1 = new User("John", "john@example.com"); User user2 = new User("Mary", "mary@example.com"); userRepository.save(user1); userRepository.save(user2); // 打印已保存用戶數(shù) System.out.println("Number of users saved: " + userRepository.count()); } }
這里我們實現(xiàn)了CommandLineRunner接口,然后注入UserRepository bean。在run方法中,首先清空所有數(shù)據(jù),然后創(chuàng)建兩個用戶對象并保存,最后打印已保存的用戶數(shù)。這樣在Spring Boot應用啟動完成后,就會自動執(zhí)行run方法,預加載指定的用戶數(shù)據(jù)。
啟動后打印應用信息
可以打印出一些應用啟動信息,如啟動端口、運行環(huán)境信息等,用于確認應用配置。
示例
@Component @Slf4j public class AppInfoPrinter implements CommandLineRunner { @Autowired private Environment environment; @Override public void run(String... args) throws Exception { log.info("========= 打印啟動信息 ========="); // 打印應用端口 log.info(("端口號: " + environment.getProperty("server.port"))); // 打印當前環(huán)境 log.info("當前環(huán)境: " + environment.getProperty("spring.profiles.active")); // 打印JDK版本 log.info("JDK 版本: " + System.getProperty("java.version")); log.info("========= 打印啟動信息結束 ========="); } }
執(zhí)行打印結果
啟動異步任務
可以使用多線程啟動一些異步任務,進行后臺數(shù)據(jù)處理等復雜業(yè)務邏輯。
示例
@Component @Slf4j public class AsyncTaskRunner implements CommandLineRunner { @Autowired private AsyncTaskService asyncTaskService; @Override public void run(String... args) throws Exception { log.info("========= 執(zhí)行任務 ========="); // 在新線程中執(zhí)行任務 new Thread(() -> { asyncTaskService.doTaskOne(); asyncTaskService.doTaskTwo(); asyncTaskService.doTaskThree(); }).start(); } } @Service @Slf4j class AsyncTaskService { public void doTaskOne() { log.info("執(zhí)行任務1"); } public void doTaskTwo() { log.info("執(zhí)行任務2"); } public void doTaskThree() { log.info("執(zhí)行任務3"); } }
執(zhí)行結果
[ main] org.example.runner.AsyncTaskRunner : ========= 執(zhí)行任務 ========= [ Thread-1] org.example.runner.AsyncTaskService : 執(zhí)行任務1 [ Thread-1] org.example.runner.AsyncTaskService : 執(zhí)行任務2 [ Thread-1] org.example.runner.AsyncTaskService : 執(zhí)行任務3
接口健康檢查
可以調(diào)用并驗證依賴服務的健康狀態(tài),如果不正??梢越K止Spring Boot啟動。
示例
@Component @Slf4j public class HealthCheckRunner implements CommandLineRunner { @Autowired private DatabaseService databaseService; @Autowired private MessageQueueService messageQueueService; @Override public void run(String... args) throws Exception { if(!databaseService.isConnected()) { log.error("數(shù)據(jù)庫服務不可用,退出應用!"); System.exit(1); } if(!messageQueueService.isConnected()) { log.error("消息隊列服務不可用,退出應用!"); System.exit(1); } log.info("所有服務正常,應用啟動。"); } }
這里我們注入兩個依賴服務 DatabaseService 和 MessageQueueService。在run方法中,調(diào)用它們的健康檢查方法,如果任何一個服務不可用,則直接調(diào)用System.exit(1)退出Spring Boot應用啟動。
外部服務調(diào)用
可以在啟動時調(diào)用外部服務,進行驗證、數(shù)據(jù)同步等操作。
示例
@Component public class OtherServiceCheckRunner implements CommandLineRunner { @Override public void run(String... args) throws Exception { // 健康檢查的URL String healthCheckUrl = "http://localhost:8080/actuator/health"; RestTemplate restTemplate = new RestTemplate(); // 發(fā)送GET請求進行健康檢查 String response = restTemplate.getForObject(healthCheckUrl, String.class); // 根據(jù)響應判斷健康狀態(tài) if (response.contains("\"status\":\"UP\"")) { System.out.println("Application is healthy"); } else { System.out.println("Application is not healthy"); } } }
參數(shù)校驗
可以對輸入的運行參數(shù)做校驗,如果不滿足條件可以終止Spring Boot啟動。
示例
@Component @Slf4j public class ParameterValidator implements CommandLineRunner { @Override public void run(String... args) throws Exception { // 校驗參數(shù)1 if(args.length < 2) { log.error("參數(shù)不正確,請傳入至少2個參數(shù)!"); System.exit(1); } // 校驗參數(shù)2是否為數(shù)字 if(!args[1].matches("\\d+")) { log.error("第二個參數(shù)必須是數(shù)字!"); System.exit(1); } // 校驗通過,應用繼續(xù)啟動 log.info("參數(shù)校驗通過,應用啟動中..."); } }
在run方法中,我們可以對main方法輸入的參數(shù)args進行自定義校驗:
檢查參數(shù)數(shù)量校驗參數(shù)類型
如果參數(shù)不滿足需求,可以直接調(diào)用System.exit(1)來終止Spring Boot的啟動。這樣就可以在應用啟動前驗證參數(shù)的正確性,避免應用啟動后發(fā)生未知錯誤。
動態(tài)設置配置
可以根據(jù)運行參數(shù)等條件動態(tài)設置Spring Boot的配置,實現(xiàn)不同環(huán)境的適配。
示例 application.yaml
myconfig: foo: 十五 bar: 1
MyConfig
@Component @Data @ConfigurationProperties(prefix = "myconfig") public class MyConfig { private String foo; private int bar; // getter和setter方法省略 @Override public String toString() { return "MyConfig{" + "foo='" + foo + '\'' + ", bar=" + bar + '}'; } }
ConfigRunner
@Component @EnableConfigurationProperties(MyConfig.class) public class ConfigRunner implements CommandLineRunner { @Autowired private MyConfig myConfig; @Override public void run(String... args) throws Exception { // 打印當前配置 System.out.println("Current config: " + myConfig); // 動態(tài)設置配置 myConfig.setFoo("new value"); myConfig.setBar(100); // 打印更新后的配置 System.out.println("Updated config: " + myConfig); } }
啟動阻塞
可以使應用啟動后阻塞住主線程,防止main方法直接退出,從而保持Spring Boot應用運行。
示例
@Component @Slf4j public class StartBlocker implements CommandLineRunner { @Override public void run(String... args) throws Exception { // 加載提示信息 log.info("正在等待管理員授權..."); // 等待授權,阻塞啟動流程 waitAuth(); // 授權完成后繼續(xù)啟動 log.info("管理員已授權,應用啟動中..."); } private void waitAuth() { // 死循環(huán)模擬等待管理員操作授權 while(true) { try { Thread.sleep(1000); } catch (InterruptedException e) { break; } } } }
總結
通過 CommandLineRunner,我們可以深度控制 Spring Boot 應用的啟動流程,在應用啟動階段增強各種自定義邏輯。是 Spring Boot 提供的一個很實用的擴展點。
以上就是一文詳解SpringBoot中CommandLineRunner接口的詳細內(nèi)容,更多關于SpringBoot CommandLineRunner接口的資料請關注腳本之家其它相關文章!
相關文章
SpringBoot多數(shù)據(jù)源讀寫分離的自定義配置問題及解決方法
這篇文章主要介紹了SpringBoot多數(shù)據(jù)源讀寫分離的自定義配置,我們可以通過自定義配置數(shù)據(jù)庫配置類來解決這個問題,方式有很多,不同的業(yè)務采用的方式也不同,下面我簡單的介紹我們項目的使用的方法2022-06-06解決FeignClient發(fā)送post請求異常的問題
這篇文章主要介紹了FeignClient發(fā)送post請求異常的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07SpringBoot Actuator未授權訪問漏洞解決方案
工作的時候遇到過提示Spring Boot后端存在Actuator未授權訪問漏洞,網(wǎng)上有很多詳細的解釋文章,在這里做一個簡單的總結、介紹和分享,需要的朋友可以參考下2023-09-09面向對象和面向過程的區(qū)別(動力節(jié)點java學院整理)
很多朋友不清楚面向對象和面向過程有什么區(qū)別,接下來小編給大家整理了關于面向對象和面向過程的區(qū)別講解,感興趣的朋友可以參考下2017-04-04用SpringBoot+Vue+uniapp小程序實現(xiàn)在線房屋裝修管理系統(tǒng)
這篇文章主要介紹了用SpringBoot+Vue+uniapp實現(xiàn)在線房屋裝修管理系統(tǒng),針對裝修樣板信息管理混亂,出錯率高,信息安全性差,勞動強度大,費時費力等問題開發(fā)了這套系統(tǒng),需要的朋友可以參考下2023-03-0370行Java代碼實現(xiàn)深度神經(jīng)網(wǎng)絡算法分享
這篇文章主要介紹了70行Java代碼實現(xiàn)深度神經(jīng)網(wǎng)絡算法分享,涉及神經(jīng)網(wǎng)絡的計算過程,神經(jīng)網(wǎng)絡的算法程序實現(xiàn),多層神經(jīng)網(wǎng)絡完整程序實現(xiàn)等相關內(nèi)容,具有一定參考價值,需要的朋友可以參考下。2017-11-11關于springboot中對sqlSessionFactoryBean的自定義
這篇文章主要介紹了springboot中對sqlSessionFactoryBean的自定義方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-12-12