这是我参与更文挑战的第3天,活动详情查看: 更文挑战
Hello, everybody! 今天小编已经在倔金更文第三天,之前也在CSDN啊简书这类博客网站更过一段时间的文章,但每次都坚持不下去,立了Flag要每天写点东西,可总是坚持不了两天,Flag立了倒,倒了立,一直得不到正反馈,最后自己都气馁了(ps:引用倔金?,说到我的心坎里啦,哈哈哈哈)这次希望自己可以坚持下去,加油⛽️
下面进入正题??????
需求背景:
在Spring Boot项目启动的时候要进行一批数据初始化到JavaCache内存中以保证后续接口的可用性,如何解决项目启动时初始化资源,在我们实际工作中,这样的需求也是很常见的,在项目启动的时候需要做一些初始化的操作,如初始化线程池,初始化数据资源等。
解决方法
为了达到这个目的,SpringBoot提供了一种简单的实现方案就是添加一个model并实现CommandLineRunner
或 ApplicationRunner
接口,实现功能的代码放在实现的run方法中,spring boot会自动监测到它们,并使用@Component注解使其成为bean;
CommandLineRunner和ApplicationRunner:
- CommandLineRunner和ApplicationRunner的区别
- 不同之处在于CommandLineRunner接口的run()方法接收String数组作为参数,即是最原始的参数,没有做任何处理;而ApplicationRunner接口的run()方法接收ApplicationArguments对象作为参数,是对原始参数做了进一步的封装。
- 当程序启动时,我们传给main()方法的参数可以被实现CommandLineRunner和ApplicationRunner接口的类的run()方法访问,即可接收启动服务时传过来的参数。我们可以创建多个实现CommandLineRunner和ApplicationRunner接口的类。为了使他们按一定
顺序执行
,可以使用@Order注解或实现Ordered接口。
话不多说,上代码,先来看一下他们的简单使用:
CommandLineRunner:
package com.wechat.wechatservice.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.stream.Collectors;
/**
*
*
* @author TZ
* @version 1.0
* @date 6/2/21 11:39 AM
*/
@Component
@Slf4j
public class CommandLineRunnerBean implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
String strArgs = Arrays.stream(args).collect(Collectors.joining("|"));
log.info("Application started with arguments:" + strArgs);
}
}
复制代码
启动类Application.java
/**
* @author tz
* @create 2019-09-24 14:30
*/
@SpringBootApplication
public class WeChatApplication {
private static final Logger logger = LoggerFactory.getLogger(WeChatApplication.class);
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(WeChatApplication.class, args);
HelloService service = context.getBean(HelloService.class);
logger.info(service.getMessage());
}
}
复制代码
import org.springframework.stereotype.Service;
@Service
public class HelloService {
public String getMessage(){
return "Hello World!";
}
}
复制代码
现在可以启动我们项目看一下效果了,我们自己测试的时候通过在idea里配置启动参数启动即可,如下图:
当然也可以使用java-jar jar包名 参数1 参数2 参数3来进行启动
我们来看一下启动输出结果:
2021-06-02 11:50:17.038 INFO 31223 --- [ restartedMain] c.w.wechatservice.WeChatApplication : Started WeChatApplication in 5.858 seconds (JVM running for 6.818)
2021-06-02 11:50:17.040 INFO 31223 --- [ restartedMain] c.w.w.config.CommandLineRunnerBean : Application started with arguments:data1|data2|data3
2021-06-02 11:50:17.042 INFO 31223 --- [ restartedMain] c.w.wechatservice.WeChatApplication : Hello World!
复制代码
ApplicationRunner同理如下:
/**
*
*
* @author tz
* @version 1.0
* @date 6/2/21 1:42 PM
*/
@Component
@Slf4j
public class ApplicationRunnerBean implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
String strArgs = Arrays.stream(args.getSourceArgs()).collect(Collectors.joining("|"));
log.info("ApplicationRunnerBean ---> {}",strArgs);
}
}
复制代码
Program arguments:作为main 方法的args参数传入
ApplicationArguments有如下方法:
boolean containsOption(String name) :返回从参数分析的选项参数集是否包含具有给定名称的选项。
List getNonOptionArgs() : 返回已分析的非选项参数集合。
Set getOptionNames() :返回所有选项参数的名称。例如,如果参数为“-foo=bar–debug”,则返回值[“foo”,“debug”]。
List getOptionValues(String name): 返回与具有给定名称的参数选项关联的值集合。返回与具有给定名称的参数选项关联的值集合。
如果选项存在且没有参数(例如:“–foo”),则返回空集合([])如果该选项存在且具有单个值(例如“–foo=bar”),则返回一个包含一个元素的集合([“bar”])
如果选项存在并且有多个值(例如“–foo=bar–foo=baz”),则返回一个集合,其中每个值都有元素([“bar”、“baz”])
如果选项不存在,则返回空值String[] getSourceArgs():
返回传递给应用程序的未处理的原始参数
CommandLineRunner和ApplicationRunner的执行顺序:
在spring boot程序中,我们可以使用不止一个实现CommandLineRunner和ApplicationRunner的bean。为了有序执行这些bean的run()方法,可以使用@Order注解或Ordered接口按顺序执行各个实现的Bean。
@Component
@Order(1)
public class CommandLineRunnerBean1 implements CommandLineRunner {
@Override
public void run(String... args) {
System.out.println("CommandLineRunnerBean 1");
}
}
------------------------------------------------------------------------
@Component
@Order(2)
public class ApplicationRunnerBean1 implements ApplicationRunner {
@Override
public void run(ApplicationArguments arg0) throws Exception {
System.out.println("ApplicationRunnerBean 1");
}
}
------------------------------------------------------------------------
@Component
@Order(3)
public class CommandLineRunnerBean2 implements CommandLineRunner {
@Override
public void run(String... args) {
System.out.println("CommandLineRunnerBean 2");
}
}
------------------------------------------------------------------------
@Component
@Order(4)
public class ApplicationRunnerBean2 implements ApplicationRunner {
@Override
public void run(ApplicationArguments arg0) throws Exception {
System.out.println("ApplicationRunnerBean 2");
}
}
------------------------------------------------------------------------
输出结果:
CommandLineRunnerBean 1
ApplicationRunnerBean 1
CommandLineRunnerBean 2
ApplicationRunnerBean 2
复制代码
ok!文章到此就结束了,分享一些工作中可能会用到的一些Java小技巧,希望可以对大家有帮助,让大家少走一些弯路,有不对的地方希望大家可以提出来的,共同成长;
细节之中只有天地,整洁成就卓越代码