Skip to content

springdocでAPIドキュメント作成

API設計書の作成方法について説明します。springdoc-openapiによってswaggerを自動生成するようにしています。

cf. https://springdoc.org/

実装

pom.xml

下記の依存関係を追加します:

        <!-- https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-starter-webmvc-ui -->
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
            <version>2.8.13</version>
        </dependency>

application.properties

下記設定を追記します:

# swagger出力用ymlファイルのエンドポイント
springdoc.api-docs.path=/api-docs
# swaggerドキュメント閲覧用エンドポイント
springdoc.swagger-ui.path=/swagger-ui.html
# application-swagger.ymlを読み込ませる
spring.profiles.active=swagger

EasyappApplication.java

APIの概要を記載します:

package nob.example.easyapp;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.info.Info;

@SpringBootApplication
@OpenAPIDefinition(info = @Info(title = "Easy App", version = "1.0.0", description = "サンプルのREST APIです。"))
public class EasyappApplication {

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

AuthController.java

各APIのインターフェース仕様を記載します:

package nob.example.easyapp.controller;

import org.springdoc.core.annotations.ParameterObject;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import nob.example.easyapp.controller.model.LoginRequest;
import nob.example.easyapp.controller.model.LoginResponse;
import nob.example.easyapp.controller.model.MeRequest;
import nob.example.easyapp.controller.model.MeResponse;
import nob.example.easyapp.handler.SampleExceptionHandler.SampleExceptionResponse;

/**
 * 認証コントローラーのインターフェースです。
 *
 * @author nob
 */
@RestController
@RequestMapping(value = "/api/v1")
@Tag(name = "Auth", description = "認証APIです。")
public interface AuthController {

    /**
     * 認証処理を呼び出します。
     *
     * @param request 認証リクエスト
     * @return 認証結果
     */
    @PostMapping(value = "/login")
    @Operation(summary = "認証", description = "${easyappdoc.describe.api.v1.login:説明文}")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "正常に処理された場合"),
            @ApiResponse(responseCode = "422", description = "エラーが発生した場合", content = @Content(schema = @Schema(implementation = SampleExceptionResponse.class)))
    })
    LoginResponse login(@RequestBody LoginRequest request);

    /**
     * ユーザ情報取得処理を呼び出します。
     *
     * @param request ユーザ情報取得リクエスト
     * @return ユーザ情報
     */
    @GetMapping(value = "/me")
    @Operation(summary = "ユーザ情報取得", description = "${easyappdoc.describe.api.v1.me:説明文}")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "正常に処理された場合")
    })
    MeResponse me(@ParameterObject MeRequest request); // GETリクエストのパラメータを表示するために@ParameterObjectを追加
}

model

各モデルクラスのスキーマ定義を記載します:

LoginRequest.java

package nob.example.easyapp.controller.model;

import io.swagger.v3.oas.annotations.media.Schema;

/**
 * 認証向けのリクエストモデルです。
 *
 * @param name     ユーザ名
 * @param password パスワード
 *
 * @author nob
 */
@Schema(description = "認証向けのリクエストモデル", type = "object")
public record LoginRequest(
        @Schema(description = "ユーザ名", type = "string", example = "nob") String name,
        @Schema(description = "パスワード", type = "string", example = "passwd") String password) {
}

LoginResponse.java

package nob.example.easyapp.controller.model;

import io.swagger.v3.oas.annotations.media.Schema;

/**
 * 認証向けのレスポンスモデルです。
 *
 * @param valid 認証可否
 *
 * @author nob
 */
@Schema(description = "認証向けのレスポンスモデル", type = "object")
public record LoginResponse(
        @Schema(description = "認証可否", type = "boolean", example = "true") Boolean valid) {
}

MeRequest.java

package nob.example.easyapp.controller.model;

import io.swagger.v3.oas.annotations.media.Schema;

/**
 * ユーザ情報取得向けのリクエストモデルです。
 *
 * @param name ユーザ名
 *
 * @author nob
 */
@Schema(description = "ユーザ情報取得向けのリクエストモデル", type = "object")
public record MeRequest(
        @Schema(description = "ユーザ名", type = "string", example = "nob") String name) {
}

MeResponse.java

package nob.example.easyapp.controller.model;

import io.swagger.v3.oas.annotations.media.Schema;

/**
 * ユーザ情報取得向けのレスポンスモデルです。
 *
 * @param name ユーザ名
 * @param age  年齢
 *
 * @author nob
 */
@Schema(description = "ユーザ情報取得向けのレスポンスモデル", type = "object")
public record MeResponse(
        @Schema(description = "ユーザ名", type = "string", example = "nob") String name,
        @Schema(description = "年齢", type = "integer", example = "13") Integer age) {
}

SampleExceptionHandler.java

例外発生時レスポンスモデルのスキーマ定義を記載します:

package nob.example.easyapp.handler;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import io.swagger.v3.oas.annotations.media.Schema;
import nob.example.easyapp.exception.SampleException;

/**
 * サンプル例外のハンドラです。
 *
 * @author nob
 */
@RestControllerAdvice
public class SampleExceptionHandler {

    /**
     * サンプル例外が投げられた際のハンドリングを行います。
     *
     * @param e
     * @return 例外メッセージ
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    @ExceptionHandler(SampleException.class) // SampleExceptionが投げられた際に動く
    public ResponseEntity<SampleExceptionResponse> handleSampleException(SampleException e) {

        return new ResponseEntity(new SampleExceptionResponse(e.getMessage()), HttpStatus.UNPROCESSABLE_CONTENT);
    }

    /**
     * サンプル例外発生時のレスポンスボディです。
     *
     * @param message エラーメッセージ
     */
    @Schema(description = "サンプルエラーのレスポンス", type = "object")
    public record SampleExceptionResponse(
            @Schema(description = "エラーメッセージ", type = "string", example = "業務エラーが発生しました。") String message) {
    }
}

resources/application-swagger.yaml

APIのdescriptionについて記載します:

#====================
# Easy App documents
#====================
easyappdoc:
  describe:
    api:
      v1:
        login: |
          認証処理を行います。リクエストに不備があった場合はエラーレスポンスを返します。
        me: |
          ユーザ情報を取得します。

動作確認

アプリ起動後、http://localhost:8080/swagger-ui/index.html でswaggerドキュメントを確認できます。

Tips

Try it outボタンを無効化したい場合

application.propertiesに下記を追加すればボタンが非表示になります:

springdoc.swagger-ui.supported-submit-methods=[]