使用Spring Boot的CommandLineRunner接口可以在应用程序启动时运行一些代码。但是在使用CommandLineRunner时,可能会遇到一些坑,下面是攻略及相应示例:
坑点及解决方案
1. CommandLineRunner执行顺序问题
在项目中可能会有多个CommandLineRunner实现类,SpringBoot在执行CommandLineRunner的时候并没有给出特定的执行顺序,所以需要开发者来指定使用@Order注解进行指定执行顺序。如下所示:
@Component
@Order(1)
public class CommandLineRunner1 implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("CommandLineRunner1");
}
}
@Component
@Order(2)
public class CommandLineRunner2 implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("CommandLineRunner2");
}
}
2. CommandLineRunner无法被单元测试覆盖到问题
由于CommandLineRunner是Spring容器启动之后执行的代码,而在单元测试中,启动Spring容器是无法将CommandLineRunner的代码也由JUnit所控制。对于这种情况,可以使用Spring-boot-starter-test提供的“TestResttemplate”来模拟外部调用,从而触发CommandLineRunner的执行流程。
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class CommandLineRunnerTests {
@Autowired
private TestRestTemplate restTemplate;
@Test
public void testCommandLineRunner() {
// 模拟外部调用
ResponseEntity<String> response = restTemplate.getForEntity("/", String.class);
assertThat(response.getStatusCode().value()).isEqualTo(200);
}
}
示例
接下来我们用示例来演示如何使用CommandLineRunner,以及如何应对上述两个坑点。
示例1
- 创建CommandLineRunner1
@Component
@Order(1)
public class CommandLineRunner1 implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("CommandLineRunner1");
}
}
- 创建CommandLineRunner2
@Component
@Order(2)
public class CommandLineRunner2 implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("CommandLineRunner2");
}
}
- 启动测试
启动Spring Boot应用程序并观察控制台输出,你会看到输出的顺序为:
CommandLineRunner1
CommandLineRunner2
- 结论
通过添加@Order(1)和@Order(2)注释,可以按照指定的顺序运行CommandLineRunner。
示例2
- 创建CommandLineRunner类
@Component
public class CommandLineRunnerImpl implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("CommandLineRunner execute success.");
}
}
- 创建测试类
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class CommandLineRunnerTests {
@Autowired
private TestRestTemplate restTemplate;
@Test
public void test() {
ResponseEntity<String> response = restTemplate.getForEntity("/", String.class);
assertThat(response.getStatusCode().value()).isEqualTo(200);
}
}
- 控制器设置
@RestController
public class IndexController {
@GetMapping("/")
public String index() {
return "Hello, world!";
}
}
- 启动测试
启动JUnit测试并观察控制台输出,你可以看到运行"CommandLineRunner execute success."的信息,并且可以进行正常的HTTP调用!
总结
在使用Spring Boot的CommandLineRunner时,要注意以上两个坑。使用@Order注解可以解决多个CommandLineRunner类的执行顺序问题, TestRestTemplate类可以模拟外部调用来触发CommandLineRunner接口的执行流程。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:使用SpringBoot的CommandLineRunner遇到的坑及解决 - Python技术站