woe*_*ler 6 java spring-boot spring-shell
我偶然发现了这个问题,解释了如何在使用单个命令从命令行调用Spring Shell应用程序后退出.但是,使用Spring Boot在2.0.0中测试它,似乎不再是用命令参数调用JAR将执行该命令然后退出的情况.shell只是正常启动而不执行提供的命令.是否仍然可以这样做?如果没有,是否可以将参数从JAR执行传递给Spring Shell,然后在执行后触发退出?
例如,假设我有一个命令,import它有几个选项.它可以在shell中运行,如下所示:
$ java -jar my-app.jar
> import -f /path/to/file.txt --overwrite
Successfully imported 'file.txt'
> exit
Run Code Online (Sandbox Code Playgroud)
但是为了构建一个可以利用这个功能的脚本,能够简单地执行和退出会很好:
$ java -jar my-app.jar import -f /path/to/file.txt --overwrite
Successfully imported 'file.txt'
Run Code Online (Sandbox Code Playgroud)
我找到了一个不错的小解决方法。我没有创建一个ApplicationRunner模仿 v1 行为的类(这很棘手,因为它JLineInputProvider是一个私有类),而是创建了一个基于活动 Spring 配置文件的可选加载类。我使用 JCommander 定义 CLI 参数,使我能够为交互式 shell 和一次性执行使用相同的命令。运行不带参数的 Spring Boot JAR 会触发交互式 shell。使用参数运行它会触发一劳永逸的执行。
@Parameters
public class ImportParameters {
@Parameter(names = { "-f", "--file" }, required = true, description = "Data file")
private File file;
@Parameter(names = { "-t", "--type" }, required = true, description = "Data type")
private DataType dataType;
@Parameter(names = { "-o", "--overwrite" }, description = "Flag to overwrite file if it exists")
private Boolean overwrite = false;
/* getters and setters */
}
public class ImportCommandExecutor {
public void run(ImportParameters params) throws Exception {
// import logic goes here
}
}
/* Handles interactive shell command execution */
@ShellComponent
public class JLineInputExecutor {
// All command executors are injected here
@Autowired private ImportCommandExecutor importExecutor;
...
@ShellMethod(key = "import", value = "Imports the a file of a specified type.")
public String importCommand(@ShellOption(optOut = true) ImportParameters params) throws Exception {
importCommandExecutor.run(params);
}
...
}
/* Handles one-off command execution */
public class JCommanderInputExecutor implements ApplicationRunner {
// All command executors are injected here
@Autowired private ImportCommandExecutor importExecutor;
...
@Override
public void run(ApplicationArguments args) throws Exception {
// Create all of the JCommander argument handler objects
BaseParameters baseParameters = new BaseParameters();
ImportParameters importParameters = new ImportParameters();
...
JCommander jc = newBuilder().
.acceptUnknownOptions(true)
.addObject(baseParameters)
.addCommand("import", importParameters)
...
.build();
jc.parse(args);
String mainCommand = jc.getParsedCommand();
if ("import".equals(mainCommand)){
importExecutor.run(importParameters);
} else if (...) {
...
}
}
}
@Configuration
@Profile({"CLI"})
public class CommandLineInterfaceConfiguration {
// All of my command executors are defined as beans here, as well as other required configurations for both modes of execution
@Bean
public ImportCommandExecutor importExecutor (){
return new ImportCommandExecutor();
}
...
}
@Configuration
@Profile({"SINGLE_COMMAND"})
public class SingleCommandConfiguration {
@Bean
public JCommanderInputExecutor commandLineInputExecutor(){
return new JCommanderInputExecutor();
}
}
@SpringBootApplication
public class Application {
public static void main(String[] args) throws IOException {
String[] profiles = getActiveProfiles(args);
SpringApplicationBuilder builder = new SpringApplicationBuilder(Application.class);
builder.bannerMode((Mode.LOG));
builder.web(false);
builder.profiles(profiles);
System.out.println(String.format("Command line arguments: %s Profiles: %s",
Arrays.asList(args), Arrays.asList(profiles)));
builder.run(args);
}
private static String[] getActiveProfiles(String[] args){
return Arrays.asList(args).contains("-X") ? new String[]{"CLI", "SINGLE_COMMAND"} : new String[]{"CLI"};
}
}
Run Code Online (Sandbox Code Playgroud)
现在我只需运行可执行 JAR 即可触发交互式客户端:
java -jar app.jar
> import -f /path/to/file.txt -t GENE -o
> quit()
Run Code Online (Sandbox Code Playgroud)
或者,如果我在命令行上传递“-X”参数,应用程序将执行然后退出:
java -jar app.jar -X import -f /path/to/file.txt -t GENE -o
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5345 次 |
| 最近记录: |