目前最新的版本不兼容spring boot 3.4.0
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.
https://github.com/xiaoymin/knife4j/issues/865#issuecomment-2497448078
大家可以使用这个替代先 https://github.com/xingfudeshi/knife4j 暂时先用着,解决问题先
<groupId>com.github.xingfudeshi</groupId> <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
4.6.0
计划什么时候能解决和3.4不兼容问题 ?
大家可以使用这个替代先 https://github.com/xingfudeshi/knife4j 暂时先用着,解决问题先
com.github.xingfudeshi knife4j-openapi3-jakarta-spring-boot-starter 4.6.0
强!成功使用!
主要是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
主要是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接口实际上的地址会显示成其他的接口
大家可以使用这个替代先 https://github.com/xingfudeshi/knife4j 暂时先用着,解决问题先
com.github.xingfudeshi knife4j-openapi3-jakarta-spring-boot-starter 4.6.0
为啥我是用这个方案,knife4j里面接口地址都是错误的。
错误
需要关闭增强。
主要是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 都是独一无二的。
SpringBoot Version 3.4.0,使用Knife4j 4.5.0,将配置文件中增强配置改为false,并将springdoc.version升级至2.8.6后即可
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;
};
}
}
@
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; }; } }
用了这个,增强配置还能用吗