如何使用 Swagger codegen 开发一个简单的 REST 客户端?

新手上路,请多包涵

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

例如,我有一个简单的应用程序,它是一个 REST 服务器,我想生成 REST 客户端。我可以用 Swagger codegen 做到这一点吗?

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 Client 是我开发的,我想知道我是否可以使用 Swagger codegen 进行这个 REST Client 开发,如何做?我只需要在 pom.xml 中添加 swagger-codegen-maven-plugin 吗?我听说过添加这个插件和一个 yml 文件,Swagger 将创建 REST 客户端。任何反馈将不胜感激!

原文由 elvis 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 527
2 个回答

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

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

最新的 OpenAPI 版本是 3.0 。但是根据您导入的 swagger 注释的包,您使用的是 2.0(或之前)版本。所以我的解决方案假设您使用的是 OpenAPI 2.0。

生成开放 API 规范

首先,您可以使用 swagger-maven-plugin 从 RestController 源代码生成 OpenAPI 规范。它基本上分析了 @RestController 中指定的类中注释的 Swagger 注释 <locations> 并将 OpenAPI 规范转储到 /src/main/resources/swagger.json :2a–

 <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/generated-sources/restclient 。您可能必须配置 IDE 以导入生成的客户端才能使用它。 (如果是Eclipse,可以在Project Properties中配置➡️Java Build Path ➡️添加生成的rest client的文件夹)

要开始生成客户端,只需执行 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/annotation/XmlRootElement 生成异常,你可能需要参考 这个

原文由 Ken Chan 发布,翻译遵循 CC BY-SA 4.0 许可协议

更新:

您的问题已在另一篇文章中得到解答。看一下: 相关帖子

仅供参考,一种使用命令行的简单方法:

在 baeldung 有一个很好的教程: how to create rest client with swagger codegen

例如执行命令:

 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. Jersey2 + 杰克逊
  3. 假装+杰克逊
  4. OkHttp + Gson
  5. Retrofit2/OkHttp + Gson
  6. Spring RestTemplate + Jackson
  7. Resteasy + 杰克逊

PS 如您所见,其余客户端是从 swagger 规范定义生成的,并使用“-i”参数定义。

原文由 Ariel Carrera 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题