Usual Software Engineer

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

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

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一個になるので楽かも

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