Spring Boot2 系列教程(十五)定义系统启动任务的两种方式
在 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
运行结果如下:

总结
整体来说 ,这两种的用法的差异不大 ,主要体现在对参数的处理上,小伙伴可以根据项目中的实际情况选择合适的解决方案。相关案例已经上传到 GitHub,欢迎小伙伴们们下载:https://github.com/lenve/javaboy-code-samples
关注公众号【江南一点雨】,专注于 Spring Boot+微服务以及前后端分离等全栈技术,定期视频教程分享,关注后回复 Java ,领取松哥为你精心准备的 Java 干货!

Spring Boot2 系列教程(十五)定义系统启动任务的两种方式的更多相关文章
- Spring Boot2 系列教程 (十五) | 服务端参数校验之一
估计很多朋友都认为参数校验是客户端的职责,不关服务端的事.其实这是错误的,学过 Web 安全的都知道,客户端的验证只是第一道关卡.它的参数验证并不是安全的,一旦被有心人抓到可乘之机,他就可以有各种方法 ...
- Spring Boot定义系统启动任务的两种方式
Spring Boot定义系统启动任务的两种方式 概述 如果涉及到系统任务,例如在项目启动阶段要做一些数据初始化操作,这些操作有一个共同的特点,只在项目启动时进行,以后都不再执行,这里,容易想到web ...
- Spring Boot2 系列教程(十六)定时任务的两种实现方式
在 Spring + SpringMVC 环境中,一般来说,要实现定时任务,我们有两中方案,一种是使用 Spring 自带的定时任务处理器 @Scheduled 注解,另一种就是使用第三方框架 Qua ...
- Spring Boot2 系列教程(十)Spring Boot 整合 Freemarker
今天来聊聊 Spring Boot 整合 Freemarker. Freemarker 简介 这是一个相当老牌的开源的免费的模版引擎.通过 Freemarker 模版,我们可以将数据渲染成 HTML ...
- Spring Boot2 系列教程(十八)Spring Boot 中自定义 SpringMVC 配置
用过 Spring Boot 的小伙伴都知道,我们只需要在项目中引入 spring-boot-starter-web 依赖,SpringMVC 的一整套东西就会自动给我们配置好,但是,真实的项目环境比 ...
- Spring Boot2 系列教程(十四)CORS 解决跨域问题
今天和小伙伴们来聊一聊通过CORS解决跨域问题. 同源策略 很多人对跨域有一种误解,以为这是前端的事,和后端没关系,其实不是这样的,说到跨域,就不得不说说浏览器的同源策略. 同源策略是由 Netsca ...
- Spring Boot2 系列教程 (十四) | 统一异常处理
如题,今天介绍 SpringBoot 是如何统一处理全局异常的.SpringBoot 中的全局异常处理主要起作用的两个注解是 @ControllerAdvice 和 @ExceptionHandler ...
- Spring Boot2 系列教程 (十二) | 整合 thymeleaf
前言 如题,今天介绍 Thymeleaf ,并整合 Thymeleaf 开发一个简陋版的学生信息管理系统. SpringBoot 提供了大量模板引擎,包含 Freemarker.Groovy.Thym ...
- Spring Boot2 系列教程 (十) | 实现声明式事务
前言 如题,今天介绍 SpringBoot 的 声明式事务. Spring 的事务机制 所有的数据访问技术都有事务处理机制,这些技术提供了 API 用于开启事务.提交事务来完成数据操作,或者在发生错误 ...
随机推荐
- CSS——段落处理
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- 自定义JDBC工具类
因为数据库的连接代码都是固定的,为了将减少重复的代码的书写,可以将这些代码封装为一个工具类,获取数据库的连接对象. import java.sql.Connection; import java.sq ...
- QCustomplot使用分享(八) 绘制图表-加载cvs文件
目录 一.概述 二.效果图 三.源码讲解 1.源码结构 2.头文件 3.移动游标 4.设置坐标轴矩形个数 5.添加图表数据 6.设置折线图类型 6.其他函数 四.测试方式 1.测试工程 2.测试文件 ...
- Windows Docker 部署 Spring Boot 项目
目录 Docker Configuration Config IDEA Plugin Create Spring Boot Project Containerize It Use Dockerfile ...
- [LeetCode] 由 “打印机任务队列" 所想
一.这是个基础问题 Ref: Python之队列模拟算法(打印机问题)[首先研究这个问题作为开始] 任务队列 定义一个任务队列,来管理任务,而无需关心队列的”任务类型". # 自定义队列类 ...
- php 两种获取分类树的方法
php 两种获取分类树的方法 1. /** * 获取分类树 * @param array $array 数据源 * @param int $pid 父级ID * @param int $level 分 ...
- Python必备收藏!Pycharm 常用快捷键思维导图!
本内容首发公众号[计算机视觉联盟],关注获取更多资料! 考虑到可能图片压缩,将思维导图的pdf和jpg版本都上传了百度云,大家可以下载打印一张A4纸,方便查询! 公众号后台回复关键词: 2019082 ...
- java数据结构——递归(Recursion)例题持续更新中
继续学习数据结构递归,什么是递归呢?字面理解就是先递出去,然后回归,递归核心思想就是直接或间接调用本身,好比从前有座山,山里有位老和尚,在给小和尚讲故事,讲的是从前有座山,山里有位老和尚,在给小和尚讲 ...
- 在vue中使用[provide/inject]实现页面reload
在vue中实现页面刷新有不同的方法: 如:this.$router.go(0),location.reload()等,但是或多或少会存在问题,如页面会一闪等 所以建议使用[provide/inject ...
- JAVA线程通信之生产者与消费者
package cn.test.hf.test3; import java.util.concurrent.locks.Condition;import java.util.concurrent.lo ...