Spring BootにSwaggerを導入する

0. 初めに

仕事でSwaggerを利用することになりました。Swaggerの利用方法・アプローチは複数ある*1ようですが、今回はJava(Spring)のコードからDocumentを生成するアプローチを取ります。

Swaggerそのものの説明は殆ど書いてないです。

1. 各種バージョン情報について

Java

# Java
$ java --version
java 17.0.3.1 2022-04-22 LTS
Java(TM) SE Runtime Environment (build 17.0.3.1+2-LTS-6)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.3.1+2-LTS-6, mixed mode, sharing)

Spring、SpringFox(SpringのSwagger用ライブラリ)

Springは2.6.7

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.7</version>
        <relativePath/> <!-- lookup parent from repository -->
</parent>

~~ 中略 ~~

<dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-boot-starter</artifactId>
            <version>3.0.0</version>
</dependency>

その他

# mac
❯ sysctl -a machdep.cpu
machdep.cpu.cores_per_package: 10
machdep.cpu.core_count: 10
machdep.cpu.logical_per_package: 10
machdep.cpu.thread_count: 10
machdep.cpu.brand_string: Apple M1 Max

# IntelliJ IDEA Community Edition
version: 2021.3.3

2. SpringFoxとは

SwaggerをSpringで利用する際に必要となるライブラリです。2022年7月現在、最新のバージョンは3.0.0です。

リリースの情報を読んでる限り、2系との特に大きな差分としてはWebfluxが使えることのようです。spring boot 2.6系との噛み合わせがまだ悪いみたいな話もあるようですが、以下のように@EnableWebMVCアノテーションをエントリーポイントに追加するだけでとりあえず動きました。

@EnableWebMvc
@SpringBootApplication
public class DemoApplication {

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

}

以下、原文をそのまんま引用しておきます。(参考

  • Highlights of this release include
    • Spring 5, Webflux support (only request mapping support, functional endpoints aren't supported yet)
    • Spring Integration support (feedback is much appreciated)
    • Spring Boot support springfox-boot-starter dependency (Zero Config, Autoconfiguration support)
    • Documented Configuration Properties with autocomplete
    • Better specification compatibility with 2.0
    • Support for OpenApi 3.0.3
    • Zero Dependency (almost, the only libraries needed are spring-plugin, pswagger-core](https://github.com/swagger-api/swagger-core)
    • Existing swagger2 annotations will continue to work and enrich open api 3.0 specification

3. 設定ファイルを記述する

適当な階層にconfigファイルを記述します。自分はentry pointと同じ階層に記述しました。

package com. example.demo;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

@Configuration
public class SwaggerConfig {

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo());
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                // タイトル
                .title("文書分類API")
                // 詳細な説明
                .description("文書を登録すると、文書の分類を行なってくれるAPIです")
                // バージョン
                .version("1.0.0")
                // 連絡先
                .contact(new Contact("takerumimata", "https://mimatasanmata.hatenablog.com", "takerumimata@example.com"))
                // ライセンス名
                .license("Apache 2.0")
                // ライセンスURL
                .licenseUrl("https://www.apache.org/licenses/LICENSE-2.0")
                // 利用規約のURL
                .termsOfServiceUrl("http://example.com/termsofuse")
                .build();
    }
}

DocketというBeanを登録しています。Docketという単語を初めて目にしたので意味を調べてみたところ、明細、などの意味があるようです。(参考)かなり硬い言葉のよう?

Docketと別に、ApiInfoという型を返すクラスを用意しています。こちらはSwagger-UIでAPIのDocumentを表示する際に、そのAPIのタイトルや概略を表示する際に利用する情報を記述することができるようです。

3.1 API Documentを確認する

mvnコマンドやIntellijなどを利用してSpringアプリケーションを走らせてください。起動したらhttp://localhost:8080/swagger-ui/ へアクセス。以下のように、Controllerを勝手に解析してDocumentを吐き出してくれます。

swagger-ui

v2/api-docsへアクセスすると、Swagger Spec(Json)を取得することもできます。

3.2 表示するAPIを絞る

表示するAPIを限定する手法について説明します。ここでは例としてbasic-error-controllerを表示対象から外すことにしました。basic-error-controllerはSpringがデフォルトで用意しているエラーコントローラですが、Documentとして表示する必要はないので見えないようにします。

SwaggerConfigを以下のように編集。

@Bean
public Docket api() {
    return new Docket(DocumentationType.SWAGGER_2)
      .select()
    // パッケージ指定によって表示するAPIを絞り込む場合。例えばControllerだけ表示したい場合は以下
    .apis(RequestHandlerSelectors.basePackage("com.example.demo.controller"))
    .paths(PathSelectors.any())
    // パス指定で絞り込む場合
    //.paths(PathSelectors.ant("/todos/**"))
    .build()
    .apiInfo(apiInfo());
}

コメントに書いてある通りですが、package、またはpathで絞り込みが行えます。

表示するAPIを制限する

4. アノテーションを記述する:Documentのカスタマイズ

この時点で既にDocumentの大枠は自動生成されています。次に、生成されたDocumentをカスタマイズする方法について述べます。

細かい設定はやり出すと止まらないので、少しだけ例を挙げます。まずは下記コードをご覧ください。Todoアプリっぽい感じで、todoを追加するPost系のAPIと、一覧を取得するGet系のAPIです。型とかは適当なので一覧といいつつString型で値を返す感じになってますが、細けぇことは気にしないでください。

       // SampleController.java
        @GetMapping(path = "/todos", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "TODOの一覧を取得します", notes = "idを指定して絞り込みもできます")
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "正常系"),
            @ApiResponse(code = 404, message = "not found")
    })
    public String todoList() {
        return "Todos...";
    }

    @PostMapping(path = "/todo", produces = MediaType.APPLICATION_JSON_VALUE)
    @ApiOperation(value = "TODOを追加", notes = "hoge")
    public void todoAdd(@RequestBody String todo) {
        // do something
    }

@ApiResponses@ApiResponseなどをメソッドにアノテーションとして付与し、parameterを渡していくと、自動生成されるものではなく、自分で設定したパラメータでDocumentを生成してくれます。

めんどくさかったので記述してませんが、Example Valueなども@Contentで設定できるようです。

アノテーションの一覧はGithub Wikiにまとまっています。

Swagger 2.X Annotations · swagger-api/swagger-core Wiki

5. まとめ

SpringFoxを利用してSpring Bootで作成したAPIのDocumentを生成する方法についてざっとみてみました。Swagger Specを記述してからSpringのコードをGenerateするアプローチを取ることも今後あるかと思うので、どこかで勉強しておきたいですね。

6. Reference

GitHub - springfox/springfox: Automated JSON API documentation for API's built with Spring

Spring Boot + SpringFoxでSwaggerを利用してソースからAPIキュメントを生成する - Qiita

Spring Bootで作成したWEB APIにSwaggerを導入して簡単ドキュメント管理

*1:SwaggerにはTop Downなアプローチ / Bottom Upなアプローチがあります。