如何使用swagger自定义api spec中生成的operationId的值?

时间:2016-08-08 05:19:59

标签: spring swagger springfox

我使用springfox 2.0配置了我的spring项目。我可以用它生成open api规范。

 "paths": {
    "/test/testinfo": {
      "post": {
        "tags": [
          "test-controller"
        ],
        "summary": "getTestInfo",
        "operationId": "getTestInfoInfoUsingGET",
        "consumes": [
          "application/json"
        ],
        "produces": [
          "application/json"
        ]

正如您所看到的,operationId的值是格式

[java_method_name_here]Using[HTTP_verb_here]

离。 getPetsUsingGET

使用swagger-codegen生成客户端时使用此operationId。 有谁知道如何定制它?我知道这可以使用@ApiOperation按api完成,但有没有更通用的方法来为所有api定义这种格式?

5 个答案:

答案 0 :(得分:4)

你可以create your own plugin来做。以下是an example我们如何在springfox中使用相同的插件技术。

@Component
@Order(YOUR_PLUGIN_ORDER) // > Ordered.HIGHEST_PRECEDENCE + 1000
public class OperationNicknameIntoUniqueIdReader implements OperationBuilderPlugin {
  @Override
  public void apply(OperationContext context) {

    //Create your own transformation to format the name in the way 
    //that you prefer
    String operationNameStem = transformName(context.getName());
    //Update the method name stem that is used to generate a unique id
    context.operationBuilder().codegenMethodNameStem(operationNameStem);
  }
  ...
}

注意:无论您提出什么干扰,springfox都会确保它在所有API中都是唯一的。因此,如果您有一个重复的命名方法,它将在您的唯一名称末尾开始编号方案。例如如果getCustomer不唯一,则会生成唯一ID getCustomer_1等。

答案 1 :(得分:0)

以下是删除“使用” + VERB的完整示例:

它与:

  • 春季版本5.1.9.RELEASE
  • Springfox 2.9.2
  • Swagger版本1.5.23
import com.google.common.base.Optional;
import io.swagger.annotations.ApiOperation;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import springfox.documentation.service.Operation;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.OperationBuilderPlugin;
import springfox.documentation.spi.service.contexts.OperationContext;
import springfox.documentation.swagger.common.SwaggerPluginSupport;

@Component
@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1000)
public class IncludeMissingNicknameIntoUniqueIdReader implements OperationBuilderPlugin
{
    @Override
    public void apply(OperationContext context)
    {
        Optional<ApiOperation> methodAnnotation = context.findControllerAnnotation(ApiOperation.class);
        Operation operationBuilder = context.operationBuilder().build();
        String uniqueId = operationBuilder.getUniqueId().replaceAll("Using(GET|POST|PUT|DELETE)", "");
        if (methodAnnotation.isPresent())
        {
            ApiOperation operation = methodAnnotation.get();
            if (MiscUtils.isNotEmpty(operation.nickname()))
            {
                // Populate the value of nickname annotation into uniqueId
                context.operationBuilder().uniqueId(operation.nickname());
                context.operationBuilder().codegenMethodNameStem(operation.nickname());
            }
            else
            {
                context.operationBuilder().uniqueId(uniqueId);
                context.operationBuilder().codegenMethodNameStem(uniqueId);
            }
        }
        else
        {
            context.operationBuilder().uniqueId(uniqueId);
            context.operationBuilder().codegenMethodNameStem(uniqueId);
        }
    }

    @Override
    public boolean supports(DocumentationType delimiter)
    {
        return SwaggerPluginSupport.pluginDoesApply(delimiter);
    }
}

答案 2 :(得分:0)

我们还可以使用昵称的这种方法来覆盖默认的operationId。

@ApiOperation(value = "", nickname = "getMeAllThePetsPlease")
@RequestMapping(value = "/pets", method = RequestMethod.GET)
public Model getAllThePets() {
    ...
}

所以我们将使用 getMeAllThePetsPlease 覆盖 operationId:getAllThePetsByGet

注意:昵称将覆盖operationId,因此可以相应地对其进行自定义。

答案 3 :(得分:0)

基于@bdzzaid的代码的较短和清晰的版本:

MAP_KEY_VALUE

答案 4 :(得分:0)

这不需要额外的依赖,也很容易自定义命名。 (改进here

app/api/src/main/java/com/observatory/api/config/SwaggerIncludeMissingNicknameIntoUniqueIdReader.java


package com.observatory.api.config;

import com.google.common.base.Optional;
import io.swagger.annotations.ApiOperation;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import springfox.documentation.service.Operation;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.OperationBuilderPlugin;
import springfox.documentation.spi.service.contexts.OperationContext;
import springfox.documentation.swagger.common.SwaggerPluginSupport;

import java.util.Locale;

@Component
@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1000)
public class SwaggerIncludeMissingNicknameIntoUniqueIdReader implements OperationBuilderPlugin {

    @Override
    public void apply(OperationContext context) {
        Optional<ApiOperation> methodAnnotation = context.findControllerAnnotation(ApiOperation.class);
        Operation operationBuilder = context.operationBuilder().build();

        String uniqueId = operationBuilder.getUniqueId();
        if(operationBuilder.getTags().stream().findFirst().get().isEmpty())
            throw new RuntimeException("operationBuilder.getTags().stream().findFirst()");
        uniqueId = uniqueId.substring(0,1).toUpperCase(Locale.ROOT)+ uniqueId.substring(1);
        uniqueId = uniqueId.replaceAll("[_].+","");
        String tag = operationBuilder.getTags().stream().findFirst().get();
        tag = tag.replace("-controller","s");
        int index = tag.indexOf("-");
        while (index >= 0) {
            tag = tag.substring(0,index) + tag.substring(index+1,index+2).toUpperCase(Locale.ROOT)+ tag.substring(index+2);
            index = tag.indexOf("-");
        }
        uniqueId = tag + uniqueId;

        // If nickname exists, populate the value of nickname annotation into uniqueId
        String fillId = methodAnnotation.transform(ApiOperation::nickname).or(uniqueId);
        context.operationBuilder().uniqueId(fillId);
        context.operationBuilder().codegenMethodNameStem(fillId);
    }

    @Override
    public boolean supports(DocumentationType delimiter) {
        return SwaggerPluginSupport.pluginDoesApply(delimiter);
    }
}