Spring Boot 定义系统启动任务,你会几种方式?
在 Servlet/Jsp 项目中,如果涉及到系统任务,例如在项目启动阶段要做一些数据初始化操作,这些操作有一个共同的特点,只在项目启动时进行,以后都不再执行,这里,容易想到web基础中的三大组件( Servlet、Filter、Listener )之一 Listener ,这种情况下,一般定义一个 ServletContextListener,然后就可以监听到项目启动和销毁,进而做出相应的数据初始化和销毁操作,例如下面这样:
public class MyListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
//在这里做数据初始化操作
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
//在这里做数据备份操作
}
}
当然,这是基础 web 项目的解决方案,如果使用了 Spring Boot,那么我们可以使用更为简便的方式。Spring Boot 中针对系统启动任务提供了两种解决方案,分别是 CommandLineRunner 和 ApplicationRunner,分别来看。
CommandLineRunner
使用 CommandLineRunner 时,首先自定义 MyCommandLineRunner1 并且实现 CommandLineRunner 接口:
@Component
@Order(100)
public class MyCommandLineRunner1 implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
}
}
关于这段代码,我做如下解释:
- 首先通过 @Compoent 注解将 MyCommandLineRunner1 注册为Spring容器中的一个 Bean。
- 添加 @Order注解,表示这个启动任务的执行优先级,因为在一个项目中,启动任务可能有多个,所以需要有一个排序。@Order 注解中,数字越小,优先级越大,默认情况下,优先级的值为 Integer.MAX_VALUE,表示优先级最低。
- 在 run 方法中,写启动任务的核心逻辑,当项目启动时,run方法会被自动执行。
- run 方法的参数,来自于项目的启动参数,即项目入口类中,main方法的参数会被传到这里。
此时启动项目,run方法就会被执行,至于参数,可以通过两种方式来传递,如果是在 IDEA 中,可以通过如下方式来配置参数:

另一种方式,则是将项目打包,在命令行中启动项目,然后启动时在命令行传入参数,如下:
java -jar devtools-0.0.1-SNAPSHOT.jar 三国演义 西游记
注意,这里参数传递时没有key,直接写value即可,执行结果如下:

ApplicationRunner
ApplicationRunner 和 CommandLineRunner 功能一致,用法也基本一致,唯一的区别主要体现在对参数的处理上,ApplicationRunner 可以接收更多类型的参数(ApplicationRunner 除了可以接收 CommandLineRunner 的参数之外,还可以接收 key/value形式的参数)。
使用 ApplicationRunner ,自定义类实现 ApplicationRunner 接口即可,组件注册以及组件优先级的配置都和 CommandLineRunner 一致,如下:
@Component
@Order(98)
public class MyApplicationRunner1 implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
List<String> nonOptionArgs = args.getNonOptionArgs();
System.out.println("MyApplicationRunner1>>>"+nonOptionArgs);
Set<String> optionNames = args.getOptionNames();
for (String key : optionNames) {
System.out.println("MyApplicationRunner1>>>"+key + ":" + args.getOptionValues(key));
}
String[] sourceArgs = args.getSourceArgs();
System.out.println("MyApplicationRunner1>>>"+Arrays.toString(sourceArgs));
}
}
当项目启动时,这里的 run 方法就会被自动执行,关于 run 方法的参数 ApplicationArguments ,我说如下几点:
- args.getNonOptionArgs();可以用来获取命令行中的无key参数(和CommandLineRunner一样)。
- args.getOptionNames();可以用来获取所有key/value形式的参数的key。
- args.getOptionValues(key));可以根据key获取key/value 形式的参数的value。
- args.getSourceArgs(); 则表示获取命令行中的所有参数。
ApplicationRunner 定义完成后,传启动参数也是两种方式,参数类型也有两种,第一种和 CommandLineRunner 一致,第二种则是 --key=value 的形式,在 IDEA 中定义方式如下:

或者使用 如下启动命令:
java -jar devtools-0.0.1-SNAPSHOT.jar 三国演义 西游记 --age=99
运行结果如下:

总结
整体来说 ,这两种的用法的差异不大 ,主要体现在对参数的处理上,小伙伴可以根据项目中的实际情况选择合适的解决方案。
关注公众号【江南一点雨】,专注于 Spring Boot+微服务,定期视频教程分享,关注后回复 Java ,领取松哥为你精心准备的 Java 干货!

Spring Boot 定义系统启动任务,你会几种方式?的更多相关文章
- Spring Boot定义系统启动任务的两种方式
Spring Boot定义系统启动任务的两种方式 概述 如果涉及到系统任务,例如在项目启动阶段要做一些数据初始化操作,这些操作有一个共同的特点,只在项目启动时进行,以后都不再执行,这里,容易想到web ...
- SpringBoot启动方式,Spring Boot 定义系统启动任务
SpringBoot启动方式,Spring Boot 定义系统启动任务 SpringBoot启动方式 1.1 方法一 1.2 方法二 1.2.1 start.sh 1.2.2 stop.sh 1.2. ...
- Spring Boot获取前端页面参数的几种方式总结
Spring Boot的一个好处就是通过注解可以轻松获取前端页面的参数,之后可以将参数经过一系列处理传送到后台数据库. 获得的方式有很多种,这里稍微总结一下,大致分为以下几种: 1.指定前端url请求 ...
- spring boot集成 servlet自动注册的两种方式
有两种方式:(两种方式同时存在时,@Bean优先@ServletComponentScan实例化,生成两个对象) 1)通过@ServletComponentScan类注解 扫描 带有@WebServl ...
- Spring的依赖注入(DI)三种方式
Spring依赖注入(DI)的三种方式,分别为: 1. 接口注入 2. Setter方法注入 3. 构造方法注入 下面介绍一下这三种依赖注入在Spring中是怎么样实现的. 首先我们需要以下几个 ...
- Spring Boot + Vue 前后端分离,两种文件上传方式总结
在Vue.js 中,如果网络请求使用 axios ,并且使用了 ElementUI 库,那么一般来说,文件上传有两种不同的实现方案: 通过 Ajax 实现文件上传 通过 ElementUI 里边的 U ...
- Spring Boot Maven Plugin打包异常及三种解决方法:Unable to find main class
[背景]spring-boot项目,打包成可执行jar,项目内有两个带有main方法的类并且都使用了@SpringBootApplication注解(或者另一种情形:你有两个main方法并且所在类都没 ...
- Spring Boot使用Servlet、Filter或Listener的方式
根据官方文档说明,有两种方式可以在你的Spring Boot应用中使用Servlet.Filter或Listener. 其一:将Servlet.Filter或Listener注册成Spring Bea ...
- Spring Boot 2 实战:常用读取配置的方式
1. 前言 在Spring Boot项目中我们经常需要读取application.yml配置文件的自定义配置,今天就来罗列一下从yaml读取配置文件的一些常用手段和方法. 2. 使用@Value注解 ...
随机推荐
- sudo pip install MySQLdb
安装数据库第三方包,报错: Could not find a version that satisfies the requirement MySQLdb (from versions: )No ma ...
- 开源纯C#工控网关+组态软件(十)移植到.NET Core
一. 引子 写这个开源系列已经十来篇了.自从十年前注册博客园以来,关注了张善友.老赵.xiaotie.深蓝色右手等一众大牛,也围观了逗比的吉日嘎啦.精密顽石等形形色色的园友.然而整整十年一篇文章都 ...
- 阿里Java架构师谈谈架构和如何成为一个Java架构师
架构的定义 我们来看看软件架构的一般定义: 程序和计算系统软件体系结构是指系统的一个或多个结构. 该结构包括软件的构建,构建的外部可见属性以及它们之间的相互关系. 该体系结构不是可操作的软件. 具体来 ...
- git-------基础(一)
更改连接仓库只用操作一次(先删后加) (1)git remote rm origin //若本地已经关联了一个远程库,则先删除已关联的 ...
- Tornado day1
Tornado 之路由配置 首先导入模块,使用Application方法中可配置多个路由,格式必须为列表中是元组 元组的第一个是配置的url,第二个参数时自定义的类(继承自RequestHandler ...
- .net Core 微服务框架 surging 使用
surging 是一个分布式微服务框架,提供高性能RPC远程服务调用,采用Zookeeper.Consul作为surging服务的注册中心, 集成了哈希,随机,轮询作为负载均衡的算法,RPC集成采用的 ...
- define 的全部使用方法
typedef的总结,以下是引用的内容(红色部分是我自己写的内容). 用途一: 定义一种类型的别名,而不只是简单的宏替换.可以用作同时声明指针型的多个对象.比如: char* pa, pb; // 这 ...
- PAT1094:The Largest Generation
1094. The Largest Generation (25) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yu ...
- 关于java集合类HashMap的理解
一.HashMap概述 HashMap基于哈希表的 Map 接口的实现.此实现提供所有可选的映射操作,并允许使用 null 值和 null 键.(除了不同步和允许使用 null 之外,HashMap ...
- Spring Cloud Sleuth服务链路追踪(zipkin)(转)
这篇文章主要讲述服务追踪组件zipkin,Spring Cloud Sleuth集成了zipkin组件. 一.简介 Spring Cloud Sleuth 主要功能就是在分布式系统中提供追踪解决方案, ...