Springboot 2.7 集成 Swagger 增强版接口框架 Knife4j 4.3 + springdoc OpenApi 3.0

这篇具有很好参考价值的文章主要介绍了Springboot 2.7 集成 Swagger 增强版接口框架 Knife4j 4.3 + springdoc OpenApi 3.0。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1 摘要

Swagger 作为一款服务端接口文档自动生成框架,早已深入人心,并且在市场上得到了广泛的应用。然而,Swagger 3.0 也就是 OpenApi 3.0 规范发布之后便停止了更新维护,出道就是巅峰。Knife4j 作为 Swagger 的增强版,是对 Swagger UI 做了优化,同时还有很多增强的功能。伴随着 Swagger 3.0 的停止更新,如今 Knife4j 从4.0开始已经逐渐使用 Springdoc 作为 swagger 的替代。Springdoc 针对 OpenApi 3.0 的适配做了较大的调整,其中注解与 Swagger 2 的基本不通用。作为新项目而言,使用社区维护活跃的开源框架显得非常重要。本文将介绍基于 Springboot 2.7 集成 Swagger 的增强框架 Knife4j 4.3 + Springdoc OpenApi 3.0 。

Knife4j 官方文档: https://doc.xiaominfo.com/docs/quick-start

Springdoc 官方文档: https://springdoc.org

2 核心 Maven 依赖

demo-knife4j-openapi3/pom.xml
        <!-- knife4j openapi3 接口文档 -->
        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
            <version>${knife4j-openapi3-spring.version}</version>
        </dependency>

版本信息

<knife4j-openapi3-spring.version>4.3.0</knife4j-openapi3-spring.version>

注意事项:

本示例中使用的是 Springboot 2.7 版本,如果是 sprigboot 3.0 + 版本,则对应的 maven 依赖为:

<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
    <version>4.3.0</version>
</dependency>

3 核心代码

3.1 application 配置

demo-knife4j-openapi3/src/main/resources/application.yml

springdoc 相关配置:

# spring-doc 接口文档
springdoc:
  api-docs:
    enabled: true # 是否启用接口文档
knife4j:
  enable: true # 是否启用 knife4j 增强,如果只是使用 knife4j 的 UI,则可以关闭

3.2 openApi 配置类

demo-knife4j-openapi3/src/main/java/com/ljq/demo/springboot/knife4j/common/config/OpenApiConfig.java
package com.ljq.demo.springboot.knife4j.common.config;

import io.swagger.v3.oas.models.ExternalDocumentation;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Description: openapi 界面配置
 * @Author: junqiang.lu
 * @Date: 2023/8/15
 */
@Configuration
public class OpenApiConfig {

    @Bean
    public OpenAPI springShopOpenAPI() {
        return new OpenAPI()
                // 接口文档标题
                .info(new Info().title("Knife4j OpenApi 3")
                        // 接口文档描述
                        .description("Knife4j OpenApi 3 example application")
                        // 接口文档版本
                        .version("v1.0")
                        // 开发者联系方式
                        .contact(new Contact().name("Flying9001").url("https://github.com/Flying9001")))
                .externalDocs(new ExternalDocumentation()
                        // 额外补充说明
                        .description("Github example code")
                        // 额外补充链接
                        .url("https://github.com/Flying9001/springBootDemo/demo-knife4j-openapi3"));
    }

    
}

3.3 POJO 类使用示例

3.3.1 实体类
demo-knife4j-openapi3/src/main/java/com/ljq/demo/springboot/knife4j/model/entity/UserPushTypeEntity.java
package com.ljq.demo.springboot.knife4j.model.entity;

import com.baomidou.mybatisplus.annotation.TableName;
import com.ljq.demo.springboot.knife4j.model.BaseEntity;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.ToString;

/**
 * 用户消息推送方式实体类
 *
 * @author junqiang.lu
 * @date 2023-08-15 14:26:38
 */
@Data
@ToString(callSuper = true)
@Schema(description = "用户消息推送方式")
@TableName(value = "user_push_type")
public class UserPushTypeEntity extends BaseEntity {

	private static final long serialVersionUID = 1L;

	@Schema(description = "用户id")
	private Long userId;

	@Schema(description = "推送方式,1-短信;2-邮件;3-app;4-wechat")
	private Integer pushType;

	@Schema(description = "通知推送接收地址")
	private String receiveAddress;

	@Schema(description = "是否启用,0-未启用,1-启用")
	private Integer enable;

}

原来 Swagger 2 的 @Apimodel 以及 @ApiModelPropertity 注解全部使用 @Schema 注解代替

3.3.2 请求参数
demo-knife4j-openapi3/src/main/java/com/ljq/demo/springboot/knife4j/model/param/userpushtype/UserPushTypeSaveParam.java
package com.ljq.demo.springboot.knife4j.model.param.userpushtype;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;

/**
 * 用户消息推送方式参数接收类
 *
 * @author junqiang.lu
 * @date 2023-08-14 17:17:19
 */
@Data
@Schema(description = "用户消息推送方式保存(单条)")
public class UserPushTypeSaveParam implements Serializable {

    private static final long serialVersionUID = 1L;



    @NotNull(message = "用户id 不能为空")
    @Schema(description = "用户id", requiredMode = Schema.RequiredMode.REQUIRED)
    private Long userId;

    @NotNull(message = "推送方式不能为空")
    @Schema(description = "推送方式,1-短信;2-邮件;3-app;4-wechat", requiredMode = Schema.RequiredMode.REQUIRED)
    private Integer pushType;

    @NotBlank(message = "通知推送接收地址 不能为空")
    @Schema(description = "通知推送接收地址", requiredMode = Schema.RequiredMode.REQUIRED)
    private String receiveAddress;

    @NotNull(message = "是否启用不能为空")
    @Schema(description = "是否启用,0-未启用,1-启用", requiredMode = Schema.RequiredMode.REQUIRED)
    private Integer enable;


}

@Schema 注解中参数是否必填使用了一个枚举类 io.swagger.v3.oas.annotations.media.Schema.RequiredMode 这是 @Schema 注解的一个内部类,支持 3 种模式, @Schema 注解中多种属性也采用了枚举类的方式,这是与原来的 @ApiModelPropertity 注解区别比较大的地方。

3.3.3 公共返回参数(包含泛型)
demo-knife4j-openapi3/src/main/java/com/ljq/demo/springboot/knife4j/common/api/ApiResult.java
package com.ljq.demo.springboot.knife4j.common.api;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.slf4j.MDC;

import java.util.Map;

/**
 * @Description: 接口返回结果
 * @Author: junqiang.lu
 * @Date: 2020/9/3
 */
@Data
public class ApiResult<T> {

    /**
     * 默认成功结果 key
     */
    public static final String DEFAULT_SUCCESS_KEY = "api.response.success";
    /**
     * 默认成功返回提示信息
     */
    public static final String DEFAULT_SUCCESS_MESSAGE = "SUCCESS";
    /**
     * 默认错误结果 key
     */
    public static final String DEFAULT_ERROR_KEY = "api.response.error";
    /**
     * 默认错误返回提示信息
     */
    public static final String DEFAULT_ERROR_MESSAGE = "ERROR";
    /**
     * 请求 id key
     */
    public static final String REQUEST_ID_KEY = "REQUEST_ID";

    /**
     * 返回结果 key
     */
    @Schema(description = "返回结果 key")
    private String key;
    /**
     * 返回提示信息
     */
    @Schema(description = "返回提示信息")
    private String message;
    /**
     * 返回数据
     */
    private T data;
    /**
     * 额外返回数据
     */
    @Schema(description = "额外返回数据")
    private Map<String, Object> extraDataMap;
    /**
     * 系统当前时间(精确到毫秒)
     */
    @Schema(description = "系统当前时间(精确到毫秒)")
    private Long timestamp = System.currentTimeMillis();
    /**
     * 请求 id
     */
    @Schema(description = "请求 id")
    private String requestId = MDC.get(REQUEST_ID_KEY);

    private ApiResult(){
    }

    /**
     * 构造方法
     *
     * @param key
     * @param message
     * @param data
     * @param extraDataMap
     */
    protected ApiResult(String key, String message, T data, Map<String, Object> extraDataMap) {
        this.key = key;
        this.message = message;
        this.data = data;
        this.extraDataMap = extraDataMap;
    }

    /**
     * 成功
     *
     * @return
     */
    public static <T> ApiResult<T> success() {
        return success(null,null);
    }

    /**
     * 成功
     *
     * @param data 返回数据
     * @return
     */
    public static <T> ApiResult<T> success(T data) {
        return success(data, null);
    }

    /**
     * 成功
     *
     * @param data 返回数据
     * @param extraDataMap 额外返回数据
     * @return
     */
    public static <T> ApiResult<T> success(T data, Map<String, Object> extraDataMap) {
        return new ApiResult<>(DEFAULT_SUCCESS_KEY, DEFAULT_SUCCESS_MESSAGE, data, extraDataMap);
    }

    /**
     * 失败
     *
     * @return
     */
    public static <T> ApiResult<T> fail() {
        return fail(DEFAULT_ERROR_KEY, DEFAULT_ERROR_MESSAGE, null, null);
    }

    /**
     * 失败
     *
     * @param responseKey 返回结果 key
     * @param message 返回提示信息
     * @return
     */
    public static <T> ApiResult<T> fail(String responseKey, String message) {
        return fail(responseKey, message, null, null);
    }

    /**
     * 失败
     *
     * @param responseKey 返回结果 Key
     * @param message 返回提示信息
     * @param data 返回数据
     * @param extraDataMap 额外返回数据
     * @return
     */
    public static <T> ApiResult<T> fail(String responseKey, String message, T data, Map<String, Object> extraDataMap) {
        return new ApiResult<>(responseKey, message, data, extraDataMap);
    }


}

这里需要注意的是公共返回结果类上不能使用 @Schema 注解,尤其是在指定 name 的情况下,这会使生成的接口文档没有对应泛型类的属性,所有的返回结果都是一样的,看不到返回结果具体对象的属性,增加了前后端对接成本,这不符合我们对于接口文档的要求。

于此同时,对于泛型类 data 参数,也不要使用 @Schema 注解,对于没有使用 lombok 插件,而手动书写 getter/setter 的方式,datagetter 方法返回结果也必须是 T 而不能是 Object 类型,否则也无法生成对应泛型类的属性文档。

3.4 Controller 控制层示例

demo-knife4j-openapi3/src/main/java/com/ljq/demo/springboot/knife4j/controller/UserPushTypeController.java
package com.ljq.demo.springboot.knife4j.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ljq.demo.springboot.knife4j.common.api.ApiResult;
import com.ljq.demo.springboot.knife4j.model.entity.UserPushTypeEntity;
import com.ljq.demo.springboot.knife4j.model.param.userpushtype.*;
import com.ljq.demo.springboot.knife4j.service.UserPushTypeService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springdoc.api.annotations.ParameterObject;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;

/**
 * 用户消息推送方式
 * 
 * @author junqiang.lu
 * @date 2023-08-15 10:41:29
 */
@RestController
@RequestMapping(value = "/knife4j/user/pushtype")
@Tag(name = "用户消息推送方式控制层")
public class UserPushTypeController {

	@Resource
	private UserPushTypeService userPushTypeService;

    @PostMapping(value = "/add", produces = {MediaType.APPLICATION_JSON_VALUE})
    @Operation(summary = "用户消息推送方式保存(单条)")
    public ResponseEntity<ApiResult<UserPushTypeEntity>> save(@RequestBody @Validated UserPushTypeSaveParam saveParam) {
        return ResponseEntity.ok(userPushTypeService.save(saveParam));
    }

    @GetMapping(value = "/query/info", produces = {MediaType.APPLICATION_JSON_VALUE})
    @Operation(summary = "用户消息推送方式查询详情(单条)")
    public ResponseEntity<ApiResult<UserPushTypeEntity>> info(@Validated @ParameterObject UserPushTypeInfoParam infoParam) {
        return ResponseEntity.ok(userPushTypeService.info(infoParam));
    }

    @GetMapping(value = "/query/page", produces = {MediaType.APPLICATION_JSON_VALUE})
    @Operation(summary = "用户消息推送方式查询列表")
    public ResponseEntity<ApiResult<IPage<UserPushTypeEntity>>> list(@Validated @ParameterObject UserPushTypeListParam listParam) {
        return ResponseEntity.ok(userPushTypeService.list(listParam));
    }

    @PutMapping(value = "/update", produces = {MediaType.APPLICATION_JSON_VALUE})
    @Operation(summary = "用户消息推送方式修改(单条)")
    public ResponseEntity<ApiResult> update(@RequestBody @Validated UserPushTypeUpdateParam updateParam) {
        return ResponseEntity.ok(userPushTypeService.update(updateParam));
    }

    @DeleteMapping(value = "/delete", produces = {MediaType.APPLICATION_JSON_VALUE})
    @Operation(summary = "用户消息推送方式删除(单条)")
    public ResponseEntity<ApiResult> delete(@RequestBody @Validated UserPushTypeDeleteParam deleteParam) {
        return ResponseEntity.ok(userPushTypeService.delete(deleteParam));
    }

}

在 Controller 类中,原来 Swagger 2 的 @Api 注解替换为 @Tag, 原来的 @ApiOperation 注解替换为 @Operation

在请求头中的参数,例如 GET 请求,如果是一个对象,则需要使用 @ParameterObject 注解,如果不添加,则无法在 Swagger 接口文档界面进行正常请求。

4 升级注意事项(踩坑指南)

4.1 Swagger 2 注解替换

  • Replace swagger 2 annotations with swagger 3 annotations (it is already included with springdoc-openapi-starter-webmvc-ui dependency). Package for swagger 3 annotations is io.swagger.v3.oas.annotations.
    • @Api@Tag
    • @ApiIgnore@Parameter(hidden = true) or @Operation(hidden = true) or @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")
  • This step is optional: Only if you have multiple Docket beans replace them with GroupedOpenApi beans.

Migrating from SpringFox

4.2 公共返回参数不能使用 @Schema 注解,否则就会只生成一个 Swagger Model

swagger(三):统一返回结果不显示字段说明

4.3 Get 请求参数前需要添加 @ParamterObject 注解

springdoc-openapi 在 1.6.11 版本中添加了一个配置,可以一键解决不使用 @ParamterObject 注解 Swagger 接口测试不可用的问题,配置如下:

springdoc:
  # 默认是false,需要设置为true
  default-flat-param-object: true

然而这么做之后,所有通过 body 传的参数也会变成请求头传递,这只是把问题转移了,并没有从根本上解决问题。

针对这一点,对于想要尝鲜的用户还是要注意书写规范,否则改动量就非常大了。

Knife4j v4.0版本针对参数解析ParameterObject的问题说明

5 使用效果

5.1 导出到 Postman 等测试工具的接口数据地址

http://127.0.0.1:9050/v3/api-docs

5.2 Knife4j 导出接口文档

swagger增强版,Java,spring boot,swagger,knife4j,springdoc,openapi3

5.3 Knife4j UI 界面

地址:

http://127.0.0.1:9050/doc.html

效果图:

swagger增强版,Java,spring boot,swagger,knife4j,springdoc,openapi3

5.4 Swagger UI 界面

地址:

http://127.0.0.1:9050/swagger-ui/index.html

效果图:

swagger增强版,Java,spring boot,swagger,knife4j,springdoc,openapi3

6 推荐参考资料

Knife4j 官方文档: https://doc.xiaominfo.com/docs/quick-start

Springdoc 官方文档: https://springdoc.org

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

swagger(三):统一返回结果不显示字段说明

Knife4j v4.0版本针对参数解析ParameterObject的问题说明

7 Github 源码

Gtihub 源码地址 : https://github.com/Flying9001/springBootDemo/tree/master/demo-knife4j-openapi3

个人公众号:404Code,分享半个互联网人的技术与思考,感兴趣的可以关注.
文章来源地址https://www.toymoban.com/news/detail-718062.html

到了这里,关于Springboot 2.7 集成 Swagger 增强版接口框架 Knife4j 4.3 + springdoc OpenApi 3.0的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Swagger + Knife4j 接口文档的整合

    Swagger 接口文档的整合: 引入依赖(Swagger 或 Knife4j)。 自定义 Swagger 配置类。 定义需要生成接口文档的代码位置(Controller)。 注意:线上环境不要把接口暴露出去!!!可以通过在 SwaggerConfig 配置文件开头加上 @Profile({“dev”, “test”}) 限定配置仅在部分环境开启。 启动

    2024年01月20日
    浏览(52)
  • 【swagger】spring security中 swagger和knife4j集成 无法访问 返回结果没有内容

    作为一个强迫症重度的程序猿 不想多导一个jar包 本文创作背景是鉴于网上大多数是旧版本swagger2的教程,且没有针对2和3区别描述,话不多说 直接步入正题。 如果只需要knife4j文档 导这 一个包 就够了 这里以3.0+版本举例 (对springboot比较熟悉的同学应该清楚 starter目的就是将其

    2024年02月06日
    浏览(41)
  • 【SpringBoot】Swagger和knife4j的使用

    springboot笔记集合: springboot笔记合计 没用的废话理论不多说,会用就完了 Swagger 是一种开源的API描述语言,就是描述API的, 同时Swagger还提供了一组工具(也叫Swagger),可以帮助开发人员自动生成API文档、测试API并与其他系统集成。 Knife4j是基于Swagge语言延伸的另一组api工具,简

    2024年02月10日
    浏览(38)
  • springBoo3.0集成knife4j4.1.0(swagger3)

    温馨提示: springBoot 版本 3.0+ knife4j 版本 4.1.0  添加依赖:knife4j包含了swagger,openapi3中的依赖,所以加这一个就行。 yml文件中配置: 然后,就可以启动测试输入地址http://ip:port/doc.html  注解的基本使用可以看下这里:swagger3注解和swagger2的区别  这里主要提下请求参数为文件

    2024年02月05日
    浏览(39)
  • Spring Boot 集成 API 文档 - Swagger、Knife4J、Smart-Doc

    Swagger 作为 API 设计和文档的强大工具,是一个由专门的工具集合支持的框架,它在整个 API 的生命周期中发挥作用,从设计和文档,到测试和部署。通过提供可视化界面,Swagger 让开发人员和最终用户都能清晰地理解和操作 API。 使用建议:笔者建议优先考虑 Knife4J,它已经能

    2024年01月22日
    浏览(58)
  • SpringBoot3中Swagger整合knife4j和springdoc的配置说明

      springboot3开始javax包改成了jakarta,而swagger-oas等包中依然使用的是javax所以报错。另外springfox已经过时了,两年没更新了,并且不支持OpenAPI3 标准,而SpringBoot3只支持OpenAPI3规范,所以要迁移到springdoc Knife4J是一款基于Swagger快速生成API文档和调试平台的开源工具,它可以轻松地

    2024年02月04日
    浏览(50)
  • springboot集成knife4j详细教程

    使用原生的swagger作为接口文档,功能不够强大,并且默认的ui比较简陋,不符合大众审美。所以实际开发中推荐使用knife4j对swagger进行增强。knife4j的地址:https://gitee.com/xiaoym/knife4j 想要使用knife4j非常简单,只要在Springboot项目中引入knife4j的依赖即可 注意:引入knife4j后会自动

    2024年02月20日
    浏览(36)
  • springboot配置swagger/knife4j时出现的Unresolvable class definition for class …异常

    抽取出其中的关键原因描述: nested exception is java.lang.IllegalArgumentException: Unresolvable class definition for class [springfox.documentation.spring.web.OnServletBasedWebApplication] springfox.documentation.common.ClassPresentInClassPathCondition 进行原因排查后,发现是依赖之间版本问题的冲突导致,下面提供一个能

    2024年02月12日
    浏览(44)
  • 【超详细】springboot + springdoc-openapi + knife4j 集成案例

    springdoc-openapijava库有助于使用 spring boot 项目自动生成 API 文档。 springdoc-openapi通过在运行时检查应用程序以根据 spring 配置、类结构和各种注释推断 API 语义来工作。 自动生成 JSON/YAML 和 HTML 格式 API 的文档。可以使用 swagger-api 注释通过注释来完成此文档。 该库支持: OpenAP

    2023年04月25日
    浏览(56)
  • Springboot3.0.0+集成SpringDoc并配置knife4j的UI

    环境:JDK17,Springboot3+,springdoc2+,knife4j 4+ Springdoc本身也是集成了Swagger3,而knife4j美化了Swagger3的UI Knife4j官网: 快速开始 | Knife4j Springdoc官网 OpenAPI 3 Library for spring-boot 由于此knife4j内依赖了SpringDoc,因此不用另外引入springdoc的依赖 springdoc依赖(无需引入),亲测引入也不会冲突

    2024年02月09日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包