knife4j icon indicating copy to clipboard operation
knife4j copied to clipboard

目前最新的版本不兼容spring boot 3.4.0

Open jasonjensenlyg opened this issue 1 year ago • 12 comments

Is your feature request related to a problem? Please describe. A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

Describe the solution you'd like A clear and concise description of what you want to happen.

Describe alternatives you've considered A clear and concise description of any alternative solutions or features you've considered.

Additional context Add any other context or screenshots about the feature request here.

jasonjensenlyg avatar Dec 12 '24 09:12 jasonjensenlyg

https://github.com/xiaoymin/knife4j/issues/865#issuecomment-2497448078

DubheAlkaid avatar Dec 12 '24 09:12 DubheAlkaid

大家可以使用这个替代先 https://github.com/xingfudeshi/knife4j 暂时先用着,解决问题先

<groupId>com.github.xingfudeshi</groupId> <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId> 4.6.0

zxhans avatar Dec 16 '24 01:12 zxhans

计划什么时候能解决和3.4不兼容问题 ?

98549844 avatar Dec 18 '24 06:12 98549844

大家可以使用这个替代先 https://github.com/xingfudeshi/knife4j 暂时先用着,解决问题先

com.github.xingfudeshi knife4j-openapi3-jakarta-spring-boot-starter 4.6.0

强!成功使用!

YunaiV avatar Dec 28 '24 04:12 YunaiV

主要是openapi和controllerAdvice的冲突, springdoc-openapi v2.7.0在Nov 24, 2024宣布支持Springboot 3.4.0 。 更新日志如下 https://github.com/springdoc/springdoc-openapi/releases/tag/v2.7.0

在pom中如下使用,即可。

        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
            <version>4.5.0</version>
        </dependency>
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
            <version>2.7.0</version>
        </dependency>

但是要关闭增强功能。

knife4j:
  enable: false

Xiamu-ssr avatar Jan 03 '25 02:01 Xiamu-ssr

主要是openapi和controllerAdvice的冲突, springdoc-openapi v2.7.0在Nov 24, 2024宣布支持Springboot 3.4.0 。 更新日志如下 https://github.com/springdoc/springdoc-openapi/releases/tag/v2.7.0

在pom中如下使用,即可。

    <dependency>
        <groupId>com.github.xiaoymin</groupId>
        <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
        <version>4.5.0</version>
    </dependency>
    <dependency>
        <groupId>org.springdoc</groupId>
        <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
        <version>2.7.0</version>
    </dependency>

但是要关闭增强功能。

knife4j: enable: false

使用了你这个方法后会有问题,springboot3.4.0及以后,knife4j中的文档内容会错乱,例:erp/stock/list 原本在erp分组模块下,但是该模块下的这个list接口实际上的地址会显示成其他的接口

Loren1999 avatar Jan 22 '25 07:01 Loren1999

大家可以使用这个替代先 https://github.com/xingfudeshi/knife4j 暂时先用着,解决问题先

com.github.xingfudeshi knife4j-openapi3-jakarta-spring-boot-starter 4.6.0

为啥我是用这个方案,knife4j里面接口地址都是错误的。

nanxiangquan avatar Feb 11 '25 07:02 nanxiangquan

错误

需要关闭增强。

nanxiangquan avatar Feb 11 '25 07:02 nanxiangquan

主要是openapi和controllerAdvice的冲突, springdoc-openapi v2.7.0在Nov 24, 2024宣布支持Springboot 3.4.0 。 更新日志如下 https://github.com/springdoc/springdoc-openapi/releases/tag/v2.7.0 在pom中如下使用,即可。

    <dependency>
        <groupId>com.github.xiaoymin</groupId>
        <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
        <version>4.5.0</version>
    </dependency>
    <dependency>
        <groupId>org.springdoc</groupId>
        <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
        <version>2.7.0</version>
    </dependency>

但是要关闭增强功能。 knife4j: enable: false

使用了你这个方法后会有问题,springboot3.4.0及以后,knife4j中的文档内容会错乱,例:erp/stock/list 原本在erp分组模块下,但是该模块下的这个list接口实际上的地址会显示成其他的接口

借助 SpringDoc 的扩展机制,自定义 OperationIdResolver 来生成唯一的 operationId。这样可以根据自身需求灵活定制生成规则,避免 operationId 重复。

@Configuration public class CustomOperationIdConfig {

@Bean
public OperationCustomizer customOperationIdResolver() {
    return (Operation operation, HandlerMethod handlerMethod) -> {
        // 根据类名、方法名和 UUID 生成唯一的 operationId
        String className = handlerMethod.getBeanType().getSimpleName();
        String methodName = handlerMethod.getMethod().getName();
        String uniqueId = UUID.randomUUID().toString().substring(0, 8);
        String operationId = className + "_" + methodName + "_" + uniqueId;
        operation.setOperationId(operationId);
        return operation;
    };
}

} 通过组合类名、方法名和一个短的 UUID 来生成唯一的 operationId,确保每个操作的 operationId 都是独一无二的。

zzhangzd avatar Mar 18 '25 08:03 zzhangzd

SpringBoot Version 3.4.0,使用Knife4j 4.5.0,将配置文件中增强配置改为false,并将springdoc.version升级至2.8.6后即可

Image

Image

Image

Loren1999 avatar Mar 27 '25 08:03 Loren1999

operationId

不错的提议,不过这个使用UUID 在容器化就会出现不一致的问题

package com.ocboot.config.swagger;

import com.github.xingfudeshi.knife4j.annotations.ApiOperationSupport;
import com.github.xingfudeshi.knife4j.annotations.ApiSupport;
import com.github.xingfudeshi.knife4j.core.conf.ExtensionsConstants;
import com.github.xingfudeshi.knife4j.core.util.StrUtil;
import com.github.xingfudeshi.knife4j.extend.util.ExtensionUtils;
import com.google.common.hash.Hashing;
import io.swagger.v3.oas.models.Operation;
import org.springdoc.core.customizers.GlobalOperationCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.web.method.HandlerMethod;

import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;

/**
 * @author Mejituu
 */
@Configuration
public class CustomOperationIdConfig {
    @Bean
    public GlobalOperationCustomizer customOperationIdResolver() {
        return (Operation operation, HandlerMethod handlerMethod) -> {
            // 根据类名、方法名和 UUID 生成唯一的 operationId
            Class<?> beanType = handlerMethod.getBeanType();
            Method method = handlerMethod.getMethod();
            operation.setOperationId(Hashing.murmur3_128()
                .hashString(beanType.getName(),
                    StandardCharsets.UTF_8) + "p" + beanType.getSimpleName() + "h" + method.getName());
            // 解析支持作者、接口排序
            ApiOperationSupport operationSupport = AnnotationUtils.findAnnotation(method, ApiOperationSupport.class);
            if (operationSupport != null) {
                String author = ExtensionUtils.getAuthors(operationSupport);
                if (StrUtil.isNotBlank(author)) {
                    operation.addExtension(ExtensionsConstants.EXTENSION_AUTHOR, author);
                }
                if (operationSupport.order() != 0) {
                    operation.addExtension(ExtensionsConstants.EXTENSION_ORDER, operationSupport.order());
                }
            } else {
                // 如果方法级别不存在,再找一次class级别的
                ApiSupport apiSupport = AnnotationUtils.findAnnotation(beanType, ApiSupport.class);
                if (apiSupport != null) {
                    String author = ExtensionUtils.getAuthor(apiSupport);
                    if (StrUtil.isNotBlank(author)) {
                        operation.addExtension(ExtensionsConstants.EXTENSION_AUTHOR, author);
                    }
                    if (apiSupport.order() != 0) {
                        operation.addExtension(ExtensionsConstants.EXTENSION_ORDER, apiSupport.order());
                    }
                }
            }
            return operation;
        };
    }
}

Mejituu avatar Jul 06 '25 18:07 Mejituu

@

operationId

不错的提议,不过这个使用UUID 在容器化就会出现不一致的问题

package com.ocboot.config.swagger;

import com.github.xingfudeshi.knife4j.annotations.ApiOperationSupport; import com.github.xingfudeshi.knife4j.annotations.ApiSupport; import com.github.xingfudeshi.knife4j.core.conf.ExtensionsConstants; import com.github.xingfudeshi.knife4j.core.util.StrUtil; import com.github.xingfudeshi.knife4j.extend.util.ExtensionUtils; import com.google.common.hash.Hashing; import io.swagger.v3.oas.models.Operation; import org.springdoc.core.customizers.GlobalOperationCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.AnnotationUtils; import org.springframework.web.method.HandlerMethod;

import java.lang.reflect.Method; import java.nio.charset.StandardCharsets;

/**

  • @author Mejituu */ @Configuration public class CustomOperationIdConfig { @Bean public GlobalOperationCustomizer customOperationIdResolver() { return (Operation operation, HandlerMethod handlerMethod) -> { // 根据类名、方法名和 UUID 生成唯一的 operationId Class<?> beanType = handlerMethod.getBeanType(); Method method = handlerMethod.getMethod(); operation.setOperationId(Hashing.murmur3_128() .hashString(beanType.getName(), StandardCharsets.UTF_8) + "p" + beanType.getSimpleName() + "h" + method.getName()); // 解析支持作者、接口排序 ApiOperationSupport operationSupport = AnnotationUtils.findAnnotation(method, ApiOperationSupport.class); if (operationSupport != null) { String author = ExtensionUtils.getAuthors(operationSupport); if (StrUtil.isNotBlank(author)) { operation.addExtension(ExtensionsConstants.EXTENSION_AUTHOR, author); } if (operationSupport.order() != 0) { operation.addExtension(ExtensionsConstants.EXTENSION_ORDER, operationSupport.order()); } } else { // 如果方法级别不存在,再找一次class级别的 ApiSupport apiSupport = AnnotationUtils.findAnnotation(beanType, ApiSupport.class); if (apiSupport != null) { String author = ExtensionUtils.getAuthor(apiSupport); if (StrUtil.isNotBlank(author)) { operation.addExtension(ExtensionsConstants.EXTENSION_AUTHOR, author); } if (apiSupport.order() != 0) { operation.addExtension(ExtensionsConstants.EXTENSION_ORDER, apiSupport.order()); } } } return operation; }; } }

用了这个,增强配置还能用吗

catch6 avatar Jul 16 '25 06:07 catch6