【超详细】springboot + springdoc-openapi + knife4j 集成案例

文章介绍了如何使用springdoc-openapi库在SpringBoot项目中自动生成API文档,包括支持的特性、替代已停更的springfox,以及如何集成和配置。此外,还提及了Knife4j作为增强解决方案,并提供了简单的示例代码展示如何用新注解替换旧的Swagger注解。

springdoc-openapi 简介

springdoc-openapijava库有助于使用 spring boot 项目自动生成 API 文档。 springdoc-openapi通过在运行时检查应用程序以根据 spring 配置、类结构和各种注释推断 API 语义来工作。

自动生成 JSON/YAML 和 HTML 格式 API 的文档。可以使用 swagger-api 注释通过注释来完成此文档。

该库支持:

  • OpenAPI3

  • SpringBoot (v1, v2 and v3)

  • JSR-303, specifically for @NotNull, @Min, @Max, and @Size.

  • Swagger-ui

  • OAuth 2

  • GraalVM 原生镜像

为什么使用 springdoc-openapi🤔

由于之前项目一直使用的是springfox3.0来集成swagger管理API接口文档,但目前springfox已经停止维护了。最近在升级底层框架时看到spring官方推荐使用springdoc,在自己一步一步查找相关资料时,发现国内对于这块的参考资料较少,也不全面。故写此篇文章来帮助大家快速集成。

Knife4j简介

Knife4j是一个集Swagger2和OpenAPI3为一体的增强解决方案。

开始集成

Maven引入

首先在maven里引入springdoc-openapi:

<dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-ui</artifactId><version>1.6.15</version></dependency>复制代码

注释的区别

这里需要注意,我们要用swagger3注释替换swagger2注释(它已经包含在springdoc-openapi-ui依赖项中)。swagger 3 注释的包是io.swagger.v3.oas.annotations:

@Api -> @Tag@ApiIgnore -> @Parameter(hidden = true) 或 @Operation(hidden = true) 或 @Hidden@ApiImplicitParam -> @Parameter@ApiImplicitParams -> @Parameters@ApiModel -> @Schema@ApiModelProperty(hidden = true) -> @Schema(accessMode = READ_ONLY)@ApiModelProperty -> @Schema@ApiOperation(value = "foo", notes = "bar") -> @Operation(summary = "foo", description = "bar")@ApiParam -> @Parameter@ApiResponse(code = 404, message = "foo") -> @ApiResponse(responseCode = "404", description = "foo")复制代码

以下举几个简单的🌰:

Controller:

@Tag(name = "用户接口")@RestController@RequestMapping("sys/user")publicclassSysUserController {

    @Resourceprivate ISysUserService sysUserService;

    @Operation(summary = "分页查询")@GetMapping("page")public AjaxResult queryPage(SysUserPageDTO dto) {
        PageInfopage= sysUserService.queryPage(dto);
        return AjaxResult.success(page);
    }

    @Operation(summary = "详情")@GetMapping("{id}")public AjaxResult queryInfo(@PathVariable Long id) {
        SysUserDTOdto= sysUserService.queryById(id);
        return AjaxResult.success(dto);
    }

    @Operation(summary = "新增")@PostMappingpublic AjaxResult save(@RequestBody SysUserDTO dto) {
        Longid= sysUserService.saveInfo(dto);
        return AjaxResult.success(id);
    }
}
复制代码

DTO:

@Schema(description = "用户 数据传输对象")@Data@Accessors(chain = true)publicclassSysUserDTOimplementsSerializable {

    @Schema(description = "ID")private Long id;

    @Schema(description = "用户名")private String userName;

    @Schema(description = "真实姓名")private String realName;

    @Schema(description = "密码")private String password;

    @Schema(description = "性别(0男,1女)")private Integer sex;

    @Schema(description = "电话号码")private String phone;

    @Schema(description = "状态(0停用,1正常)")private Integer status;
}
复制代码

配置

配置文件,更多配置请看:springdoc 核心配置

springdoc:api-docs:# 是否开启接口文档enabled:trueswagger-ui:# 持久化认证数据,如果设置为 true,它会保留授权数据并且不会在浏览器关闭/刷新时丢失persistAuthorization:true复制代码

配置文档:

❗ 这里我更推荐将文档标题、作者等信息写到application里,然后通过@ConfigurationProperties引入,会更优雅😉

@Configuration@AutoConfigureBefore(SpringDocConfiguration.class)publicclassOpenApiConfig {

    privatestaticfinalStringTOKEN_HEADER="Authorization";

    @Beanpublic OpenAPI openApi() {
        // 针对 knife4j(增强UI),这里添加全局请求头(addParameters)无效,只能按组添加,待官方解决returnnewOpenAPI()
                .components(
                        newComponents().addSecuritySchemes(TOKEN_HEADER,
                                newSecurityScheme()
                                        .type(SecurityScheme.Type.APIKEY)
                                        // 这里配置 bearer 后,你的请求里会自动在 token 前加上 Bearer
                                        .scheme("bearer")
                                        .bearerFormat("JWT")
                        ).addParameters(TOKEN_HEADER,
                                newParameter()
                                        .in("header")
                                        .schema(newStringSchema())
                                        .name(tokenHeader)
                        ))
                .info(
                        newInfo()
                                .title("文档标题")
                                .description("文档描述")
                                .contact(newContact().name("作者").email("邮箱").url("可以写你的博客地址或不填"))
                                // 参考 Apache 2.0 许可及地址,你可以不配此项
                                .license(newLicense().name("Apache 2.0").url("https://www.apache.org/licenses/LICENSE-2.0.html"))
                                .version("0.1")
                )
                // 引入外部的文档,我这里引得是 springdoc 官方文档地址,你可以不配此项
                .externalDocs(newExternalDocumentation()
                        .description("SpringDoc Full Documentation")
                        .url("https://springdoc.org/")
                );
    }

    /**
     * GroupedOpenApi 是对接口文档分组,类似于 swagger 的 Docket
     * 
     * @return
     */@Beanpublic GroupedOpenApi authApi() {
        return GroupedOpenApi.builder()
                // 组名
                .group("认证接口")
                // 扫描的路径,支持通配符
                .pathsToMatch("/login")
                // 扫描的包
                .packagesToScan("com.demo.controller.auth")
                .build();
    }
    
    @Beanpublic GroupedOpenApi sysApi() {
        return GroupedOpenApi.builder()
                .group("系统接口")
                .pathsToMatch("/sys/**")
                // 添加自定义配置,这里添加了一个用户认证的 header,否则 knife4j 里会没有 header
                .addOperationCustomizer((operation, handlerMethod) -> operation.security(
                        Collections.singletonList(newSecurityRequirement().addList(TOKEN_HEADER)))
                )
                .build();
    }
}
复制代码

访问文档

配置完成之后,就可以访问文档地址:http://localhost:${port}/${context-path}/swagger-ui/html.index

❗ 如果你加入了拦截器或引入了spring-security等权限框架,需要放通文档地址及静态资源:

- /**/*.html
- /**/*.css
- /**/*.js
- /**/api-docs/**
复制代码

至此一个简单的接口文档就生成了,是不是很简单😎

集成knife4j

Maven引入

在maven里引入knife4j

<dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi3-spring-boot-starter</artifactId><version>4.0.0</version></dependency>复制代码

❗ 如果你使用的是SpringBoot3,需要注意:

  • Spring Boot 3 只支持OpenAPI3规范

  • Knife4j提供的starter已经引用springdoc-openapi的jar,开发者需注意避免jar包冲突

  • JDK版本必须 >= 17

而且需要引入这个包:

<dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId><version>4.0.0</version></dependency>复制代码

访问文档地址

然后你就可以直接访问文档地址了:http://localhost:${port}/${context-path}/doc.html

至此我们就集成完了,有其他疑问欢迎在评论区提出来😊

作者:penga

链接:https://juejin.cn/post/7214015651828006967

<think>我们遇到了一个Java运行时错误:`java.lang.NoSuchMethodError: &#39;java.util.List org.springdoc.core.prop...`。这个错误通常发生在编译时使用的库版本与运行时实际加载的库版本不一致,导致在运行时找不到特定的方法。 根据你提供的依赖信息: - `knife4j-openapi3-jakarta-spring-boot-starter` 版本 `4.5.0` - Spring Boot 版本 `3.4.0` - `springdoc-openapi-starter-webmvc-ui` 版本 `2.8.9` 这个错误可能是因为`knife4j`和`springdoc-openapi`之间的版本不兼容导致的。`knife4j`在底层依赖于`springdoc-openapi`,因此需要确保两者的版本是兼容的。 ### 错误分析 `NoSuchMethodError`通常表示在类路径上找到了一个类,但是这个类不包含我们在编译时使用的方法。这可能是由于: 1. 依赖冲突:项目中有多个版本的同一个库,类加载器加载了错误的版本。 2. 版本不兼容:我们使用的库版本之间存在不兼容问题。 ### 解决方案 1. **检查依赖树,排除冲突版本**:我们可以使用Maven或Gradle的依赖树命令来查看是否存在多个版本的`springdoc-openapi`相关库,并排除掉冲突的版本。 2. **确保版本兼容**:查阅`knife4j`的官方文档,确认版本`4.5.0`与`springdoc-openapi`版本`2.8.9`是否兼容。如果不兼容,需要调整版本。 根据经验,`knife4j-openapi3-jakarta-spring-boot-starter` 4.5.0 应该与`springdoc-openapi`的版本有明确的对应关系。我们可以查看`knife4j`的官方文档或GitHub仓库的README来确定兼容的`springdoc`版本。 ### 步骤 #### 1. 使用Maven排除冲突(如果使用Maven) 在`pom.xml`中,我们可以这样排除传递依赖: ```xml <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId> <version>4.5.0</version> <exclusions> <exclusion> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> </exclusion> <!-- 可能还需要排除其他相关依赖 --> </exclusions> </dependency> ``` 然后,我们显式引入兼容的`springdoc-openapi`版本。但是,请注意,`knife4j`可能对`springdoc`有特定版本要求,所以最好按照`knife4j`推荐的版本引入。 #### 2. 调整版本 根据`knife4j`的[官方文档](https://doc.xiaominfo.com/knife4j/documentation/),我们找到与`knife4j`4.5.0兼容的`springdoc`版本。 在`knife4j`的[Github Release](https://github.com/xiaoymin/knife4j/releases)页面,我们可以看到版本4.5.0的发布信息,其中提到: > 基于springdoc-openapi v2.2.0版本适配 但是,我们使用的`springdoc-openapi`版本是2.8.9,这显然高于2.2.0,可能存在不兼容。 因此,我们需要将`springdoc-openapi`降级到与`knife4j`兼容的版本。根据上述信息,应该是2.2.0。但请注意,我们使用的Spring Boot3.4.0,所以也要确保`springdoc`版本支持Spring Boot 3.4.0。 实际上,`springdoc-openapi`的2.2.0版本发布于2023年,而Spring Boot 3.4.0是较新的版本,可能不被2.2.0支持。因此,我们需要寻找一个折中方案。 ### 推荐做法 1. **升级`knife4j`版本**:查看是否有更新的`knife4j`版本支持更高版本的`springdoc`。目前(2025年)`knife4j`的最新版本是多少?你可能需要查看官网。 2. **使用与`springdoc`2.8.9兼容的`knife4j`版本**:如果无法升级`knife4j`,则可能需要降低`springdoc`的版本,但这可能会影响其他功能。 ### 实际验证 在`knife4j`的官方文档中,4.5.0版本对应的`springdoc`版本是2.2.0,但Spring Boot 3.4.0需要较高版本的`springdoc`(至少2.3.0以上)。所以,我们可能需要升级`knife4j`到支持更高`springdoc`的版本。 在`knife4j`的GitHub上,我们可以在[Issues](https://github.com/xiaoymin/knife4j/issues)中搜索相关兼容性问题。或者查看[Release](https://github.com/xiaoymin/knife4j/releases)页面。 目前,`knife4j`的最新版本是`4.5.0`(截至2024年3月),但是有更高版本如`4.6.0`(如果发布的话)。如果没有,那么可能需要等待更新。 ### 临时解决方案 如果你必须使用Spring Boot 3.4.0和`springdoc`2.8.9,那么可以尝试不使用`knife4j`的starter,而是单独引入`knife4j`的UI包,并手动配置,避开版本冲突。 但是,这可能需要更多的手动配置,并且不一定能成功。 ### 总结建议 1. 降低`springdoc-openapi`版本至与`knife4j`兼容的版本(如2.2.0),并测试是否支持Spring Boot 3.4.0。 2. 或者,寻找支持`springdoc`2.8.9的`knife4j`版本(可能需要升级`knife4j`到更新版本,例如4.6.0+,如果存在的话)。 ### 检查依赖树 使用Maven命令: ```bash mvn dependency:tree ``` 查看`org.springdoc`相关的依赖版本,确认是否有多个版本冲突。 ### 示例排除依赖 在Maven中排除`knife4j`带来的`springdoc`依赖,然后显式引入需要的版本: ```xml <dependencies> <!-- Knife4j --> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId> <version>4.5.0</version> <exclusions> <exclusion> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-starter-common</artifactId> </exclusion> <exclusion> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-starter-webmvc-api</artifactId> </exclusion> <!-- 排除所有springdoc的传递依赖 --> </exclusions> </dependency> <!-- 显式引入springdoc-openapi --> <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> <version>2.8.9</version> </dependency> </dependencies> ``` 但是,这样做可能会导致`knife4j`因为缺少它预期的`springdoc`版本而无法正常工作。 ### 最终建议 由于版本兼容性问题,最稳妥的方式是使用`knife4j`官方推荐的`springdoc`版本。因此,建议将`springdoc-openapi`降级到2.2.0版本,并测试是否与Spring Boot 3.4.0兼容。 如果降级`springdoc`后出现其他问题,那么可能需要等待`knife4j`更新版本。 另外,也可以考虑使用`springdoc`自带的Swagger UI,而不使用`knife4j`,因为`springdoc`自带的UI已经足够好。 ### 相关错误示例 在项目中,我们可能会遇到类似如下错误: ``` java.lang.NoSuchMethodError: &#39;java.util.List org.springdoc.core.properties.SpringDocConfigProperties.getDefaultProduces()&#39; ``` 这是因为在`SpringDocConfigProperties`类中,高版本(如2.8.9)可能有不同的方法签名,而`knife4j`4.5.0编译时使用的是低版本(如2.2.0)的方法。 ### 结论 由于时间关系,这里不提供具体代码,因为这是一个依赖管理问题,而不是代码逻辑问题。请按照上述步骤调整依赖版本。 最后,为了预防此类问题,建议使用Maven的`dependencyManagement`或Gradle的`platform`来统一管理依赖版本。 ### 相关问题 §§相关问题§§: 1. 如何解决Java中的NoSuchMethodError错误? 2. Maven中如何排除依赖的传递性? 3. 如何查看Maven项目的依赖树? 4. 在Spring Boot项目中如何集成Knife4j? </think>### 问题分析 您遇到的 `java.lang.NoSuchMethodError` 错误通常是由于依赖版本冲突导致的。具体来说,`knife4j-openapi3-jakarta-spring-boot-starter 4.5.0` 和 `springdoc-openapi-starter-webmvc-ui 2.8.9` 存在兼容性问题。Knife4J 4.5.0 是为 SpringDoc 1.x 设计的,而您使用的 SpringDoc 2.8.9 属于 2.x 系列,两者存在 API 差异。 ### 解决方案 #### 方案 1:升级 Knife4J(推荐) 使用兼容 SpringDoc 2.x 的 Knife4J 版本(4.5.0 不支持 SpringDoc 2.x)。修改 Maven 依赖: ```xml <!-- pom.xml --> <dependencies> <!-- 移除旧版 --> <!-- <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId> <version>4.5.0</version> </dependency> --> <!-- 改用新版 --> <dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId> <version>4.5.1</version> <!-- 支持 SpringDoc 2.x --> </dependency> <!-- SpringDoc 保持不变 --> <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> <version>2.8.9</version> </dependency> </dependencies> ``` #### 方案 2:降级 SpringDoc 如果必须使用 Knife4J 4.5.0,需降级 SpringDoc 到兼容版本(不推荐,可能影响 Spring Boot 3.4 兼容性): ```xml <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId> <version>1.7.0</version> <!-- 兼容 Knife4J 4.5.0 的版本 --> </dependency> ``` ### 配置示例 确保正确配置 OpenAPIKnife4J: ```java // OpenAPI 配置类 @Configuration public class OpenApiConfig { @Bean public OpenAPI customOpenAPI() { return new OpenAPI() .info(new Info() .title("API Documentation") .version("1.0") .description("Spring Boot 3 + OpenAPI")); } } ``` ```java // Knife4J 配置(自动生效,无需额外配置) @EnableKnife4j // 仅需添加此注解 @SpringBootApplication public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` ### 验证步骤 1. 访问 Swagger UI:`http://localhost:8080/swagger-ui.html` 2. 访问 Knife4J 增强 UI:`http://localhost:8080/doc.html` ### 错误原因详解 - `NoSuchMethodError` 表明 JVM 在运行时找不到编译时存在的方法。 - 根本原因:Knife4J 4.5.0 调用 `org.springdoc.core.properties.SpringDocConfigProperties.getDefaultProduces()` 方法,但该方法在 SpringDoc 2.8.9 中已被移除或重构。 - 版本兼容矩阵: | 组件 | 兼容 SpringDoc 1.x | 兼容 SpringDoc 2.x | |---------------------|---------------------|---------------------| | Knife4J ≤ 4.5.0 | ✅ | ❌ | | Knife4J ≥ 4.5.1 | ❌ | ✅ | | SpringDoc 1.x | ✅ | ❌ | | SpringDoc 2.x | ❌ | ✅ |
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值