diff --git a/src/main/java/com/ly/doc/builder/openapi/OpenApiBuilder.java b/src/main/java/com/ly/doc/builder/openapi/OpenApiBuilder.java index 33a83bd0..4fd5bf62 100644 --- a/src/main/java/com/ly/doc/builder/openapi/OpenApiBuilder.java +++ b/src/main/java/com/ly/doc/builder/openapi/OpenApiBuilder.java @@ -25,6 +25,7 @@ import com.ly.doc.constants.DocGlobalConstants; import com.ly.doc.constants.Methods; import com.ly.doc.constants.OpenApiTagNameTypeEnum; +import com.ly.doc.constants.OperationIdStrategyEnum; import com.ly.doc.constants.ParamTypeConstants; import com.ly.doc.helper.JavaProjectBuilderHelper; import com.ly.doc.model.ApiConfig; @@ -178,17 +179,36 @@ public Map buildPathUrlsRequest(ApiConfig apiConfig, ApiMethodDo List paths = OpenApiSchemaUtil.getPatternResult("[A-Za-z0-9_{}]*", apiMethodDoc.getPath()); paths.add(apiMethodDoc.getType()); - // add operationId - String methodName = apiMethodDoc.getMethodName(); - if (OPERATIONID_ORDER_NO_MAP.containsKey(methodName)) { - int order = OPERATIONID_ORDER_NO_MAP.get(methodName); - request.put("operationId", methodName + "_" + order); - OPERATIONID_ORDER_NO_MAP.put(methodName, order + 1); - } - else { - request.put("operationId", methodName); - OPERATIONID_ORDER_NO_MAP.put(methodName, 1); + // add operationId based on configured strategy + OperationIdStrategyEnum strategy = apiConfig.getOperationIdStrategy(); + String operationId; + switch (strategy) { + case METHOD_ID: + // Use methodId (MD5 hash) + operationId = apiMethodDoc.getMethodId(); + break; + case PATH_METHOD_HTTP: + // Use path + method name + HTTP method type + List pathSegments = OpenApiSchemaUtil.getPatternResult("[A-Za-z0-9_]*", apiMethodDoc.getPath()); + operationId = String.join("-", pathSegments) + "-" + apiMethodDoc.getMethodName() + "-" + + apiMethodDoc.getType(); + break; + case METHOD_NAME: + default: + // Use method name only (with duplicate handling) + String methodName = apiMethodDoc.getMethodName(); + if (OPERATIONID_ORDER_NO_MAP.containsKey(methodName)) { + int order = OPERATIONID_ORDER_NO_MAP.get(methodName); + operationId = methodName + "_" + order; + OPERATIONID_ORDER_NO_MAP.put(methodName, order + 1); + } + else { + operationId = methodName; + OPERATIONID_ORDER_NO_MAP.put(methodName, 1); + } + break; } + request.put("operationId", operationId); // add extension attribution if (apiMethodDoc.getExtensions() != null) { diff --git a/src/main/java/com/ly/doc/constants/OperationIdStrategyEnum.java b/src/main/java/com/ly/doc/constants/OperationIdStrategyEnum.java new file mode 100644 index 00000000..07e07b85 --- /dev/null +++ b/src/main/java/com/ly/doc/constants/OperationIdStrategyEnum.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2018-2025 smart-doc + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package com.ly.doc.constants; + +/** + * Enum representing the possible strategies for generating operationId in OpenAPI + * specifications. Each enum value defines a strategy for determining the value of + * `operationId` in the OpenAPI document. + * + *

+ * Supported strategies include: + *

    + *
  • Using the method name only
  • + *
  • Using the methodId (MD5 hash)
  • + *
  • Using path + method name + HTTP method type
  • + *
+ * + * @author smart-doc + * @version 3.1.2 + */ +public enum OperationIdStrategyEnum { + + /** + * Use the method name only as the operationId. + *

+ * This is the default strategy. The operationId will be the Java method name. + * If there are duplicate method names, a numeric suffix will be added. + *

+ *

+ * Example: {@code getUserInfo} or {@code getUserInfo_1} for duplicates + *

+ */ + METHOD_NAME, + + /** + * Use the methodId (MD5 hash) as the operationId. + *

+ * The methodId is generated as an MD5 hash based on the class name, method name, and order. + * This ensures unique operationIds across the entire API. + *

+ *

+ * Example: {@code user-controller-getUserInfo-1-a1b2c3d4e5f6} + *

+ */ + METHOD_ID, + + /** + * Use path + method name + HTTP method type as the operationId. + *

+ * This strategy combines URL path segments (excluding path variables), the method name, + * and the HTTP method type to create a descriptive operationId. + *

+ *

+ * Example: For a POST request to {@code /api/users/profile} with method {@code updateProfile}, + * the operationId will be {@code api-users-updateProfile-POST} + *

+ */ + PATH_METHOD_HTTP; + +} diff --git a/src/main/java/com/ly/doc/model/ApiConfig.java b/src/main/java/com/ly/doc/model/ApiConfig.java index 5946189a..913737a7 100644 --- a/src/main/java/com/ly/doc/model/ApiConfig.java +++ b/src/main/java/com/ly/doc/model/ApiConfig.java @@ -24,6 +24,7 @@ import com.ly.doc.constants.ComponentTypeEnum; import com.ly.doc.constants.DocLanguage; import com.ly.doc.constants.OpenApiTagNameTypeEnum; +import com.ly.doc.constants.OperationIdStrategyEnum; import com.ly.doc.handler.ICustomJavaMethodHandler; import com.ly.doc.model.jmeter.JMeter; import com.ly.doc.model.rpc.RpcApiDependency; @@ -503,6 +504,31 @@ public class ApiConfig { */ private boolean allowSelfReference = Boolean.FALSE; + /** + * Strategy for generating OpenAPI operationId. + *

+ * This field specifies how the operationId in the generated OpenAPI document is + * determined. Supported strategies include: + *

+ * + *
    + *
  • {@link OperationIdStrategyEnum#METHOD_NAME}: Use the method name only + * (with numeric suffix for duplicates)
  • + *
  • {@link OperationIdStrategyEnum#METHOD_ID}: Use the methodId (MD5 hash)
  • + *
  • {@link OperationIdStrategyEnum#PATH_METHOD_HTTP}: Use path + method name + + * HTTP method type
  • + *
+ * + *

+ * This setting affects how API operations are identified in the OpenAPI documentation. + * Choose the strategy that best aligns with your API naming conventions. + *

+ * + * @see OperationIdStrategyEnum + * @since 3.1.2 + */ + private OperationIdStrategyEnum operationIdStrategy = OperationIdStrategyEnum.METHOD_NAME; + public static ApiConfig getInstance() { return instance; } @@ -1212,4 +1238,16 @@ public ApiConfig setOpenApiTagNameType(OpenApiTagNameTypeEnum openApiTagNameType return this; } + public OperationIdStrategyEnum getOperationIdStrategy() { + if (Objects.isNull(operationIdStrategy)) { + return OperationIdStrategyEnum.METHOD_NAME; + } + return operationIdStrategy; + } + + public ApiConfig setOperationIdStrategy(OperationIdStrategyEnum operationIdStrategy) { + this.operationIdStrategy = operationIdStrategy; + return this; + } + }