知識庫 / Spring / Spring Boot RSS 訂閱

使用 OpenAPI 生成器實現開放 API 服務器

Spring Boot
HongKong
8
12:34 PM · Dec 06 ,2025

1. 概述

正如其名稱所示,OpenAPI Generator 從 OpenAPI 規範生成代碼。它可以創建客户端庫、服務器樁、文檔和配置。

它支持多種語言和框架。特別值得一提的是,它支持 C++、C#、Java、PHP、Python、Ruby、Scala——幾乎所有廣泛使用的 那些

在本教程中,我們將學習 如何使用 OpenAPI Generator 的 Maven 插件來創建基於 Spring 的服務器樁

通過其 CLI在線工具 也可以使用生成器。

2. YAML 文件

為了開始,我們需要一個 YAML 文件,其中指定了 API。我們將將其作為輸入提供給我們的生成器,以生成服務器樁。

以下是我們的 <em >petstore.yml</em> 的片段:

openapi: "3.0.0"
paths:
  /pets:
    get:
      summary: List all pets
      operationId: listPets
      tags:
        - pets
      parameters:
        - name: limit
          in: query
          ...
      responses:
        ...
    post:
      summary: Create a pet
      operationId: createPets
      ...
  /pets/{petId}:
    get:
      summary: Info for a specific pet
      operationId: showPetById
      ...
components:
  schemas:
    Pet:
      type: object
      required:
        - id
        - name
      properties:
        id:
          type: integer
          format: int64
        name:
          type: string
        tag:
          type: string
    Error:
      type: object
      required:
        - code
        - message
      properties:
        code:
          type: integer
          format: int32
        message:
          type: string

3. Maven 依賴

Maven 依賴是構建項目時,項目所依賴的外部庫和組件。這些依賴項通常存儲在 Maven 倉庫中,Maven 構建工具會從這些倉庫中下載並管理依賴項。

以下是一些常見的 Maven 依賴類型:

  • JAR (Java Archive): 包含 Java 類文件的壓縮文件。
  • WAR (Web Application Archive): 包含 Web 應用程序所需的所有文件,例如 Web 應用的類文件、資源文件和 Web 應用描述文件。
  • EAR (Enterprise Application Archive): 包含 WAR 文件和相關的配置文件的壓縮文件,用於部署大型企業應用程序。
  • POM (Project Object Model): Maven 項目的描述文件,包含項目的元數據、依賴項、構建配置等信息。

pom.xml 文件中,可以使用 <dependencies> 標籤來聲明項目的依賴項。例如:

<dependencies>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.12.0</version>
    </dependency>
</dependencies>

這個例子聲明瞭對 Apache Commons Lang 3 的依賴。 groupId 是 Maven 倉庫中的組織標識符,artifactId 是 Artifact 的 ID,version 是版本號。

3.1. OpenAPI 生成器插件

接下來,讓我們添加 Maven 依賴,用於生成器插件:

<plugin>
    <groupId>org.openapitools</groupId>
    <artifactId>openapi-generator-maven-plugin</artifactId>
    <version>7.8.0</version>
    <executions>
        <execution>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <inputSpec>
                    ${project.basedir}/src/main/resources/petstore.yml
                </inputSpec>
                <generatorName>spring</generatorName>
                <apiPackage>com.baeldung.openapi.api</apiPackage>
                <modelPackage>com.baeldung.openapi.model</modelPackage>
                <supportingFilesToGenerate>
                    ApiUtil.java
                </supportingFilesToGenerate>
                <configOptions>
                    <delegatePattern>true</delegatePattern>
                </configOptions>
            </configuration>
        </execution>
    </executions>
</plugin>

如我們所見,我們通過 YAML 文件傳遞了 inputSpec。之後,由於我們需要一個基於 Spring 的服務器,我們使用 generatorName 作為 spring

然後,apiPackage 指定了 API 生成到的包名。

接下來,我們有 modelPackage,生成器將數據模型放置在其。

delegatePattern 設置為 true 時,我們希望創建一個可以作為自定義 @Service 類的實現接口。

重要的是,OpenAPI Generator 的選項與我們是否使用 CLI、Maven/Gradle 插件或在線生成選項相同。

3.2. Maven 依賴

由於我們將生成一個 Spring 服務器,因此還需要其依賴項(包括 Spring Boot Starter WebSpring Data JPA),以便生成的代碼能夠編譯和正常運行。

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <version>2.4.4</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.data</groupId>
        <artifactId>spring-data-jpa</artifactId>
        <version>2.4.6</version>
    </dependency>
</dependencies>

除了上述 Spring 依賴之外,我們還需要 jackson-databindspringdoc 依賴,以便我們的生成代碼能夠成功編譯:

<dependency>
    <groupId>org.openapitools</groupId>
    <artifactId>jackson-databind-nullable</artifactId>
    <version>0.2.1</version>
</dependency>
<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-ui</artifactId>
    <version>1.7.0</version>
</dependency>

4. 代碼生成

要生成服務器樁,只需運行以下命令:

mvn clean install

因此,我們得到的是:

現在讓我們來查看一下代碼,首先查看 apiPackage 的內容。

首先,我們得到一個名為 PetsApi 的 API 接口,其中包含 YAML 規範中定義的的所有請求映射。

以下是片段:

@javax.annotation.Generated(value = "org.openapitools.codegen.languages.SpringCodegen", 
  date = "2021-03-22T23:26:32.308871+05:30[Asia/Kolkata]")
@Validated
@Api(value = "pets", description = "the pets API")
public interface PetsApi {
    /**
     * GET /pets : List all pets
     *
     * @param limit How many items to return at one time (max 100) (optional)
     * @return A paged array of pets (status code 200)
     *         or unexpected error (status code 200)
     */
    @ApiOperation(value = "List all pets", nickname = "listPets", notes = "", 
      response = Pet.class, responseContainer = "List", tags={ "pets", })
    @ApiResponses(value = { @ApiResponse(code = 200, message = "A paged array of pets", 
      response = Pet.class, responseContainer = "List"),
      @ApiResponse(code = 200, message = "unexpected error", response = Error.class) })
    @GetMapping(value = "/pets", produces = { "application/json" })
    default ResponseEntity<List<Pet>> listPets(@ApiParam(
      value = "How many items to return at one time (max 100)") 
      @Valid @RequestParam(value = "limit", required = false) Integer limit) {
        return getDelegate().listPets(limit);
    }

    // other generated methods
}

其次,由於我們使用了委託模式,OpenAPI 還為我們生成了一個名為 PetsApiDelegate 的委託接口。

特別是,該接口中聲明的方法默認返回 HTTP 狀態碼 501 Not Implemented

@javax.annotation.Generated(value = "org.openapitools.codegen.languages.SpringCodegen", 
  date = "2021-03-22T23:26:32.308871+05:30[Asia/Kolkata]")
public interface PetsApiDelegate {
    /**
     * GET /pets : List all pets
     *
     * @param limit How many items to return at one time (max 100) (optional)
     * @return A paged array of pets (status code 200)
     *         or unexpected error (status code 200)
     * @see PetsApi#listPets
     */
    default ResponseEntity<List<Pet>> listPets(Integer limit) {
        getRequest().ifPresent(request -> {
            for (MediaType mediaType: MediaType.parseMediaTypes(request.getHeader("Accept"))) {
                if (mediaType.isCompatibleWith(MediaType.valueOf("application/json"))) {
                    String exampleString = "{ \"name\" : \"name\", \"id\" : 0, \"tag\" : \"tag\" }";
                    ApiUtil.setExampleResponse(request, "application/json", exampleString);
                    break;
                }
            }
        });
        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
    }

    // other generated method declarations
}

之後,我們看到 有一個 PetsApiController 類,它只是將委託器連接起來:

@javax.annotation.Generated(value = "org.openapitools.codegen.languages.SpringCodegen", 
  date = "2021-03-22T23:26:32.308871+05:30[Asia/Kolkata]")
@Controller
@RequestMapping("${openapi.swaggerPetstore.base-path:}")
public class PetsApiController implements PetsApi {

    private final PetsApiDelegate delegate;

    public PetsApiController(
      @org.springframework.beans.factory.annotation.Autowired(required = false) PetsApiDelegate delegate) {
        this.delegate = Optional.ofNullable(delegate).orElse(new PetsApiDelegate() {});
    }

    @Override
    public PetsApiDelegate getDelegate() {
        return delegate;
    }
}

modelPackage 中,生成了若干個數據模型 POJO,名為 ErrorPet,這些 POJO 基於我們 YAML 輸入中定義的 schemas 而生成。

讓我們來看其中之一——Pet

@javax.annotation.Generated(value = "org.openapitools.codegen.languages.SpringCodegen", 
  date = "2021-03-22T23:26:32.308871+05:30[Asia/Kolkata]")
public class Pet {
  @JsonProperty("id")
  private Long id;

  @JsonProperty("name")
  private String name;

  @JsonProperty("tag")
  private String tag;

  // constructor

  @ApiModelProperty(required = true, value = "")
  @NotNull
  public Long getId() {
    return id;
  }

  // other getters and setters

  // equals, hashcode, and toString methods
}

5. 測試服務器

現在,為了使服務器樁作為一個服務器正常運行,只需要實現 delegator 接口的實現。

為了保持簡單,我們不會在這裏進行操作,而是隻測試樁。

此外,在進行測試之前,我們需要一個 Spring Application

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

5.1. 使用 curl 測試

啓動應用程序後,我們只需運行以下命令:

curl -I http://localhost:8080/pets/

以下是預期結果:

HTTP/1.1 501 
Content-Length: 0
Date: Fri, 26 Mar 2021 17:29:25 GMT
Connection: close

5.2. 集成測試

或者,我們可以為相同功能編寫一個簡單的集成測試:

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class OpenApiPetsIntegrationTest {
    private static final String PETS_PATH = "/pets/";

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void whenReadAll_thenStatusIsNotImplemented() throws Exception {
        this.mockMvc.perform(get(PETS_PATH)).andExpect(status().isNotImplemented());
    }

    @Test
    public void whenReadOne_thenStatusIsNotImplemented() throws Exception {
        this.mockMvc.perform(get(PETS_PATH + 1)).andExpect(status().isNotImplemented());
    }
}

6. Spring Boot 3.0 版本及 jakarta 命名空間

此外,我們的配置在 Spring Boot 版本 3.0 之前的項目上都能正常工作。但是,從 Spring Boot 3.0 開始,javax 命名空間已被jakarta 命名空間所取代。

因此,為了生成與 Spring Boot 3.0 及更高版本兼容的代碼,我們需要修改插件配置中的 configOptions 選項:

<configOptions>
     // ... 
    <useSpringBoot3>true</useSpringBoot3>
</configOptions>

在這裏,我們添加了 useSpringBoot3 選項並將其設置為 true。此選項默認啓用 jakarta 命名空間。

或者,我們可以指定 useJakartaEe 選項,在 configOptions 中。

<configOptions>
     // ...
    <useJakartaEe>true</useJakartaEe>
</configOptions>

通過將 useJakartaEe 選項設置為 true,生成的代碼將使用 jakarta 命名空間,並且不會出現編譯錯誤。

值得注意的是,在 Spring Boot 3.0 項目中同時定義這兩個選項是多餘的,因為 useSpringBoot3 選項默認會啓用 useJakartaEe 選項。

7. 結論

在本文中,我們瞭解到如何使用 OpenAPI 生成器 Maven 插件,從 YAML 規範生成基於 Spring 的服務器樁。

作為下一步,我們還可以使用它來生成客户端。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.