14

我已经使用 springfox 2.0 配置了我的 spring 项目。我能够用它生成开放的 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

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

4

6 回答 6

10

我们也可以使用 Nickname 的这种方法来覆盖默认的 operationId。

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

所以我们将覆盖operationId: getAllThePetsByGetgetMeAllThePetsPlease

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

于 2019-11-26T06:25:15.773 回答
6

您可以创建自己的插件来做到这一点。这是我们如何在 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不是唯一的,它将生成一个唯一的 idgetCustomer_1等。

于 2016-08-08T11:25:32.357 回答
5

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

@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().replaceAll("Using(GET|POST|PUT|DELETE)", "");

        // 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);
    }
}
于 2020-06-22T09:19:16.367 回答
3

最简单的选择是实现您自己的名称生成器,扩展 Springfox 的名称生成器,如下所示:

public class SwaggerOperationIdTrimmer implements OperationNameGenerator {

private static final String DEFAULT_SPRINGFOX_PATTERN_REGEX = "Using(GET|POST|PUT|DELETE)(_[0-9])?";

@Override
public String startingWith(String operationId) {
    //Trimming of default names generated by Springfox, eliminating the extra appended information
    return operationId.replaceAll(DEFAULT_SPRINGFOX_PATTERN_REGEX, "");
}

}

正则表达式是这里的关键:)

唯一剩下的就是在你的配置文件中将它实例化为一个 bean,将它添加为主要的以覆盖CachingOperationNameGeneratorSpringfox 的默认值:

@Bean
@Primary
public SwaggerOperationIdTrimmer customOperationNameGenerator() {
    return new SwaggerOperationIdTrimmer();
}
于 2022-01-14T10:34:33.097 回答
0

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

它适用于:

  • 春季版 5.1.9.RELEASE
  • 春狐 2.9.2
  • 招摇版本 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);
    }
}
于 2019-11-20T13:19:42.160 回答
0

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

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);
    }
}
于 2021-03-31T07:10:03.057 回答