如何使用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";
    }

}

员工最忠实客户:

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


答案 1

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

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

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

生成开放 API 规范

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

<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 客户端

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

默认情况下,它将生成整个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,并将生成到文件夹 。您可能需要将 IDE 配置为导入生成的客户端才能使用它。(对于 Eclipse,您可以在项目属性➡️中配置 Java 构建路径 ➡️ 添加生成的 rest 客户端的文件夹)target/generated-sources/restclient

要开始生成客户端,只需执行 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

答案 2

更新:

您的问题在另一篇文章中得到了解答。一起来看看:相关文章

...

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

在baeldung有一个很好的教程:如何使用swagger codegen创建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 支持以下 Client 实现:

  1. 球衣1 + 杰克逊
  2. 球衣2 + 杰克逊
  3. 假装+杰克逊
  4. OkHttp + Gson
  5. Retrofit2/OkHttp + Gson
  6. 春季休息模板 + 杰克逊
  7. Resteasy + Jackson

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


推荐