読者です 読者をやめる 読者になる 読者になる

Usual Software Engineer

よくあるソフトウェアエンジニアのブログ

Spring BootでWebじゃないコマンドラインアプリケーションを作る

Java Spring Spring Boot コマンドライン

JavaMVCなWebアプリケーションを作成する時にSpringはとても便利で定番かと思います。
中でもSpring Bootは従来のwarにかためてサーブレットコンテナのTomcatやJetty上で動かすだけでなく、
それだけで動作可能なjarを作ることも可能なため、近年よく使われている気がします。
今回はそんなSpring Bootを使いつつ、でもWebじゃないコマンドラインアプリケーションを作る方法を紹介します。

小さなサンプルのリポジトリはこちらです。

github.com

まずは build.gradle に使用するパッケージのdependencyを定義してあげてください。
Spring Boot用のgradle pluginも使用できるように定義しておくと良いと思います。

apply plugin: 'org.springframework.boot'
...
dependencies {
    ...
    compile 'org.springframework.boot:spring-boot-starter'

Spring Bootのアプリケーションを作るには、mainメソッドで SpringApplication を生成します。
そして @SpringBootApplication というアノテーションを付けるだけでほぼ完了です。
@ComponentScan@EnableAutoConfiguration の機能を備えているのでそれだけで大丈夫なのです。

spring-boot-example-nonweb/NonWebSpringBootApplication.java at 2bda7632ad25d0963e87dc33175c28bb080dd661 · innossh/spring-boot-example-nonweb · GitHub

@SpringBootApplication
public class NonWebSpringBootApplication {

    public static void main(String[] args) {
        new SpringApplicationBuilder(NonWebSpringBootApplication.class).web(false).run(args);
    }

}

続いてWebじゃないコマンドラインアプリケーションなので、処理の入り口を作ってあげます。
下記のように新しいクラスとして定義しても良いですし、 CommandLineRunner のBeanだけ作ってあげても大丈夫です。
runメソッド内に処理を記述しましょう。

spring-boot-example-nonweb/NonWebCommandLineRunner.java at 2bda7632ad25d0963e87dc33175c28bb080dd661 · innossh/spring-boot-example-nonweb · GitHub

@Component
@Slf4j
public class NonWebCommandLineRunner implements CommandLineRunner {

    @Override
    public void run(String... args) throws Exception {
        boolean verbose = appArgs.containsOption("verbose");
        appArgs.getNonOptionArgs().stream().forEachOrdered((s -> {
            boolean isValid = jsonValidator.validate(s, verbose);
            log.info(isValid ? "It's a JSON object!" : "It's not a JSON object.");
        }));
    }

}

では早速実行してみます。今回のサンプルでは適当に入力値がJSONかどうか判定するものにしました。

$ ./gradlew build
$ ./build/libs/spring-boot-example-nonweb.jar --verbose "{\"hoge\":\"fuga\"}"

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v1.5.2.RELEASE)

...
[main] INFO innossh.springboot.example.notweb.JsonValidator - {"hoge":"fuga"}
[main] INFO innossh.springboot.example.notweb.NonWebCommandLineRunner - It's a JSON object!
...

$ ./build/libs/spring-boot-example-nonweb.jar --verbose "invalid"
...
[main] INFO innossh.springboot.example.notweb.JsonValidator - Unrecognized token 'invalid': was expecting ('true', 'false' or 'null')
 at [Source: invalid; line: 1, column: 15]
[main] INFO innossh.springboot.example.notweb.NonWebCommandLineRunner - It's not a JSON object.
...

Spring Bootを使用していると最初の起動が少し時間がかかりますが、問題なくコマンドラインアプリケーションが実行できていますね。

Webじゃないコマンドラインアプリケーションを作るのにSpring Bootを使う理由としては

  • DIとかのためにどうせSpring使うならSpring Bootでもいいか
  • gradle plugin使って自前でfat jar作るのもいいけれどSpring Bootの方が無駄な設定とかなくてjar一個になるので楽かも

などでしょうか。
気が向いたら使ってみてください。