Spring Boot 2 - 使用CommandLineRunner与ApplicationRunner
本篇文章我们将探讨CommandLineRunner和ApplicationRunner的使用。
在阅读本篇文章之前,你可以新建一个工程,写一些关于本篇内容代码,这样会加深你对本文内容的理解,关于如何快速创建新工程,可以参考我的这篇博客:
概述
CommandLineRunner和ApplicationRunner是Spring Boot所提供的接口,他们都有一个run()方法。所有实现他们的Bean都会在Spring Boot服务启动之后自动地被调用。
由于这个特性,它们是一个理想地方去做一些初始化的工作,或者写一些测试代码。
CommandLineRunner
使用Application实现
在我们新建好工程后,为了简单我们直接使用Application类实现CommandLineRunner接口,这个类的注解@SpringBootApplication会为我们自动配置。
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("服务已启动,执行command line runner。"); for (int i = 0; i < args.length; ++i) { logger.info("args[{}]: {}", i, args[i]); } } }
接下来我们直接启动服务,查看日志如下,发现run()方法被正常地执行了:
Tomcat started on port(s): 8080 (http) with context path '' Started Sb2runnerApplication in 2.204 seconds (JVM running for 3.161) 服务已启动,执行command line runner。
参数传递
run()方法有个可变参数args,这个参数是用来接收命令行参数的,我们下面来加入参数来测试一下:
然后重启服务,观察日志,可以看到参数被正常地接收到了:
Tomcat started on port(s): 8080 (http) with context path '' Started Sb2runnerApplication in 1.888 seconds (JVM running for 2.41) 服务已启动,执行command line runner。 args[0]: --param=sth
命令行参数传递
之前我们说过使用Spring Boot的一大优势就是可以将工程直接打包成一个jar包而不需要单独部署。打包成jar包后可以直接执行该jar包进行服务的启动,这样在执行jar包时我们就可以传入命令行参数,让CommandLineRunner接收参数。
这种场景在服务器上特别常用。比如我们想执行某个操作,又不想对外部暴露,此时可以使用CommandLineRunner作为该操作的入口。
下面我们就打成jar包来演示一下。
- 进入终端界面,开始打包
- 打包完成后,执行该jar包,记得先把IDE的服务停掉。
可以从日志中看到我们也正常地获取到了参数。通过传递参数,在业务逻辑上我们可以根据不同的参数而执行不同的操作。
上面我们提到的只是一个CommandLineRunner,如果我们有多个CommandLineRunner怎么办呢?怎么控制它们执行的顺序呢?
下面我们就来介绍如何指定执行的顺序。
指定执行顺序
Spring Boot为我们提供了一个注解"@Order",可以用来指定执行的顺序,比如我们工程里面有三个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("执行第一个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("执行第二个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("执行第三个command line runner..."); } }
我们可以在该类的上面直接加入@Order注解,然后Spring Boot就会按照我们注解指定的顺序从小到大的执行了。很简单,是不是?
Tomcat started on port(s): 8080 (http) with context path '' Started Sb2runnerApplication in 1.764 seconds (JVM running for 2.292) 执行第一个command line runner... 执行第二个command line runner... 执行第三个command line runner...
ApplicationRunner
ApplicationRunner与CommandLineRunner做的事情是一样的,也是在服务启动之后其run()方法会被自动地调用,唯一不同的是ApplicationRunner会封装命令行参数,可以很方便地获取到命令行参数和参数值。
@Component public class ApplicationRunner1 implements ApplicationRunner { private static Logger logger = LoggerFactory.getLogger(ApplicationRunner1.class); @Override public void run(ApplicationArguments args) throws Exception { logger.info("执行application runner..."); logger.info("获取到参数: " + args.getOptionValues("param")); } }
执行结果:
我们可以发现,通过run()方法的参数ApplicationArguments可以很方便地获取到命令行参数的值。
所以如果你的工程需要获取命令行参数的话,建议你使用ApplicationRunner。
总结
无论是CommandLineRunner还是ApplicationRunner,它们的目的都是在服务启动之后执行一些操作。如果需要获取命令行参数时则建议使用ApplicationRunner。
另一种场景是我们在服务器上需要执行某个操作,比如修正数据库用户的数据,而又找不到合适的执行入口,那么这就是它们理想的使用场景了。
我的博客中其他关于Spring Boot的所有文章可以点击这里找到,欢迎关注!
如果有问题可以留言,或者给我发邮件lloyd@examplecode.cn,期待我们共同学习与成长!
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
javascript 作用域详解
javascript 作用域详解作用域理解:定义的变量、函数生效的范围。javascript 有全局作用域和函数作用域两种。注:es6实现let 块级作用域不是js原生的,底层同样是通过var实现的。如果想了解具体细节,请访问babel官方 对es6中let 进行解析。 执行上下文范围:一段内或者一个函数内;全局:函数声明、变量声明 。范围:;函数:函数声明、变量声明、this、arguments。范围:一个函数内部; 函数、变量声明提升 foo(); //打印a var foo = 1; function foo (){ console.log(’a‘) }; console.log(foo); //1 //实际的执行顺序为 function foo(){ //函数声明优先于变量的声明 console.log("a"); } //var a ; 重复声明,这儿被省略了。 foo(); //打印a foo = 1; //给foo赋值为1 console.log(foo); //1 当js引擎执行一个 执行上下文代码块时,执行顺序为:1.函数声明 function a(){};(函数优先...
- 下一篇
Java异常被抛出或被捕获之后,代码是否继续执行的问题
在写程序的时候,我们经常被教导,要对异常的信息进行处理,哪里该抛出异常。但是,更多的时候,我们只是模仿异常的抛出,却不知道为什么要这样抛异常(被catch了?被向上抛了?后面的代码是否执行了?)。 接下来,我就简单的说一下异常抛出后的代码执行问题。此处不讨论自定义异常,因为自定义异常有自己的处理方式。 一、结论: 凡是有异常的地方,需要有处理异常的地方。(示例:Demo1, Demo2) 只要异常被处理,异常处理之后的代码都可以正常执行。(示例:Demo1, Demo2) 异常被往上抛出,则抛出异常之后的代码将不被执行。(示例:Demo2, Demo3) 二、示例代码 接下来用两段代码来说明异常抛出后代码执行的顺序 示例1. Demo1.java /** * 抛出异常的代码是放在 try 中 */ public class Demo1 {
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- CentOS8编译安装MySQL8.0.19
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- Hadoop3单机部署,实现最简伪集群
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- CentOS关闭SELinux安全模块
- CentOS8编译安装MySQL8.0.19
- CentOS7设置SWAP分区,小内存服务器的救世主
- 设置Eclipse缩进为4个空格,增强代码规范
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池