SpringBoot2.x入门:使用CommandLineRunner钩子接口

简介: 这篇文章是《SpringBoot2.x入门》专辑的「第6篇」文章,使用的SpringBoot版本为2.3.1.RELEASE,JDK版本为1.8。这篇文章主要简单聊聊钩子接口CommandLineRunner和ApplicationRunner,下文有时候统称两者为Runner。

微信截图_20220513123019.png


前提



这篇文章是《SpringBoot2.x入门》专辑的第6篇文章,使用的SpringBoot版本为2.3.1.RELEASEJDK版本为1.8


这篇文章主要简单聊聊钩子接口CommandLineRunnerApplicationRunner,下文有时候统称两者为Runner


Runner的回调时机



参考org.springframework.boot.SpringApplication#run()方法的源码,可以知道CommandLineRunnerApplicationRunner的回调时机:


微信截图_20220513123028.png


在所有的CommandLineRunnerApplicationRunner回调之前,下面的步骤已经确保执行完毕:


  1. Environment内置变量的创建和属性填充已经完成。
  2. Banner已经打印完毕。
  3. ApplicationContextBeanFactory创建完成,并且完成了上下文刷新(refreshContext),意味着所有单例的Bean完成了初始化以及属性装配。
  4. Servlet容器启动成功,如内置的TomcatJetty容器已经正常启动,可以正常接收请求和处理。
  5. 启动信息完成打印,一般会看到日志输出类似Started OrderExportApplication in XXX seconds (JVM running for YYY)

也就是CommandLineRunner或者ApplicationRunner回调的时候,可以使用所有上下文中存在的单例BeanEnvironment内置变量中已经存在的属性值,所以很多时候demo项目都会在CommandLineRunner或者ApplicationRunner中进行操作。


Runner的简单使用



CommandLineRunnerApplicationRunner没有本质区别,唯一的区别在:CommandLineRunner#run()接收来自于main方法的参数,类型是字符串数组(不定字符串数组),而ApplicationRunner#run()接收ApplicationArguments类型的参数,对应的实现类是DefaultApplicationArguments


可以直接把注解@Component应用在CommandLineRunner或者ApplicationRunner的实现类上,相对于把对应的实现单例添加到Spring上下文中。例如:


@Slf4j
@Component
public class CustomCommandLineRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        log.info("CustomCommandLineRunner runs...");
    }
}
复制代码


也可以通过@Bean注解,直接作用于CommandLineRunner的匿名类对应的方法上,例如:


@Slf4j
@Configuration
public class CommandLineRunners {
    @Bean
    public CommandLineRunner commandLineRunner(){
        return args -> log.info("CommandLineRunners commandLineRunner");
    }
}
复制代码


或者直接在启动类实现CommandLineRunner接口(这种方式不推荐使用):


@Slf4j
@SpringBootApplication
public class Ch5Application implements CommandLineRunner {
    public static void main(String[] args) {
        SpringApplication.run(Ch5Application.class, args);
    }
    @Override
    public void run(String... args) throws Exception {
        log.info("Ch5Application CommandLineRunner runs...");
    }
}
复制代码


此外,可以通过实现org.springframework.core.Ordered接口或者@Order注解定义Runner回调的顺序,指定的顺序数越小,优先级越高。


Runner的使用场景



这一小节是根据个人的编程习惯提出的建议。Runner钩子接口回调的时候如果抛出异常,会直接导致应用进程退出,所以如果在Runner回调方法中一定要注意异常的捕获和处理。基于这个特性,结合前面分析Runner接口的回调时机,它适用的主要场景有:


  • 打印日志用于标识服务启动成功或者标识某些属性加载成功。
  • 设置属性值或者启动组件,例如开启某些组件的开关、一些应用级别缓存的加载、启动定时任务等等。
  • 预加载数据(更常见于一些测试场景中,可以结合@Profile注解使用,指定特定的profile才生效)。
  • 需要使用main方法的入参。


下面使用CommandLineRunner启动所有Quartz中的Job(记得先引入依赖spring-boot-starter-quartz以及quartz),为了简单起见调度器使用内存态:


@Slf4j
@DisallowConcurrentExecution
public class SimpleJob extends QuartzJobBean {
    @Override
    protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
        log.info("SimpleJob run...");
    }
}
@Component
public class QuartzCommandLineRunner implements CommandLineRunner {
    @Autowired
    private Scheduler scheduler;
    @Override
    public void run(String... args) throws Exception {
        JobDetail job = JobBuilder.newJob(SimpleJob.class).storeDurably().withIdentity(JobKey.jobKey("SimpleJob")).build();
        // 30秒执行一次
        Trigger trigger = TriggerBuilder.newTrigger()
                .withSchedule(SimpleScheduleBuilder.simpleSchedule().repeatForever().withIntervalInSeconds(30))
                .forJob(job).build();
        scheduler.scheduleJob(job, trigger);
    }
}
复制代码


启动应用后,日志如下:


微信截图_20220513123038.png


小结



本文demo项目仓库:



(本文完 c-2-d e-a-20200712 封面图来自于《可塑性记忆》)

相关文章
|
20天前
|
存储 前端开发 Java
SpringBoot使用云端资源url下载文件的接口写法
在Spring Boot中实现从云端资源URL下载文件的功能可通过定义REST接口完成。示例代码展示了一个`FileDownloadController`,它包含使用`@GetMapping`注解的方法`downloadFile`,此方法接收URL参数,利用`RestTemplate`下载文件,并将文件字节数组封装为`ByteArrayResource`返回给客户端。此外,通过设置HTTP响应头,确保文件以附件形式下载。这种方法适用于从AWS S3或Google Cloud Storage等云服务下载文件。
118 7
|
14天前
|
Dubbo JavaScript Java
SpringBoot 调用外部接口的三种方式
SpringBoot不仅继承了Spring框架原有的特性,还简化了应用搭建与开发流程。在SpringBoot项目中,有时需要访问外部接口或URL。本文介绍三种不使用Dubbo的方式:一是利用原生`httpClient`发起请求;二是使用`RestTemplate`,支持GET和POST请求,包括`getForEntity`、`getForObject`及`postForEntity`等方法;三是采用`Feign`客户端简化HTTP请求,需引入相关依赖并在启动类上启用Feign客户端。这三种方式均能有效实现对外部服务的调用。
|
6天前
|
存储 监控 Java
|
4天前
|
JavaScript 前端开发 Java
SpringBoot 引入 smart-doc 接口文档管理插件,以及统一接口返回,最后推送到 Torna,进行统一管理
本文介绍了如何在SpringBoot项目中整合smart-doc接口文档管理插件,实现接口文档的生成和统一管理,并展示了如何将文档推送到Torna接口文档管理系统进行进一步的集中管理。
11 0
SpringBoot 引入 smart-doc 接口文档管理插件,以及统一接口返回,最后推送到 Torna,进行统一管理
|
5天前
|
Java
SpringBoot 接口并发限制(Semaphore)
SpringBoot 接口并发限制(Semaphore)
14 1
|
6天前
|
JSON 安全 Java
|
3天前
|
Java
SpringBoot java 一个接口,多个实现,客户定制化
SpringBoot java 一个接口,多个实现,客户定制化
10 0
|
5天前
|
JavaScript Java Spring
SpringBoot 接口输出文件流 & Vue 下载文件流,获取 Header 中的文件名
SpringBoot 接口输出文件流 & Vue 下载文件流,获取 Header 中的文件名
8 0
|
7天前
|
JavaScript Java Spring
Spring Boot 接口返回文件流
Spring Boot 接口返回文件流
15 0
|
20天前
|
前端开发 Java 网络架构
SpringBoot使用接口下载图片的写法
在Spring Boot中实现图片下载功能涉及定义一个REST接口来发送图片文件。首先,创建`ImageController`类,并在其中定义`downloadImage`方法,该方法使用`@GetMapping`注解来处理HTTP GET请求。方法内部,通过`Files.readAllBytes`读取图片文件到字节数组,再将该数组封装成`ByteArrayResource`。接着,设置`HttpHeaders`以指定文件名为`image.jpg`并配置为附件下载。