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 {
    }
}

关于这段代码,我做如下解释:

  1. 首先通过 @Compoent 注解将 MyCommandLineRunner1 注册为Spring容器中的一个 Bean。
  2. 添加 @Order注解,表示这个启动任务的执行优先级,因为在一个项目中,启动任务可能有多个,所以需要有一个排序。@Order 注解中,数字越小,优先级越大,默认情况下,优先级的值为 Integer.MAX_VALUE,表示优先级最低。
  3. 在 run 方法中,写启动任务的核心逻辑,当项目启动时,run方法会被自动执行。
  4. 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 ,我说如下几点:

  1. args.getNonOptionArgs();可以用来获取命令行中的无key参数(和CommandLineRunner一样)。
  2. args.getOptionNames();可以用来获取所有key/value形式的参数的key。
  3. args.getOptionValues(key));可以根据key获取key/value 形式的参数的value。
  4. 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 干货!

原文地址:https://www.cnblogs.com/lenve/p/11732245.html

时间: 2024-10-20 04:45:13

Spring Boot2 系列教程(十五)定义系统启动任务的两种方式的相关文章

Spring Boot2 系列教程 (十五) | 服务端参数校验之一

估计很多朋友都认为参数校验是客户端的职责,不关服务端的事.其实这是错误的,学过 Web 安全的都知道,客户端的验证只是第一道关卡.它的参数验证并不是安全的,一旦被有心人抓到可乘之机,他就可以有各种方法来摸拟系统的 Http 请求,访问数据库的关键数据.轻则导致服务器宕机,重则泄露数据.所以,这时就需要设置第二道关卡,服务端验证了. 老项目的服务端校验 @RestController @RequestMapping("/student") public class ValidateOne

Spring Boot2 系列教程 (十二) | 整合 thymeleaf

前言 如题,今天介绍 Thymeleaf ,并整合 Thymeleaf 开发一个简陋版的学生信息管理系统. SpringBoot 提供了大量模板引擎,包含 Freemarker.Groovy.Thymeleaf.Velocity 以及 Mustache,SpringBoot 中推荐使用 Thymeleaf 作为模板引擎,因为 Thymeleaf 提供了完美的 SpringMVC 支持.Thymeleaf 是新一代 Java 模板引擎,在 Spring 4 后推荐使用. 什么是模板引擎? Thym

Spring Boot2 系列教程 (十) | 实现声明式事务

前言 如题,今天介绍 SpringBoot 的 声明式事务. Spring 的事务机制 所有的数据访问技术都有事务处理机制,这些技术提供了 API 用于开启事务.提交事务来完成数据操作,或者在发生错误时回滚数据. 而 Spring 的事务机制是用统一的机制来处理不同数据访问技术的事务处理,Spring 的事务机制提供了一个 PlatformTransactionManager 接口,不同的数据访问技术的事务使用不同的接口实现,如下表: 数据访问技术 实现 JDBC DataSourceTrans

Spring Boot2 系列教程 (十四) | 统一异常处理

如题,今天介绍 SpringBoot 是如何统一处理全局异常的.SpringBoot 中的全局异常处理主要起作用的两个注解是 @ControllerAdvice 和 @ExceptionHandler ,其中 @ControllerAdvice 是组件注解,添加了这个注解的类能够拦截 Controller 的请求,而 ExceptionHandler 注解可以设置全局处理控制里的异常类型来拦截要处理的异常. 比如:@ExceptionHandler(value = NullPointExcept

Spring Boot2 系列教程 (十八) | 整合 MongoDB

微信公众号:一个优秀的废人.如有问题,请后台留言,反正我也不会听. 前言 如题,今天介绍下 SpringBoot 是如何整合 MongoDB 的. MongoDB 简介 MongoDB 是由 C++ 编写的非关系型数据库,是一个基于分布式文件存储的开源数据库系统,它将数据存储为一个文档,数据结构由键值 (key=>value) 对组成.MongoDB 文档类似于 JSON 对象.字段值可以包含其他文档,数组及文档数组,非常灵活.存储结构如下: { "studentId": &qu

Spring Boot2 系列教程 (五) | yaml 配置文件详解

自定义属性加载 首先构建 SpringBoot 项目,不会的看这篇旧文 使用 IDEA 构建 Spring Boot 工程. 首先在项目根目录 src >> resource >>?application.properties 文件下加入以下自定义属性: # 防止读取乱码 spring.http.encoding.charset=UTF-8 # 项目启动端口 server.port=9999 # 自定义配置 com.nasus.author.name=一个优秀的废人 com.nas

Spring Boot2 系列教程 (八) | 配置日志

前言 如题,今天介绍 springboot 默认日志的配置. 默认日志 Logback 默认情况下,Spring Boot 用 Logback 来记录日志,并用 INFO 级别输出到控制台.如果你在平常项目中用过 Spring Boot,你应该已经注意到很多 INFO 级别的日志了.默认日志长这样: 2019-02-18 22:02:14.907 INFO 23384 --- [ main] org.hibernate.Version : HHH000412: Hibernate Core {5

Spring Boot2 系列教程(四)理解Spring Boot 配置文件 application.properties

在 Spring Boot 中,配置文件有两种不同的格式,一个是 properties ,另一个是 yaml . 虽然 properties 文件比较常见,但是相对于 properties 而言,yaml 更加简洁明了,而且使用的场景也更多,很多开源项目都是使用 yaml 进行配置(例如 Hexo).除了简洁,yaml 还有另外一个特点,就是 yaml 中的数据是有序的,properties 中的数据是无序的,在一些需要路径匹配的配置中,顺序就显得尤为重要(例如我们在 Spring Cloud

Spring Boot2 系列教程(二十三)理解 Spring Data Jpa

有很多读者留言希望松哥能好好聊聊 Spring Data Jpa! 其实这个话题松哥以前零零散散的介绍过,在我的书里也有介绍过,但是在公众号中还没和大伙聊过,因此本文就和大家来仔细聊聊 Spring Data 和 Jpa! 本文大纲: 1. 故事的主角 1.1 Jpa 1.1.1 JPA 是什么 Java Persistence API:用于对象持久化的 API Java EE 5.0 平台标准的 ORM 规范,使得应用程序以统一的方式访问持久层 1.1.2 JPA 和 Hibernate 的关