当前位置: 首页 > 知识库问答 >
问题:

如何使用 Swagger 代码生成开发一个简单的 REST 客户端?

井兴怀
2023-03-14

我正在学习Swagger以及如何使用Swagger代码生成REST客户端。我知道如何使用Swagger做文档,我也知道如何使用Swagger生成一个简单的REST服务器,但我不知道如何使用Swagger代码生成一个简单的REST客户端。

例如,我有一个简单的应用程序,它是一个REST服务器,我想生成REST客户端。我能用斯威格代码吗?

REST服务器的控制器:

package com.dgs.spring.springbootswagger.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;

@RestController
@RequestMapping("/api/v1")
@Api(value = "Employee Management System", description = "Operations pertaining to employee in Employee Management System")
public class EmployeeController {

     @Autowired
     private EmployeeRepository employeeRepository;

        @ApiOperation(value = "View a list of available employees", response = List.class)
        @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Successfully retrieved list"),
            @ApiResponse(code = 401, message = "You are not authorized to view the resource"),
            @ApiResponse(code = 403, message = "Accessing the resource you were trying to reach is forbidden"),
            @ApiResponse(code = 404, message = "The resource you were trying to reach is not found")
        })
     @GetMapping("/employees")
     public List<Employee> getAllEmployees() {
         return employeeRepository.findAll();
     }

     @ApiOperation(value = "Get an employee by Id")   
     @GetMapping("/employees/{id}")
     public ResponseEntity<Employee> getEmployeeById(
             @ApiParam(value = "Employee id from which employee object will retrieve", required = true) @PathVariable(value = "id") Long employeeId)
             throws ResourceNotFoundException {

          Employee employee = employeeRepository.findById(employeeId)
            .orElseThrow(() -> new ResourceNotFoundException("Employee not found for this id :: " + employeeId));

          return ResponseEntity.ok().body(employee);
     }

     @ApiOperation(value = "Add an employee")
     @PostMapping("/employees")
     public Employee createEmployee(
             @ApiParam(value = "Employee object store in database table", required = true) @Valid @RequestBody Employee employee) {
         return employeeRepository.save(employee);
     }

     @ApiOperation(value = "Update an employee")
     @PutMapping("/employees/{id}")
     public ResponseEntity<Employee> updateEmployee(
             @ApiParam(value = "Employee Id to update employee object", required = true) @PathVariable(value = "id") Long employeeId,
             @ApiParam(value = "Update employee object", required = true) @Valid @RequestBody Employee employeeDetails) throws ResourceNotFoundException {

          Employee employee = employeeRepository.findById(employeeId)
            .orElseThrow(() -> new ResourceNotFoundException("Employee not found for this id :: " + employeeId));

          employee.setEmail(employeeDetails.getEmail());
          employee.setLastName(employeeDetails.getLastName());
          employee.setFirstName(employeeDetails.getFirstName());
          final Employee updatedEmployee = employeeRepository.save(employee);

          return ResponseEntity.ok(updatedEmployee);
     }

     @ApiOperation(value = "Delete an employee")
     @DeleteMapping("/employees/{id}")
     public Map<String, Boolean> deleteEmployee(
             @ApiParam(value = "Employee Id from which employee object will delete from database table", required = true) @PathVariable(value = "id") Long employeeId)
       throws ResourceNotFoundException {

      Employee employee = employeeRepository.findById(employeeId)
        .orElseThrow(() -> new ResourceNotFoundException("Employee not found for this id :: " + employeeId));

      employeeRepository.delete(employee);
      Map<String, Boolean> response = new HashMap<>();
      response.put("deleted", Boolean.TRUE);

      return response;
     }
}

之后,我开发了一个简单的REST客户端:

package com.dgs.restclient.controllers;

@Controller
public class UpdateController {

    @Autowired
    private EmployeeRestClient restClient;

    @GetMapping("/showStartUpdate")
    public String showStartCheckin() {
        return "startUpdate";
    }

    @PostMapping("/startUpdate")
    public String startCheckIn(@RequestParam("employeeId") Long employeeId, ModelMap modelMap) {

        Employee employee = restClient.findEmployee(employeeId);
        modelMap.addAttribute("employee", employee);

        return "displayEmployeeDetails";
    }

    @PostMapping("/completeUpdate")
    public String completeCheckIn(@RequestParam("employeeId") Long employeeId,
            @RequestParam("employeeFirstName") String employeeFirstName,
            @RequestParam("employeeLastName") String employeeLastName,
            @RequestParam("employeeEmail") String employeeEmail) {

        EmployeeUpdateRequest employeeUpdateRequest = new EmployeeUpdateRequest();
        employeeUpdateRequest.setId(employeeId);
        employeeUpdateRequest.setFirstName(employeeFirstName);
        employeeUpdateRequest.setLastName(employeeLastName);
        employeeUpdateRequest.setEmail(employeeEmail);
        restClient.updateEmployee(employeeUpdateRequest);

        return "updateConfirmation";
    }

}

EmployeeRestClient:

package com.dgs.restclient.integration;

@Component
public class EmployeeRestClientImpl implements EmployeeRestClient {

    private static final String EMPLOYEE_REST_URL = 
            "http://localhost:8080/api/v1/employees/";

    @Override
    public Employee findEmployee(Long id) {

        RestTemplate restTemplate = new RestTemplate();
        Employee employee = restTemplate
                .getForObject(EMPLOYEE_REST_URL + id, Employee.class);

        return employee;
    }

    @Override
    public Employee updateEmployee(EmployeeUpdateRequest request) {

        RestTemplate restTemplate = new RestTemplate();
        restTemplate
                .put(EMPLOYEE_REST_URL + request.getId(), request, Employee.class); 

        Employee employee = restTemplate
                .getForObject(EMPLOYEE_REST_URL + request.getId(), Employee.class);

        return employee;
    }

}

这个REST客户端是由我开发的,我想知道我是否可以用Swagger代码进行REST客户端开发,以及如何进行?我需要在pom中添加swagger codegen maven插件吗。xml?我听说过添加这个插件和一个yml文件,Swager将创建REST客户端。任何反馈都将不胜感激!

共有3个答案

仉伟兆
2023-03-14

假设您的应用程序的Swagerendpoint可以访问:

>

  • 测试 Swagger 2.0 JSON API 文档

    http://localhost:8080/v2/api-文档?组=员工

    http://localhost:8080/v2/api-docs(如果尚未设置名为employee的组)

    测试Swagger UI

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

    您可以从Maven Central存储库下载swagger-codegen-cli-2.4.7.jar。

    现在您已经有了Swagger Codegen JAR,您可以通过执行以下命令来生成REST客户端:

    java -jar swagger-codegen-cli-2.4.7.jar generate \
      -i http://localhost:8080/v2/api-docs?group=employee \
      -l java \
      -o swagger-codegen-client
    

    如果没有招摇分组,

    java -jar swagger-codegen-cli-2.4.7.jar generate \
      -i http://localhost:8080/v2/api-docs \
      -l java \
      -o swagger-codegen-client
    

    尽管Swagger Codecen CLI带有许多选项,但我们使用的选项对于生成客户端代码是绝对必要的。

    • -i指向您的应用程序Swagger api docs的URL。
    • -l客户端的编程语言,在本例中为java
    • -o生成的客户端代码的输出文件夹。

    一旦您执行了前面生成代码的命令,您应该会注意到终端上的以下消息:

    [main] INFO io.swagger.parser.Swagger20Parser - reading from http://localhost:8080/v2/api-docs?group=employee
    [main] WARN io.swagger.codegen.ignore.CodegenIgnoreProcessor - Output directory does not exist, or is inaccessible. No file (.swagger-codegen-ignore) will be evaluated.
    [main] INFO io.swagger.codegen.AbstractGenerator - writing file swagger-codegen-client/src/main/java/io/swagger/client/model/Employee.java
    [main] INFO io.swagger.codegen.AbstractGenerator - writing file swagger-codegen-client/docs/Employee.md
    [main] INFO io.swagger.codegen.AbstractGenerator - writing file swagger-codegen-client/src/main/java/io/swagger/client/api/EmployeeControllerApi.java
    ...
    [main] INFO io.swagger.codegen.AbstractGenerator - writing file swagger-codegen-client/src/main/java/io/swagger/client/ApiClient.java
    ...
    

    代码生成完成后,您应该注意到具有以下结构的gradle/maven项目:

    __ swagger-codegen-client
      |__ README.md
      |__ build.gradle
      |__ build.sbt
      |__ docs
      |__ git_push.sh
      |__ gradle
      |__ gradle.properties
      |__ gradlew
      |__ gradlew.bat
      |__ pom.xml
      |__ settings.gradle
      |__ src
         |__ main
            |__ java
              |__ io.swagger.client.api
                 |__ EmployeeControllerApi.java
         |__ test
            |__ java
              |__ io.swagger.client.api
                 |__ EmployeeControllerApiTest.java
    

    可在此处找到生成的客户端项目的示例。

    客户端项目包含许多java类。然而,最重要的类是EmployeeControllerApi.java。这是一个包含用于创建REST客户端类的所有逻辑的类。

    另一个重要的类是EmployeeControllerApiTest.java。它向您展示了如何使用EmployeeControllerApi.java。生成的客户端项目还提供了一个非常有用的README文件

    类包含与建立 HTTP 客户端连接相关的信息。请确保 REST 应用程序的 basePath 正确。在生成的示例中,basePath 具有 https://localhost:8080 URL,而不是 http://localhost:8080

    生成的项目适用于Java8。如果您使用的是Java12,则必须添加以下依赖项才能编译项目:

        <dependency>
            <groupId>javax.xml.bind</groupId>
            <artifactId>jaxb-api</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-core</artifactId>
            <version>2.3.0</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>2.3.0</version>
        </dependency>
    
        <dependency>
            <groupId>javax.annotation</groupId>
            <artifactId>javax.annotation-api</artifactId>
            <version>1.3.2</version>
        </dependency>
    

    下面是通过调用 REST POST 方法方法创建员工的示例。

    Employee employee = new Employee();
    employee.setId(3L);
    employee.setFirstName("Sam");
    employee.setLastName("Fox");
    employee.setEmail("sfox@gmail.com");
    
    EmployeeControllerApi api = new EmployeeControllerApi();
    Employee response = api.createEmployeeUsingPOST(employee);
    System.out.println(response);
    

    您应该做出类似如下的响应:

    class Employee {
        email: sfox@gmail.com
        firstName: Sam
        id: 3
        lastName: Fox
    }
    

    您可以在此处找到完整的示例。

  • 傅博瀚
    2023-03-14

    更新:

    您的问题已在另一篇文章中回答。看一看:相关文章

    ...

    baeldung有一个关于它的很好的教程:如何使用swagger codecen创建rest客户端

    例如,执行命令:

    java -jar swagger-codegen-cli.jar generate \
      -i http://mydomain/v2/swagger.json \
      --api-package com.mypackage.api \
      --model-package com.mypackage.model \
      --invoker-package com.mypackage.invoker \
      --group-id com.mygroup \
      --artifact-id spring-swagger-codegen-api-client \
      --artifact-version 0.0.1-SNAPSHOT \
      -l java \
      --library resttemplate \
      -o spring-swagger-codegen-api-client
    

    Swagger Codegen支持以下客户端实现:

    1. 球衣1杰克逊
    2. 杰克森球衣2
    3. 假杰克逊
    4. OkHttp Gson
    5. 改装2/OkHttp Gson
    6. SpringRest模板杰克逊
    7. 雷斯特西·杰克逊

    P.S.如您所见,rest客户机是由swagger规范定义生成的,它由“-i”参数定义。

    东门晓博
    2023-03-14

    是的。您可以使用swagger-codegen-maven-plugin生成REST客户端。但在此之前,您需要在OpenAPI规范中用YAML或JSON描述REST API,主要是因为swagger-codegen-maven-plugin只能从本规范中编写的文件生成REST客户端。

    其他答案假设您需要手动编写规范,而我的解决方案则进一步从REST控制器源代码自动生成规范。

    < sup >最新的OpenAPI版本是3.0。但是基于您导入的swagger注释的包,您使用的是2.0版(或更早)。所以我的解决方案假设您使用的是OpenAPI 2.0。

    生成开放API规范

    首先,您可以使用 swagger-maven-plugin 从 RestController 源代码生成 OpenAPI 规范。它基本上分析了在 @RestController 类中注释的 Swagger 注释,这些注释在

    <plugin>
        <groupId>com.github.kongchen</groupId>
        <artifactId>swagger-maven-plugin</artifactId>
        <version>3.1.5</version>
        <configuration>
            <apiSources>
                <apiSource>
                    <springmvc>true</springmvc>
                    <locations>
                        <location>com.dgs.spring.springbootswagger.controller.EmployeeController</location>
                        <location>com.dgs.spring.springbootswagger.controller.FooController</location>
                    </locations>
                    <schemes>
                        <scheme>http</scheme>
                    </schemes>
                    <host>127.0.0.1:8080</host>
                    <basePath>/</basePath>
                    <info>
                        <title>My API</title>
                        <version>1.1.1</version>
                    </info>
                    <swaggerDirectory>${basedir}/src/main/resources/</swaggerDirectory>
                </apiSource>
            </apiSources>
        </configuration>
        <executions>
            <execution>
                <goals>
                    <goal>generate</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    

    执行以下maven命令开始生成:

    mvn clean compile
    

    生成Rest客户端

    生成swagger.json后,您可以将其复制并粘贴到您的客户端项目中(例如 /src/main/resources/swagger.json),然后我们可以使用swagger-codegen-maven-plugin生成HTTP客户端。

    默认情况下,它将生成整个maven项目,其中包括测试用例和其他文档资料。但是我想要的只是HttpClient的源代码,没有其他东西。经过几次反复试验,我确定了以下配置:

    <plugin>
        <groupId>io.swagger</groupId>
        <artifactId>swagger-codegen-maven-plugin</artifactId>
        <version>2.4.7</version>
        <executions>
            <execution>
                <goals>
                    <goal>generate</goal>
                </goals>
                <configuration>
                    <inputSpec>${basedir}/src/main/resources/swagger.json</inputSpec>
                    <language>java</language>
                    <library>resttemplate</library>
                    <output>${project.basedir}/target/generated-sources/</output>
    
                    <apiPackage>com.example.demo.restclient.api</apiPackage>
                    <modelPackage>com.example.demo.restclient.model</modelPackage>
                    <invokerPackage>com.example.demo.restclient</invokerPackage>
    
                    <generateApiTests>false</generateApiTests>
                    <generateModelTests>false</generateModelTests>
                    <generateApiDocumentation>false</generateApiDocumentation>
                    <generateModelDocumentation>false</generateModelDocumentation>
                    <configOptions>
                        <dateLibrary>java8</dateLibrary>
                        <sourceFolder>restclient</sourceFolder>
                    </configOptions>
                </configuration>
            </execution>
        </executions>
    </plugin>
    

    生成的HTTP客户端基于RestTemplate,将生成到文件夹target/generatedsources/restclient。您可能需要配置IDE以导入生成的客户端才能使用它➡️ Java构建路径➡️ 添加生成的rest客户端的文件夹)

    要开始生成客户端,只需执行 maven 命令:

    mvn clean compile
    

    要使用生成的HTTP客户端:

    ApiClient apiClient = new ApiClient();
    
    //Override the default API base path configured in Maven
    apiClient.setBasePath("http://api.example.com/api");
    
    EmployeeManagementSystemApi api = new EmployeeManagementSystemApi(apiClient);
    api.getEmployeeById(1l);
    

    注:

    • 如果在使用java8时在生成过程中遇到javax/xml/bind/nannotation/XmlRootElement异常,您可能需要参考这一点

     类似资料:
    • 我的设想如下。 我有一个swagger. json,例如:http://petstore.swagger.io/v2/swagger.json我想为上面的REST API使用生成的java客户端,例如: 扩展输出:<code>cica</code>,新宠物根据REST API实现进行存储。 我已经使用以下命令成功地为petstore生成了服务器存根: 但是这个 maven 项目代码是一个服务器代码

    • 我需要在eclipse中使用with swagger codegen插件(用于maven)生成服务器存根代码。你能帮我怎么做吗?以及需要什么配置(在pom.xml中)。

    • 我正在努力创建rest客户端,我将调用一个API来提供这个大的json输出。我想知道如何通过输入这个json来自动创建Pojo类来晃动代码gen,并让它为我创建我的pojo类,这将节省手动时间。这是我尝试过的 要为生成PHP客户端,请执行以下操作:http://petstore.swagger.io/v2/swagger.json,请运行以下命令: (如果您使用的是Windows,请将最后一个命令

    • 问题内容: 我已经开始使用Spring学习Apache CXF。首先,我尝试创建一个简单的客户端/服务器模型。 服务器端是: service.HelloWorld.java service.HelloWorldImpl.java 客户端是: client.Client.java 公共类Client { cxf-client-servlet.xml 问题是:要使客户端正常工作,我必须向客户端的项目添

    • 我正在尝试使用swagger codegen maven插件(版本3.0.0)生成的ApiClient,从我的Spring Boot应用程序中使用OAuth2安全的REST API。身份验证服务器(keycoat)提供了一个JWT和刷新令牌,但我不知道如何最好地处理bean中的令牌。现在我的豆子看起来像这样: 问题是:获取令牌和处理刷新令牌的最佳方法是什么? 编辑:为了获得令牌,我想使用客户端ID

    • 我的目标是使用OpenAPI3.0生成Spring Boot REST客户端。 我希望首先生成API的OpenAPI规范文件(springdoc-openapi-maven-plugin),然后使用Maven从该文件(swagger-codegen-maven-plugin)生成客户机代码。 我的问题是swagger-codegen-maven-plugin在springdoc-openapi-m