1. 概要

ドキュメントは、RESTAPIを構築する上で不可欠な部分です。 このチュートリアルでは、SpringDocを見ていきます。SpringDocは、Spring Boot1.xおよび2.xアプリケーションのOpenAPI3仕様に基づいてAPIドキュメントの生成と保守を簡素化するツールです。

2. springdoc-openapiの設定

springdoc-openapiがAPIのOpenAPI3仕様ドキュメントを自動的に生成するには、springdoc-openapi-ui依存関係をpom.xmlに追加するだけです。

<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-ui</artifactId>
    <version>1.6.4</version>
</dependency>

次に、アプリケーションを実行すると、OpenAPIの説明がデフォルトでパス / v3 /api-docsで利用可能になります。

http://localhost:8080/v3/api-docs/

カスタムパスを使用するには、application.propertiesファイルで次のように指定できます。

springdoc.api-docs.path=/api-docs

これで、次の場所にあるドキュメントにアクセスできるようになります。

http://localhost:8080/api-docs/

OpenAPI定義は、デフォルトでJSON形式です。 yaml 形式の場合、次の場所で定義を取得できます。

http://localhost:8080/api-docs.yaml

3. SwaggerUIを使用したspringdoc-openapiのセットアップ

OpenAPI 3仕様自体を生成するだけでなく、springdoc-openapiをSwagger UIと統合して、API仕様と対話し、エンドポイントを実行できるようにすることができます。

3.1. Mavenの依存関係

Swagger UIを使用してspringdoc-openapiを設定するために必要なのは、依存関係springdoc-openapi-uiをプロジェクトのpom.xmlに追加することだけです。

<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-ui</artifactId>
    <version>1.6.4</version>
</dependency>

これで、次の場所でAPIドキュメントにアクセスできます。

http://localhost:8080/swagger-ui.html

3.2. swagger-uiプロパティのサポート

Springdoc-openapiは、swagger-uiプロパティもサポートしています。 これらは、プレフィックスspringdoc.swagger-uiを付けてSpringBootプロパティとして使用できます。

たとえば、APIドキュメントのパスをカスタマイズしましょう。 これを行うには、application.propertiesを変更して次のものを含めます。

springdoc.swagger-ui.path=/swagger-ui-custom.html

そのため、APIドキュメントは http:// localhost:8080 /swagger-ui-custom.htmlで利用できるようになります。

別の例として、HTTPメソッドの順序でAPIパスを並べ替えるために、次を追加できます。

springdoc.swagger-ui.operationsSorter=method

3.3. サンプルAPI

アプリケーションにBookを管理するためのコントローラーがあるとします。

@RestController
@RequestMapping("/api/book")
public class BookController {

    @Autowired
    private BookRepository repository;

    @GetMapping("/{id}")
    public Book findById(@PathVariable long id) {
        return repository.findById(id)
            .orElseThrow(() -> new BookNotFoundException());
    }

    @GetMapping("/")
    public Collection<Book> findBooks() {
        return repository.getBooks();
    }

    @PutMapping("/{id}")
    @ResponseStatus(HttpStatus.OK)
    public Book updateBook(
      @PathVariable("id") final String id, @RequestBody final Book book) {
        return book;
    }
}

次に、アプリケーションを実行すると、次の場所でドキュメントを表示できます。

http://localhost:8080/swagger-ui-custom.html

/ api / book エンドポイントにドリルダウンして、リクエストとレスポンスの詳細を確認しましょう。

4. springdoc-openapiとSpringWebFluxの統合

springdoc-openapi-webflux-ui を追加することで、springdoc-openapiとSwaggerUIをSpringWebFluxプロジェクトに統合できます。

<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-webflux-ui</artifactId>
    <version>1.6.4</version>
</dependency>

以前と同様に、ドキュメントには次の場所からアクセスできます。

http://localhost:8080/swagger-ui.html

パスをカスタマイズするために、application.propertiesspringdoc.swagger-ui.pathプロパティを再度追加できます。

5. ページネーション情報の公開

SpringDataJPAはSpringMVCと非常にシームレスに統合されます。 このような統合の一例は、Pageableサポートです。

@GetMapping("/filter")
public Page<Book> filterBooks(@ParameterObject Pageable pageable) {
     return repository.getBooks(pageable);
}

最初は、SpringDocが生成されたドキュメントに page size 、およびsortクエリパラメーターを追加することを期待するかもしれません。 ただし、デフォルトでは、SpringDocはこの期待に応えません。 この機能のロックを解除するには、springdoc-openapi-data-rest依存関係を追加する必要があります。

<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-data-rest</artifactId>
    <version>1.6.4</version>
</dependency>

これで、予想されるクエリパラメータがドキュメントに追加されます。

6. springdoc-openapiMavenプラグインの使用

springdoc-openapiライブラリは、jsonおよびyaml形式でOpenAPI記述を生成するためのMavenプラグインspringdoc-openapi-maven-pluginを提供します。

springdoc-openapi-maven-plugin プラグインは、spring-boot-mavenプラグインと連動します。 Mavenは、統合テストフェーズ中にopenapiプラグインを実行します。

pom.xmlでプラグインを構成する方法を見てみましょう。

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <version>2.3.3.RELEASE</version>
    <executions>
        <execution>
            <id>pre-integration-test</id>
            <goals>
                <goal>start</goal>
            </goals>
        </execution>
        <execution>
            <id>post-integration-test</id>
            <goals>
                <goal>stop</goal>
            </goals>
        </execution>
    </executions>
</plugin>
<plugin>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-maven-plugin</artifactId>
    <version>0.2</version>
    <executions>
        <execution>
            <phase>integration-test</phase>
            <goals>
                <goal>generate</goal>
            </goals>
        </execution>
    </executions>
</plugin>

カスタム値を使用するようにプラグインを構成することもできます。

<plugin>
    <executions>
        .........
    </executions>
    <configuration> 
        <apiDocsUrl>http://localhost:8080/v3/api-docs</apiDocsUrl> 
        <outputFileName>openapi.json</outputFileName> 
        <outputDir>${project.build.directory}</outputDir> 
    </configuration>
</plugin>

プラグイン用に構成できるパラメーターを詳しく見てみましょう。

  • apiDocsUrl –ドキュメントにJSON形式でアクセスできるURL。デフォルトは http:// localhost:8080 / v3 / api-docs
  • outputFileName –定義が保存されているファイルの名前。デフォルトはopenapi.jsonです。
  • outputDir –ドキュメントが保存されているディレクトリの絶対パス。デフォルトでは $ {project.build.directory}

7. JSR-303BeanValidationを使用した自動ドキュメント生成

モデルに@NotNull @NotBlank @Size @Min @Max 、springdoc-openapiライブラリはそれらを使用して、対応する制約の追加のスキーマドキュメントを生成します。

Bookbeanを使用した例を見てみましょう。

public class Book {

    private long id;

    @NotBlank
    @Size(min = 0, max = 20)
    private String title;

    @NotBlank
    @Size(min = 0, max = 30)
    private String author;

}

Book Bean用に生成されたドキュメントは、もう少し有益です。

8. @ControllerAdviceおよび@ResponseStatusを使用してドキュメントを生成します

@RestControllerAdviceクラスのメソッドで@ResponseStatusを使用すると、応答コードのドキュメントが自動的に生成されます。 この@RestControllerAdviceクラスでは、2つのメソッドに@ResponseStatusという注釈が付けられています。

@RestControllerAdvice
public class GlobalControllerExceptionHandler {

    @ExceptionHandler(ConversionFailedException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResponseEntity<String> handleConnversion(RuntimeException ex) {
        return new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST);
    }
    
    @ExceptionHandler(BookNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ResponseEntity<String> handleBookNotFound(RuntimeException ex) {
        return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);
    }
}

その結果、応答コード400および404のドキュメントを確認できます。

9. @Operationおよび@ApiResponsesを使用してドキュメントを生成します

次に、いくつかのOpenAPI固有のアノテーションを使用してAPIに説明を追加する方法を見てみましょう。

そのために、コントローラーの / api / book /{id}エンドポイントに@Operation@ApiResponsesの注釈を付けます。

@Operation(summary = "Get a book by its id")
@ApiResponses(value = { 
  @ApiResponse(responseCode = "200", description = "Found the book", 
    content = { @Content(mediaType = "application/json", 
      schema = @Schema(implementation = Book.class)) }),
  @ApiResponse(responseCode = "400", description = "Invalid id supplied", 
    content = @Content), 
  @ApiResponse(responseCode = "404", description = "Book not found", 
    content = @Content) })
@GetMapping("/{id}")
public Book findById(@Parameter(description = "id of book to be searched") 
  @PathVariable long id) {
    return repository.findById(id).orElseThrow(() -> new BookNotFoundException());
}

効果は次のとおりです。

ご覧のとおり、@Operationに追加したテキストはAPI操作レベルに配置されています。 同様に、@ApiResponsesコンテナアノテーションのさまざまな@ApiResponse要素に追加された説明もここに表示され、API応答に意味を追加します。

明らかに、上記の応答400および404のスキーマは取得されていません。 空の@Contentを定義したため、説明のみが表示されます。

10. Kotlinサポート

Spring Boot 2.xはKotlinをファーストクラスでサポートしているため、SpringDocはBoot2.xアプリケーションでこのJVM言語をすぐにサポートします。

これが実際に動作することを確認するために、Kotlinで単純な FooAPIを作成します。

初期設定の後に、データクラスとコントローラーを追加します。 それらをブートアプリのサブパッケージに追加して、実行時にFooControllerを以前のBookControllerと一緒にピックアップするようにします。

@Entity
data class Foo(
    @Id
    val id: Long = 0,
    
    @NotBlank
    @Size(min = 0, max = 50)
    val name: String = ""
)

@RestController
@RequestMapping("/")
class FooController() {
    val fooList: List = listOf(Foo(1, "one"), Foo(2, "two"))

    @Operation(summary = "Get all foos")
    @ApiResponses(value = [
	ApiResponse(responseCode = "200", description = "Found Foos", content = [
            (Content(mediaType = "application/json", array = (
                ArraySchema(schema = Schema(implementation = Foo::class)))))]),
	ApiResponse(responseCode = "400", description = "Bad request", content = [Content()]),
	ApiResponse(responseCode = "404", description = "Did not find any Foos", content = [Content()])]
    )
    @GetMapping("/foo")
    fun getAllFoos(): List = fooList
}

APIドキュメントのURLにアクセスすると、 FooAPIも表示されます。

Kotlinタイプのサポートを強化するために、次の依存関係を追加できます。

<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-kotlin</artifactId
    <version>1.6.4</version>
</dependency>

その後、JSR-303 Bean Validationを追加したときと同様に、Fooスキーマはより有益に見えます。

11. 結論

この記事では、プロジェクトでspringdoc-openapiを設定する方法を学びました。 次に、springdoc-openapiをSwaggerUIと統合する方法を確認しました。 また、SpringWebfluxプロジェクトでこれを行う方法も確認しました。

次に、springdoc-openapi Mavenプラグインを使用してAPIのOpenAPI定義を生成し、Springデータからページングと並べ替えの情報を公開する方法を確認しました。 その後、springdoc-openapiがJSR303Bean検証アノテーションと@ControllerAdviceクラスの@ResponseStatusアノテーションを使用してドキュメントを自動的に生成する方法を確認しました。

また、いくつかのOpenAPI固有のアノテーションを使用してAPIに説明を追加する方法も学びました。 最後に、OpenAPIによるKotlinのサポートを確認しました。

springdoc-openapiは、OpenAPI3仕様に従ってAPIドキュメントを生成します。 さらに、Swagger UI構成も処理するため、APIドキュメントの生成は非常に簡単なタスクになります。

いつものように、コードはGitHubから入手できます。