SpringfoxでSwaggerAPI仕様書を自動生成する(環境設定編)

2017.12.22

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは。しがないOLのくにきちです。
あっという間に年末ですね。今回もクラスメソッドはお休み開始が早いので、今日で仕事納めです。
私はTwitterなどのアイコンを自作しているのですが、最近新作を描けてなかったので休み中に新しいアイコン描きたいなぁ、と思ってます。

そんなところで早速本題。 今回は「Springfox」というツールを使って、ソースコードから簡単に Web API仕様書を作成する方法を書いていきたいと思います。「環境設定編」と「仕様書カスタマイズ編」の全2回くらいで考えています。

まずは、今回のブログに出てくる Swagger と Springfox について簡単に説明。

Swagger とは

Swagger は、REST API を定義するためのオープンフレームワークです。
仕様を記述するためのルールを定め、Swagger Editor や Swagger UI など、設計や構築、ドキュメントの生成、テスト、デプロイなどを可能にするための関連ツールを提供しています。

Springfox とは

Swagger をベースに、Springで構築された API から Web API 仕様書を自動生成するためのツールです。アノテーションを用いてSwagger準拠のJSONを自動生成し、生成されたJSONからWebAPI仕様書を生成します。

本ブログの構成

  • 前提
  • ライブラリを追加する
  • SwaggerConfigurationクラスを作成する
  • SwaggerUIでAPI仕様書を表示する
  • まとめ
  • おわりに

前提

  • Springfoxのバージョン : 2.0.7
  • Springfoxの Swagger UI のバージョン : 2.2.10 (現在のSwagger UI バージョンは 3系なのでちょっと古い)

ライブラリを追加する

まずは、必要なライブラリを追加していきます。

build.gradle

compile 'io.swagger:swagger-annotations:1.5.16'
compile "io.springfox:springfox-swagger2:$springfoxVersion"
compile "io.springfox:springfox-swagger-ui:$springfoxVersion"

追加したライブラリは、以下のような役割があります。

swagger-annotations

Swaggerドキュメントをカスタマイズするためのアノテーションを定義しているライブラリです。

ソースコードにSwaggerアノテーションを付与して、API に関する説明を追加するなどSwaggerドキュメントをカスタマイズできます。次回の「仕様書カスタマイズ編」で大活躍します。

springfox-swagger2

Swaggerの設定を有効化し、Swagger準拠のJSONを生成します。

@EnableSwagger2 を SwaggerConfigurationクラス(後述)に付与することで必要なBeanをロードし、Swaggerのサポートを有効にします。 bootRun でアプリケーションを起動後、 http://localhost:8080/v2/api-docs にアクセスすると生成されたJSONを確認できます。

このライブラリは、以下のコンポーネントで構成されています。

  • springfox-spi : 使用可能な拡張プラグインなどを使用できるようにします。
  • springfox-schema : パラメータ、モデル、レスポンスのスキーマを構築します。
  • springfox-swagger-common : Swaggerアノテーションを認識するための拡張機能。
  • springfox-spring-web : RequestMapping情報に基づいてサービスモデルを構築します。
  • springfox-core : 内部サービス、スキーマ記述モデル、ビルダーを保有し、JSONを生成します。

springfox-swagger-ui

springfox-swagger2 により生成された JSON から Web API 仕様書を生成します。

bootRun でアプリケーションを起動後、http://localhost:8080/swagger-ui.html で生成した Web API 仕様書を確認できます。

API仕様書生成イメージ

SwaggerConfigurationクラスを作成する

Swaggerドキュメントを定義するクラスとして SwaggerConfiguration.java を作成します。このクラスでは、サービスを文書化するための Docket インスタンスを生成し、Docket が持つメソッドを用いてSwaggerドキュメントを定義します。

Docket の定義

Docketは多くのメソッドを用意しています。今回はその一部をご紹介します。

メソッド 説明
apiInfo ApiInfoBuilderでAPIのメタ情報を設定します。ApiInfoBuilderでは以下の設定ができます。
title : APIタイトル
description : APIの説明
termsOfServiceUrl : サービス利用規約URL
contact : APIに関する連絡先(name, url, e-mail)
license : APIのライセンス情報
licenseUrl : APIのライセンスURL
version : APIのバージョン情報
extensions : APIの拡張機能を追加する
securitySchemes APIでサポートされているセキュリティスキーム(認証タイプ)を設定します。Swagger 2.0では、APIに対して次の3つの認証タイプをサポートしています。
・Basic Authentication(基本認証)
・APIキー
・OAuth2
select ApiSelectorBuilderを生成します。ApiSelectorBuilderは以下の設定ができます。
apis : API仕様書の対象とするRequestHandlerを設定します。
paths : API仕様書の対象とするパスを設定します。
build : ApiSelectorの構築を完了します。
enableUrlTemplating パスにURLテンプレートを使用するかどうかを指定します。
genericModelSubstitutes 汎用クラスをパラメータ化された型に置き換えます。例えば、optionalの @RequestParam は、デフォルト設定だとドキュメントに表示されませんが、このメソッドの引数に Optional.class を指定することでドキュメントに表示されます。
useDefaultResponseMessages デフォルトのレスポンスを使用するかどうかを指定します。
globalResponseMessage HTTPメソッド毎に共通のレスポンスを設定できます。API固有のレスポンスはControllerクラスで設定します。
レスポンスメッセージだけでなく、レスポンスのモデルを表示したい場合は、表示したいモデル定義クラスに Swaggerアノテーションの @ApiModel を付加し、reference名を設定します。SwaggerConfigurationクラスでは、new ModelRef() の部分でモデル定義クラスに設定したリファレンス名を指定することでモデルを表示することができます。

SwaggerConfigurationの例

@EnableSwagger2
@Configuration
public class SwaggerConfiguration {

    @Bean
    public Docket restApi() {
        return new Docket(DocumentationType.SWAGGER_2)
            .produces(newHashSet("application/json"))
            .apiInfo(apiInfo()) // (1)
            .select()
            .paths(paths()) // (2)
            .build()
            .securitySchemes(securityScheme()) // (3)
            .enableUrlTemplating(false)
            .genericModelSubstitutes(Optional.class)
            .useDefaultResponseMessages(false)
            // メソッド毎の共通エラーレスポンスを定義
            .globalResponseMessage(RequestMethod.GET, getErrorResponses()); // (4)
            // 複数ある場合は、.globalResponseMessage()を追加する。
    }

    // (1)APIの基本情報を定義
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("APIタイトルを表示する") 
                .description("APIの説明を表示する") 
                .termsOfServiceUrl("利用規約URLを表示する")
                .contact(new Contact("名前", "https://example.com", "test@example.jp"))
                .license("APIのライセンス情報")
                .licenseUrl("APIのライセンスURL")
                .version("APIのバージョン") 
                .build();
    }

    // (2)対象とするRequestHandlerを定義
    private Predicate<String> paths() {
        return ant("/members/**");
        // 複数ある場合は、return or(ant("/foo/**"), ant("/bar/**")) のように記述する。
    }

    // (3) securitySchemesを定義
    private List<SecurityScheme> securityScheme() {
        return newArrayList(
                new OAuth(
                    "members_auth", 
                    asList(
                        new AuthorizationScope("write_members", "modify members in your account"),
                        new AuthorizationScope("read_members", "read your members")),
                    Arrays.<GrantType> asList(new ImplicitGrant(
                        new LoginEndpoint("http://members.swagger.io/api/oauth/dialog"), "tokenName"))),
                new ApiKey("api_key", "api_key", "header"));
    }

    // (4)-1 GETメソッドの共通エラーレスポンスを定義
    private List<ResponseMessage> getErrorResponses() {
        return newArrayList(
                createErrorResponseMessage(403, "ユーザまたはクライアントに、その操作をする権限が足りない。"),
                createErrorResponseMessage(404, "指定したリソースが見つからない。")
        );
    }

    // (4)-2 ResponseMessageを生成するためのメソッド
    private ResponseMessage createErrorResponseMessage(int code, String message) {
        return new ResponseMessageBuilder()
            .code(code)
            .message(message)
            .responseModel(new ModelRef("ErrorResponse"))
            .build();
    }
}
  • restApi を見やすくするために apiInfo などの詳細な定義を切り出しましたが、細かい設定をしないなら restApi でまとめてもよいです。
  • genericModelSubstitutes は、繰り返し同じ処理を書くことになるのでResponseMessage生成部分を createErrorResponseMessage としてメソッドを切り出しています。
  • ResponseMessageBuilderresponseModel を設定する場合は、表示したいモデル定義クラスにリファレンス名を設定しておく必要があります。

共通部分の設定は、これで終了になります。

SwaggerUIでAPI仕様書を表示する

API仕様書生成用に簡単なAPIを作成し、ブラウザからAPI仕様書を確認します。

bootRun でアプリケーションを起動します。起動後、http://localhost:8080/swagger-ui.html にアクセスすると、以下のようなAPI仕様書が表示されます。

まとめ

今回は環境設定編として、ライブラリの追加と、仕様書を生成するためのDocketを定義し、ブラウザからAPI仕様書を確認しました。お分かりの通り、共通部分を設定しただけなので、仕様書としてはもうちょっと説明を加えるなどカスタマイズしたいところです。
ということで、次回はモデルやコントローラーにアノテーションを付加して細かい設定をしていきたいと思います。

おわりに

今年も一年ありがとうございました。私の拙いブログを見てくださったことに感謝です。
今年は事務職からエンジニアにジョブチェンジするという、なかなか濃い一年でした。これからも引き続き頑張っていきます。
そのうち、ジョブチェンジしたときに戸惑ったことや気付いたことなどをまとめたブログを書きたいなと思ってます。(ポエムカテゴリーで)
また来年も宜しくお願いしますm(_ _)m
by くにきち