有一些特殊的任务需要在系统启动时执行,例如配置文件加载、数据库初始化等操作。
Spring Boot对此提供了两种解决方案:CommandLineRunner和ApplicationRunner。
CommandLineRunner和ApplicationRunner基本一致,差别主要体现在参数上。
1. CommandLineRunner
1. 实现CommandLineRunner接口
SpringBoot项目在启动时会遍历所有CommandLineRunner的实现类并调用其中的run方法,如果整个系统中有多个CommandLineRunner的实现类,那么可以使用@Order注解对这些实现类的调用顺序进行排序。
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@Order(1)
@Component
public class MyCommandLineRunner1 implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("MyCommandLineRunner1>>run"+ Arrays.toString(args));
}
}
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@Order(2)
@Component
public class MyCommandLineRunner2 implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("MyCommandLineRunner2>>run"+ Arrays.toString(args));
}
}
代码解释:
- @Order(1)注解用来描述CommandLineRunner的执行顺序,数字越小越先执行。
- run方法中是调用的核心逻辑,参数是系统启动时传入的参数,即入口类中main方法的参数(在调用SpringApplication.run方法时被传入Spring Boot项目中)。
2. 在系统启动时,配置传入的参数。
以IntelliJ IDEA为例,配置方式如下:
2. ApplicationRunner
ApplicationRunner的用法和CommandLineRunner基本一致,区别主要体现在run方法的参数上。
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Set;
@Order(1)
@Component
public class MyApplicationRunner1 implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
List<String> nonOptionArgs = args.getNonOptionArgs();
System.out.println("MyApplicationRunner1>>nonOptionArgs" + nonOptionArgs);
Set<String> optionNames = args.getOptionNames();
optionNames.forEach(optionName -> {
System.out.println("MyApplicationRunner1>>optionName>>key:" + optionName + ",val:" + args.getOptionValues(optionName));
});
}
}
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Set;
@Order(2)
@Component
public class MyApplicationRunner2 implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
List<String> nonOptionArgs = args.getNonOptionArgs();
System.out.println("MyApplicationRunner1>>nonOptionArgs" + nonOptionArgs);
Set<String> optionNames = args.getOptionNames();
optionNames.forEach(optionName -> {
System.out.println("MyApplicationRunner1>>optionName>>key:" + optionName + ",val:" + args.getOptionValues(optionName));
});
}
}
代码解释:
- @Order注解依然是用来描述执行顺序的,数字越小越优先执行。
- 不同于CommandLineRunner中run方法的String数组参数,这里run方法的参数是一个ApplicationArguments对象,如果想从ApplicationArguments对象中获取入口类中main方法接收的参数,调用ApplicationArguments中的getNonOptionArgs方法即可。ApplicationArguments中的getOptionNames方法用来获取项目启动命令行中参数的key,例如将本项目打成jar包,运行java-jar xxx.jar-name=Michael命令来启动项目,此时getOptionNames方法获取到的就是name,而getOptionValues方法则是获取相应的value。