SpringBoot中CommandLineRunner详解(含源码)

这篇具有很好参考价值的文章主要介绍了SpringBoot中CommandLineRunner详解(含源码)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


SpringBoot中CommandLineRunner详解(含源码),SpringBoot,spring boot,java,后端,原力计划

前言

Spring Boot的CommandLineRunner接口是一个函数式接口,用于在Spring Boot应用程序启动后执行一些初始化操作。它提供了一个run方法,该方法在应用程序启动后被调用。

使用CommandLineRunner接口,可以在应用程序启动后执行一些必要的初始化操作,例如加载配置文件、初始化数据库连接、创建默认数据等。可以通过实现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");
    }
}
执行结果

SpringBoot中CommandLineRunner详解(含源码),SpringBoot,spring boot,java,后端,原力计划

在上面的示例中,我们创建了一个名为MyCommandLineRunner的类,并实现了CommandLineRunner接口。在run方法中,我们可以编写需要在应用程序启动后执行的初始化逻辑。

需要注意的是,实现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 ...");
    }
}
执行结果

SpringBoot中CommandLineRunner详解(含源码),SpringBoot,spring boot,java,后端,原力计划


通常用法

SpringBoot中CommandLineRunner详解(含源码),SpringBoot,spring boot,java,后端,原力计划

加载初始化数据

可以实现CommandLineRunner接口,在run方法中加载一些初始化数据到数据库等。适合做一些数据预加载工作。

示例
@Component
public class DataInitializer implements CommandLineRunner {

    @Autowired
    private UserRepository userRepository;

    @Override
    public void run(String... args) throws Exception {
        
        // 创建初始用户
        User admin = new User("admin", "123456");
        userRepository.save(admin);

        User normalUser = new User("user", "123456");
        userRepository.save(normalUser);
        
        System.out.println("数据加载完毕!");
    }
}

这里创建了一个 DataInitializer 类,实现 CommandLineRunner 接口。在 run() 方法中,我们注入了 UserRepository,然后创建了两个用户对象保存到数据库中。这个类会在 Spring Boot 应用启动完成后执行,从而实现了数据预加载的效果。通过 CommandLineRunner,我们可以灵活地在 Spring Boot 启动时进行一些初始化操作,如预先加载测试数据、插入管理员账户等,很好地增强了应用的功能。

假设我们有一个User模型和用户Repository,需要在Spring Boot启动时预加载几个用户数据,可以这样使用CommandLineRunner:

@Component
public class DataInitializer implements CommandLineRunner {

    @Autowired
    private UserRepository userRepository;

    @Override
    public void run(String... args) throws Exception {
        
        // 清除所有数据
        userRepository.deleteAll(); 
        
        // 创建几个用户
        User user1 = new User("John", "john@example.com");
        User user2 = new User("Mary", "mary@example.com");
        
        userRepository.save(user1);
        userRepository.save(user2);
        
        // 打印已保存用户数
        System.out.println("Number of users saved: " + userRepository.count());
    }

}

这里我们实现了CommandLineRunner接口,然后注入UserRepository bean。在run方法中,首先清空所有数据,然后创建两个用户对象并保存,最后打印已保存的用户数。这样在Spring Boot应用启动完成后,就会自动执行run方法,预加载指定的用户数据。

启动后打印应用信息

可以打印出一些应用启动信息,如启动端口、运行环境信息等,用于确认应用配置。

示例
@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")));
        // 打印当前环境
        log.info("当前环境: " + environment.getProperty("spring.profiles.active"));
        // 打印JDK版本
        log.info("JDK 版本: " + System.getProperty("java.version"));
        log.info("========= 打印启动信息结束 =========");

    }

}

执行打印结果

SpringBoot中CommandLineRunner详解(含源码),SpringBoot,spring boot,java,后端,原力计划

启动异步任务

可以使用多线程启动一些异步任务,进行后台数据处理等复杂业务逻辑。

示例
@Component
@Slf4j
public class AsyncTaskRunner implements CommandLineRunner {

    @Autowired
    private AsyncTaskService asyncTaskService;

    @Override
    public void run(String... args) throws Exception {
        log.info("========= 执行任务 =========");
        // 在新线程中执行任务
        new Thread(() -> {
            asyncTaskService.doTaskOne();
            asyncTaskService.doTaskTwo();
            asyncTaskService.doTaskThree();
        }).start();
    }

}

@Service
@Slf4j
class AsyncTaskService {

    public void doTaskOne() {
        log.info("执行任务1");
    }

    public void doTaskTwo() {
        log.info("执行任务2");
    }

    public void doTaskThree() {
        log.info("执行任务3");
    }
}

执行结果

[           main] org.example.runner.AsyncTaskRunner       : ========= 执行任务 =========
[       Thread-1] org.example.runner.AsyncTaskService      : 执行任务1
[       Thread-1] org.example.runner.AsyncTaskService      : 执行任务2
[       Thread-1] org.example.runner.AsyncTaskService      : 执行任务3
接口健康检查

可以调用并验证依赖服务的健康状态,如果不正常可以终止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("数据库服务不可用,退出应用!");
            System.exit(1);
        }

        if(!messageQueueService.isConnected()) {
            log.error("消息队列服务不可用,退出应用!");
            System.exit(1);
        }

        log.info("所有服务正常,应用启动。");

    }
}

这里我们注入两个依赖服务 DatabaseService 和 MessageQueueService。在run方法中,调用它们的健康检查方法,如果任何一个服务不可用,则直接调用System.exit(1)退出Spring Boot应用启动。

外部服务调用

可以在启动时调用外部服务,进行验证、数据同步等操作。

示例
@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();
        // 发送GET请求进行健康检查
        String response = restTemplate.getForObject(healthCheckUrl, String.class);

        // 根据响应判断健康状态
        if (response.contains("\"status\":\"UP\"")) {
            System.out.println("Application is healthy");
        } else {
            System.out.println("Application is not healthy");
        }
    }
}
参数校验

可以对输入的运行参数做校验,如果不满足条件可以终止Spring Boot启动。

示例
@Component
@Slf4j
public class ParameterValidator implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        // 校验参数1
        if(args.length < 2) {
            log.error("参数不正确,请传入至少2个参数!");
            System.exit(1);
        }

        // 校验参数2是否为数字
        if(!args[1].matches("\\d+")) {
            log.error("第二个参数必须是数字!");
            System.exit(1);
        }

        // 校验通过,应用继续启动
        log.info("参数校验通过,应用启动中...");
    }
}

在run方法中,我们可以对main方法输入的参数args进行自定义校验:

  • 检查参数数量
  • 校验参数类型

如果参数不满足需求,可以直接调用System.exit(1)来终止Spring Boot的启动。这样就可以在应用启动前验证参数的正确性,避免应用启动后发生未知错误。

动态设置配置

可以根据运行参数等条件动态设置Spring Boot的配置,实现不同环境的适配。

示例
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);

// 动态设置配置
        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();

        // 授权完成后继续启动
        log.info("管理员已授权,应用启动中...");
    }

    private void waitAuth() {
        // 死循环模拟等待管理员操作授权
        while(true) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                break;
            }
        }
    }

}

总结

通过 CommandLineRunner,我们可以深度控制 Spring Boot 应用的启动流程,在应用启动阶段增强各种自定义逻辑。是 Spring Boot 提供的一个很实用的扩展点。


源码获取

如果需要完整源码请关注公众号"架构殿堂" ,回复 "SpringBoot+CommandLineRunner"即可获得


写在最后

感谢您的支持和鼓励! 😊🙏

如果大家对相关文章感兴趣,可以关注公众号"架构殿堂",会持续更新AIGC,java基础面试题, netty, spring boot, spring cloud等系列文章,一系列干货随时送达!

SpringBoot中CommandLineRunner详解(含源码),SpringBoot,spring boot,java,后端,原力计划文章来源地址https://www.toymoban.com/news/detail-734002.html

到了这里,关于SpringBoot中CommandLineRunner详解(含源码)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • “从零开始学习Spring Boot:快速搭建Java后端开发环境“

    标题:从零开始学习Spring Boot:快速搭建Java后端开发环境 摘要:本文将介绍如何从零开始学习Spring Boot,并详细讲解如何快速搭建Java后端开发环境。通过本文的指导,您将能够快速搭建一个基于Spring Boot的Java后端开发环境并开始编写代码。 正文: 一、准备工作 在开始之前,

    2024年02月15日
    浏览(42)
  • ELADMIN - 免费开源 admin 后台管理系统,基于 Spring Boot 和 Vue ,包含前端和后端源码

    一款简单好用、功能强大的 admin 管理系统,包含前端和后端源码,分享给大家。 ELADMIN 是一款基于 Spring Boot、Jpa 或 Mybatis-Plus、 Spring Security、Redis、Vue 的前后端分离的后台管理系统。 ELADMIN 的作者在 Github 和 Gitee 上看了很多的项目,发现大多数都是基于 Mybatis , 而基于 Sp

    2024年02月04日
    浏览(47)
  • 【Spring Boot 源码学习】BootstrapRegistryInitializer 详解

    《Spring Boot 源码学习系列》 书接前文《初识 SpringApplication》,我们从 Spring Boot 的启动类 SpringApplication 上入手,了解了 SpringApplication 实例化过程。其中,有如下三块内容还未详细分析: 本篇博文就主要围绕 2.3 的内容展开,详细分析一下加载并初始化 BootstrapRegistryInitializer

    2024年02月04日
    浏览(29)
  • 【Spring Boot 源码学习】BootstrapRegistry 详解

    《Spring Boot 源码学习系列》 前面的博文《BootstrapRegistryInitializer 详解》,Huazie 带大家一起详细分析了 Spring Boot 启动时加载并初始化 BootstrapRegistryInitializer 及其相关的类的逻辑。其中有个 BootstrapRegistry 接口只是简单提及,本篇就详细分析一下 BootstrapRegistry 接口,这对于我们后

    2024年02月20日
    浏览(28)
  • 【Spring Boot 源码学习】HttpEncodingAutoConfiguration 详解

    Spring Boot 源码学习系列 前面的博文,我们从源码角度介绍了自动装配流程。虽然带大家从整体上有了清晰的认识,但是我们还不能熟练地运用。本篇就以 Spring Boot 内置的 http 编码功能为例,来带大家分析一下 HttpEncodingAutoConfiguration 的整个自动配置的过程。 在开始本篇的内容

    2024年02月08日
    浏览(29)
  • 【Spring Boot 源码学习】OnWebApplicationCondition 详解

    《Spring Boot 源码学习系列》 上篇博文带大家从 Spring Boot 源码深入详解了 OnBeanCondition ,那本篇也同样从源码入手,带大家深入了解 OnWebApplicationCondition 的过滤匹配实现。 在开始本篇的内容介绍之前,我们先来看看往期的系列文章【有需要的朋友,欢迎关注系列专栏】: Spr

    2024年02月08日
    浏览(29)
  • 【Spring Boot 源码学习】JedisConnectionConfiguration 详解

    《Spring Boot 源码学习系列》 上篇博文, Huazie 带大家从源码角度分析了 Spring Boot 内置的有关 Redis 的自动配置类【 RedisAutoConfiguration 】,其中有关 LettuceConnectionConfiguration 和 JedisConnectionConfiguration 这两个用于配置 Redis 连接的具体实现还未介绍。本篇就以我们常用的 Jedis 实现

    2024年02月05日
    浏览(34)
  • 【Spring Boot 源码学习】RedisAutoConfiguration 详解

    《Spring Boot 源码学习系列》 上篇博文, Huazie 带大家从源码角度分析了 Spring Boot 内置的 http 编码功能,进一步熟悉了自动配置的装配流程。本篇趁热打铁,继续带大家分析 Spring Boot 内置的有关 Redis 的自动配置类【 RedisAutoConfiguration 】。 在开始本篇的内容介绍之前,我们先来

    2024年02月07日
    浏览(28)
  • spring boot学习第六篇:SpringBoot 集成WebSocket详解

    1、WebSocket简介 WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。 2、为什么需要WebSocket HTTP 是基于请求响应式的,即通信只能由客户端发起,服务端做出响应,无状态,无连接。 无状态:每次连

    2024年01月21日
    浏览(40)
  • Spring Boot进阶(68):如何用SpringBoot轻松实现定时任务?集成Quartz来帮你!(附源码)

            Quartz是一个非常流行的开源调度框架,它提供了许多强大的功能,如定时任务调度、作业管理、任务持久化等。而SpringBoot是目前Java开发中非常流行的框架之一,其对各种开源框架集成非常方便。本篇文章将介绍如何在SpringBoot中集成Quartz,以便于更好的管理和调度

    2024年02月07日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包