2017-09-22 11 views
0

나는 하나의 명령으로 명령 행에서 호출 한 후 Spring Shell 애플리케이션을 종료하는 방법을 설명하면서 잠시 후 this question을 우연히 발견했다. 그러나 스프링 부트 2.0.0에서이를 테스트하면 더 이상 JAR을 명령 인수로 호출하면 해당 명령이 실행 된 다음 종료됩니다. 쉘은 제공된 명령을 실행하지 않고 정상적으로 시작합니다. 이것을 할 수 있습니까? 그렇지 않다면 JAR 실행에서 Spring Shell로 인수를 전달한 다음 실행 후 종료를 트리거 할 수 있습니까?하나의 명령을 실행하여 Spring Shell 2를 빠져 나온다.

예를 들어, 몇 가지 옵션이있는 import 명령이 있다고 가정 해 봅니다.

$ java -jar my-app.jar 

> import -f /path/to/file.txt --overwrite 
Successfully imported 'file.txt' 

> exit 

그러나 단순히이 기능을 활용할 수있는 스크립트를 구축을 위해, 실행 및 종료 할 수있는 것이 좋을 것이다 : 그것은 다음과 같이 쉘에서 실행 할 수

$ java -jar my-app.jar import -f /path/to/file.txt --overwrite 
Successfully imported 'file.txt' 

답변

0

정확한 질문 (및 제안 된 솔루션)에 대해서는 this issue을 참조하십시오.

+0

합니다. 내가 좋은 것을 생각해 내면 여기서 나의 해결책을 게시 할 것이다. 감사. – woemler

0

멋진 해결책을 찾았습니다. JLineInputProvider은 개인 클래스이므로 v1 동작을 모방 한 ApplicationRunner을 만드는 대신 활성 스프링 프로필을 기반으로 선택적으로로드되는 템플릿을 만들었습니다. JCommander를 사용하여 CLI 매개 변수를 정의 했으므로 대화 형 셸과 일회용 실행에 대해 동일한 명령을 사용할 수 있습니다. args가없는 Spring Boot JAR을 실행하면 대화식 쉘이 트리거됩니다. 인수로 실행하면 일회성 실행이 트리거됩니다. 내가 명령 줄에 인수를 전달하는 경우

java -jar app.jar 
> import -f /path/to/file.txt -t GENE -o 
> quit() 

가 아니면, 그들이 실행하고 다음 종료 :

public class JCommanderImportCommands { 

    public static enum DataType { SAMPLE, GENE, DATA } 

    @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 */ 
} 

@ShellComponent 
public class ImportCommands { 

    @ShellMethod(key = "import", value = "Imports the a file of a specified type.") 
    public String jCommanderFileImport(@ShellOption(optOut = true) JCommanderImportCommands commands){ 
    System.out.println(String.format("Importing file=%s dataType=%s overwrite=%s", 
     commands.getFile(), commands.getDataType(), commands.getOverwrite())); 
    return commands.getFile().getAbsolutePath(); 
    } 

} 

public class JCommanderShellRunner implements ApplicationRunner { 

    @Override 
    public void run(ApplicationArguments args) throws Exception { 
    JCommanderImportCommands importCommands = new JCommanderImportCommands(); 
    JCommander.newBuilder() 
     .addCommand("import", importCommands) 
     .acceptUnknownOptions(true) 
     .build() 
     .parse(args.getSourceArgs()); 
    System.out.println(String.format("Importing file=%s dataType=%s overwrite=%s", 
     importCommands.getFile(), importCommands.getDataType(), importCommands.getOverwrite())); 
    } 
} 

@Configuration 
@Profile({"jc"}) 
public class ShellConfig { 

    @Bean 
    public JCommanderShellRunner shellRunner(){ 
    return new JCommanderShellRunner(); 
    } 

} 

@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 args.length > 0 ? new String[]{"jc"} : new String[]{}; 
    } 

} 

그래서 지금은 단순히 내 실행 JAR를 실행하여 대화 형 클라이언트를 실행할 수 있습니다

java -jar app.jar import -f /path/to/file.txt -t GENE -o 
0

추가하기 만하면 다른 방법으로 대화 형 모드에서 실행할 수 있지만 위의 프로필을 사용하면 구성을 바꿀 수 있습니다. 내가 롬복과 jool을 사용하고 있습니다

항목

@SpringBootApplication 
public class Righter { 

    public static void main(String[] args) { 
     SpringApplication.run(Righter.class, args); 
    } 

    @Bean 
    public ApplicationRunner shellRunner(Shell shell) { 
     return new NonInteractiveShellRunner(shell); 
    } 

응용 프로그램 러너 (단지의 경우 누군가에 페이스트를 복사하고 재미있는 문제를 가져옵니다!) : 날이었다

@Order(0) 
public class NonInteractiveShellRunner implements ApplicationRunner{ 

    private final Shell shell; 

    public NonInteractiveShellRunner(Shell shell) { 
     this.shell = shell; 
    } 

    @Override 
    public void run(ApplicationArguments args) throws Exception { 
     shell.run(new CommandInputProvider(args.getSourceArgs())); 
    } 

    public static class PredefinedInputProvider implements InputProvider{ 

     private final Input input; 
     private boolean commandExecuted = false; 

     public PredefinedInputProvider(String[] args) { 
      this.input = new PredefinedInput(args); 
     } 

     @Override 
     public Input readInput() { 
      if (!commandExecuted){ 
       commandExecuted=true; 
       return input; 
      } 
      return new PredefinedInput(new String[]{"exit"}); 
     } 

     @AllArgsConstructor 
     private static class PredefinedInput implements Input{ 

      private final String[] args; 

      @Override 
      public String rawText() { 
       return Seq.of(args).toString(" "); 
      } 

      @Override 
      public List<String> words(){ 
       return Arrays.asList(args); 
      } 
     } 

    } 

}