概要

OpenAPIを使ってAPIの設計書からSpring Bootのコントローラーやモデルクラスを自動生成し、 さらにHTML2ジェネレータを使ってドキュメントを生成する方法を、解説します。 手順は以下のようになってます。

  1. OpenAPIの基本を理解する
  2. Spring Bootプロジェクトの初期設定(依存関係とGradle設定)を行う
  3. OpenAPI YAMLファイルを作成し、openApiGenerateタスクでコードを生成する
  4. 生成されたコントローラーインターフェース/モデルクラスを確認し、必要な実装クラスを作成する
  5. openApiHtml2タスクで静的ドキュメントを生成し、ブラウザで確認する

1. OpenAPI とは何か?

1.1 OpenAPI の概要

OpenAPI Specification(OAS)は、RESTful APIを機械可読な形式(YAMLまたはJSON)で定義するための標準規格です。 もともと「Swagger Specification」と呼ばれており、2016年以降はLinux Foundation傘下のOpenAPI Initiativeによって管理されています。 OpenAPIを利用すると、APIのエンドポイント、パラメータ、リクエスト/レスポンス構造、認証方式などを一元的に記述でき、 様々なツール(ドキュメント生成、テスト自動化、クライアント/サーバースタブ生成など)と連携が可能になります。

1.2 OpenAPI のメリット

  • 標準化された記述フォーマット:誰が書いても同じ構造で記述でき、チーム内で共通ルールを確立できる。
  • ドキュメントの自動生成:Swagger UIやhtml2などを使い、仕様から自動的にリファレンスドキュメントを生成できる。
  • コード生成:クライアントライブラリやサーバースタブを自動生成し、手作業のコーディングを減らせる。
  • 仕様と実装の整合性:設計書と実装がずれにくくなり、保守性が向上する。

1.3 OpenAPI の構造例(YAML)

openapi: 3.0.1
info:
  title: Customer API
  version: '1.0'
servers:
  - url: http://localhost:8080
paths:
  /customers:
    get:
      summary: 顧客一覧を取得
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Customer'
    post:
      summary: 新規顧客を作成
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Customer'
      responses:
        '201':
          description: 作成完了
  /customers/{id}:
    get:
      summary: IDで顧客を取得
      parameters:
        - name: id
          in: path
          required: true
          schema:
            type: integer
      responses:
        '200':
          description: 成功
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Customer'
components:
  schemas:
    Customer:
      type: object
      properties:
        id:
          type: integer
        name:
          type: string
        email:
          type: string
      required:
        - id
        - name
        - email

2. Spring Boot プロジェクトの準備

2.1 プロジェクトのディレクトリ構成例

trn-generateApi/
├─ autoGenerate/
│  ├─ build.gradle
│  ├─ settings.gradle
│  └─ src/
│     ├─ main/
│     │  ├─ java/
│     │  └─ resources/
│     │     └─ openapi.yaml
│     └─ test/
└─ README.md

- build.gradle:Gradle設定ファイル - settings.gradle:プロジェクト情報 - src/main/resources/openapi.yaml:OpenAPI仕様のYAMLファイル - src/main/java:生成されたコードおよび独自実装クラスを配置 - src/main/resources:静的ドキュメント(HTML2出力など)を配置

2.2 build.gradle の基本設定

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.5.0'
    id 'io.spring.dependency-management' version '1.1.7'
    id 'org.openapi.generator' version '7.13.0'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'

java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'io.swagger.core.v3:swagger-annotations:2.2.30'
    implementation 'org.openapitools:jackson-databind-nullable:0.2.6'
    compileOnly  'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') {
    useJUnitPlatform()
}

// ドキュメント出力先ディレクトリ
def docsOutputDir = "$projectDir/src/main/resources"

// コード生成出力先ディレクトリ
def generatedCodeDir = "$buildDir/generated"

// OpenAPI Generator 設定
openApiGenerate {
    generatorName  = 'spring'
    inputSpec      = "$projectDir/src/main/resources/openapi.yaml"
    outputDir      = generatedCodeDir
    apiPackage     = 'com.example.api'
    modelPackage   = 'com.example.model'
    invokerPackage = 'com.example.invoker'
    configOptions = [
        interfaceOnly       : 'true',
        dateLibrary         : 'java8',
        useSpringBoot3      : 'true',
        useJakartaEe        : 'true'
    ]
}

// 生成されたコードを main ソースセットに追加
sourceSets {
    main {
        java {
            srcDirs += "$generatedCodeDir/src/main/java"
        }
    }
}

// コード生成用クリーン
task cleanGenerated(type: Delete) {
    group       = "openapi tools"
    description = "自動生成コードをクリーンする"
    delete generatedCodeDir
}

// html2 ジェネレータ実行タスク
tasks.register('openApiHtml2', org.openapitools.generator.gradle.plugin.tasks.GenerateTask) {
    group       = 'openapi tools'
    description = 'OpenAPI Generator の html2 で静的ドキュメント生成'
    generatorName.set('html2')
    inputSpec.set(tasks.named('openApiGenerate').get().inputSpec.get())
    outputDir.set(docsOutputDir)
    configOptions.set([
        title                   : "API定義書",
        withInterfaces          : "true",
        hideGenerationTimestamp : "true"
    ])
}

// クリーン→生成を一気に行うタスク
task cleanAndGenerate {
    group       = "openapi tools"
    description = "クリーン後にコードとドキュメント生成を行う"
    dependsOn cleanGenerated, tasks.named('openApiGenerate'), tasks.named('openApiHtml2')
}

3. コード生成の実行方法

3.1 コマンドラインでの実行

  1. 生成済みコードのクリーン
    ./gradlew cleanGenerated
    build/generatedを削除します。
  2. Spring用サーバースタブ & モデルクラス生成
    ./gradlew openApiGenerate
    build/generated/src/main/javaにインターフェースやモデルが生成されます。
  3. 静的ドキュメント(html2)生成
    ./gradlew openApiHtml2
    src/main/resources/index.htmlなどの静的ファイルが生成されます。
  4. クリーン & 一括生成
    ./gradlew cleanAndGenerate
    build/generatedをクリーン後、openApiGenerateopenApiHtml2を順に実行します。

3.2 IDEからの実行

  • IntelliJ IDEA
    - 右ペインの「Gradle」タブ → openapi toolsopenApiGenerate / openApiHtml2 をダブルクリックで実行できます。 - または Run → Edit Configurations で「Gradle」を新規作成し、タスク名を指定して実行可能です。
  • Eclipse
    - 「Gradle Tasks」ビューを開き、openApiGenerate / openApiHtml2 を右クリック → Run Gradle Task で実行します。

4. 生成されたコードの確認と実装

4.1 ディレクトリ構造例

build/
└─ generated/
   └─ src/
      └─ main/
         └─ java/
            └─ com/
               └─ example/
                  ├─ api/
                  │  ├─ CustomerApi.java
                  │  └─ OtherApi.java
                  ├─ model/
                  │  ├─ Customer.java
                  │  └─ ErrorResponse.java
                  └─ invoker/
                     ├─ ApiClient.java
                     └─ Configuration.java

- api/CustomerApi.javaなどに、自動生成されたコントローラーインターフェースが配置されます。 - model/Customer.javaなどに、自動生成されたモデルクラスが配置されます。

4.2 コントローラーインターフェース例

package com.example.api;

import org.springframework.web.bind.annotation.*;
import java.util.List;
import com.example.model.Customer;

@RequestMapping("/customers")
public interface CustomerApi {

    @GetMapping
    List getCustomers();

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    void createCustomer(@RequestBody Customer customer);

    @GetMapping("/{id}")
    Customer getCustomerById(@PathVariable("id") Long id);
}

- @RequestMapping@GetMappingなどは、OpenAPIのpaths定義に応じて自動生成されます。 - 実際のビジネスロジックは、このインターフェースを実装するクラス(例:CustomerApiController)に記述します。

4.3 モデルクラス例

package com.example.model;

import lombok.Data;

@Data
public class Customer {
    private Long id;
    private String name;
    private String email;
}

- @Data(Lombok)は、getter/setterやtoString()などを自動生成するため、ボイラープレートが減ります。 - Lombokを使うには、compileOnly 'lombok'annotationProcessor 'lombok'build.gradleに記載しておく必要があります。

5. HTML2 を使った静的ドキュメント生成と確認

5.1 html2 タスクの挙動

src/
└─ main/
   └─ resources/
      ├─ index.html
      ├─ openapi.json
      ├─ openapi.yaml
      └─ assets/
         ├─ swagger-ui.css
         ├─ swagger-ui-bundle.js
         └─ ...他ファイル

- ./gradlew openApiHtml2 を実行すると、src/main/resources/index.html などが生成されます。 - index.html をブラウザで開くと、左側にエンドポイント一覧、右側にモデル定義が表示されたAPIリファレンス画面が確認できます。

5.2 ブラウザでの確認方法

  1. プロジェクト直下の src/main/resources/index.html をダブルクリックし、ブラウザで開く
  2. Spring Boot アプリを ./gradlew bootRun で起動し、http://localhost:8080/index.html にアクセスする

6. まとめ

  • OpenAPIを使うと、API設計書を機械可読なYAML/JSONで定義し、設計書からサーバーコードとドキュメントを自動生成できる。
  • Spring Bootプロジェクトに org.openapi.generator と必要な依存関係を追加しておくことで、openApiGenerate タスクがコントローラーインターフェースとモデルクラスを生成する。
  • openApiHtml2 タスクを実行すると、静的HTML形式のAPIリファレンスsrc/main/resources に生成され、すぐにブラウザで確認できる。
  • 生成されたインターフェースを実装し、ビジネスロジックを追加するだけで、APIファースト開発が完了する。

以上の手順を試すことで、「仕様書から動くAPIをスピーディに作る」開発フローが身につきます。ぜひ実際に手を動かして確認してください。