基于命令行参数的多个Spring Boot CommandLineRunner

Sha*_*hay 5 java spring-boot spring-cloud-task

我已经创建了带有春季云任务的春季启动应用程序,该任务应该执行一些命令(任务)。每个任务/命令都是短期任务,所有任务都从命令行开始,执行一些简短的ETL作业并完成执行。

有一个包含所有命令/任务的spring boot jar。每个任务都是CommandLineRunner,我想根据命令行中的参数来决定执行哪些任务(一个或多个)。最佳做法是什么?我不喜欢有肮脏的代码问“如果不是”或类似的东西。

use*_*566 8

你也可以让你的 CommandLineRunner 实现 @Component 和 @ConditionalOnExpression("${someproperty:false}")

然后有多个配置文件,将 someproperty 设置为 true 以将那些 CommandLineRunners 包含在上下文中。

@Component
@Slf4j
@ConditionalOnExpression("${myRunnerEnabled:false}")
public class MyRunner implements CommandLineRunner {
    @Override
    public void run(String ... args) throws Exception {
        log.info("this ran");
    }
}
Run Code Online (Sandbox Code Playgroud)

并在 yml application-myrunner.yml

myRunnerEnabled: true
Run Code Online (Sandbox Code Playgroud)
myRunnerEnabled: true
Run Code Online (Sandbox Code Playgroud)


P.J*_*sch 6

Spring Boot 运行应用程序上下文中的所有CommandLineRunnerApplicationRunnerbean。您不能通过任何参数选择一个。

所以基本上你有两种可能性:

  1. 你有不同的CommandLineRunner实现,在每个实现中你检查参数以确定是否CommandLineRunner应该运行这个特殊的。
  2. 您只实现了一个CommandLineRunner充当调度员的角色。代码可能如下所示:

这是您的跑步者将实现的新接口:

public interface MyCommandLineRunner {
    void run(String... strings) throws Exception;
}
Run Code Online (Sandbox Code Playgroud)

然后定义实现并用名称标识它们:

@Component("one")
public class MyCommandLineRunnerOne implements MyCommandLineRunner {
    private static final Logger log = LoggerFactory.getLogger(MyCommandLineRunnerOne.class);

    @Override
    public void run(String... strings) throws Exception {
        log.info("running");
    }
}
Run Code Online (Sandbox Code Playgroud)

@Component("two")
public class MyCommandLineRunnerTwo implements MyCommandLineRunner {
    private static final Logger log = LoggerFactory.getLogger(MyCommandLineRunnerTwo.class);
    @Override
    public void run(String... strings) throws Exception {
        log.info("running");
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在您的单个CommandLineRunner实现中,您获得应用程序上下文并按名称解析所需的 bean,我的示例仅使用第一个参数,并调用它的MyCommandLineRunner.run()方法:

@Component
public class CommandLineRunnerImpl implements CommandLineRunner, ApplicationContextAware {
    private ApplicationContext applicationContext;


    @Override
    public void run(String... strings) throws Exception {
        if (strings.length < 1) {
            throw new IllegalArgumentException("no args given");
        }

        String name = strings[0];
        final MyCommandLineRunner myCommandLineRunner = applicationContext.getBean(name, MyCommandLineRunner.class);
        myCommandLineRunner.run(strings);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这两种方法都不太合理......只是转到 3 层高的 switch 语句,......我不想这么说,但它保持得更好。依赖注入,当然是 100%,一旦你超越了那个...... (3认同)