Spring Doc OpenAPI3.0 抛弃SpringFox拥抱SpringDoc

news2024/11/14 7:35:09

Spring Doc

1 简介

SpringDoc是SpringBoot 的API文档工具。官网:https://springdoc.org/

在使用SpringBoot 2.6以前去创建API文档工具一般会采用SpringFox提供的Swagger库,但是由于SpringBoot版本的不断升级和SpringFox摆烂不更新,导致了SpringBoot2.6之后的项目无法使用SpringFox去生成API文档,或者可以使用但是有很多的bug。

SpringDoc是一款可以结合SpringBoot使用API文档生成工具,基于OpenAPI 3,而且项目维护和社区都在不断更新,不仅支持SpringMVC,而且还支持Spring WebFlux项目。

下图为SpringDoc的架构图的总体概述。
在这里插入图片描述

2 基本使用

2.1 新建项目并导入maven

<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-ui</artifactId>
    <version>1.7.0</version>
</dependency>

2.2 使用注解标记接口

2.2.1 常用注解

注解描述
@Tag标记在接口类上,用来设置 Controller 的名称和描述
@Parameter/@Parameters用来设置请求参数的描述
@Operation对接口方法的描述,可以设置接口的名称
@ApiResponse/@ApiResponses用来配置响应
@Schema标记在模型(model)类上或类的属性上,进行标注解释。

2.2.2 测试Controler Demo

TestController

package org.example.controller.test;
/**
 * 省略import
 */
@Tag(name = "测试接口", description = "定义测试接口")
@RestController
@RequestMapping("/test")
public class TestController {
    @Operation(summary = "get测试接口", description = "返回id")
    @Parameter(name = "id", description = "参数ID", example = "123456")
    @ApiResponse(responseCode = "403", description = "无权限")
    @GetMapping("/get")
    public Map<String, Object> get(@Parameter(description = "id") String id) {
        Map<String, Object> res = new HashMap<>(1);
        res.put("id", id);
        return res;
    }
}

UserController

package org.example.controller.user;
/**
 * 省略import
 */
@Tag(name = "用户接口", description = "定义用户接口")
@RestController
@RequestMapping("/user")
public class UserController {
    @Operation(summary = "post测试接口", description = "返回username")
    @Parameter(name = "username", description = "参数username", example = "username")
    @ApiResponse(responseCode = "403", description = "无权限")
    @PostMapping("/post")
    public Map<String, Object> get(@Parameter(description = "用户名") String username) {
        Map<String, Object> res = new HashMap<>(1);
        res.put("username", username);
        return res;
    }
}

2.3 编写SpringDocConfig

2.3.1 常用springdoc的配置

package org.example.config;

import io.swagger.v3.oas.models.Components;
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 io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.springdoc.core.GroupedOpenApi;
import org.springdoc.core.customizers.OpenApiCustomiser;
import org.springdoc.core.customizers.OperationCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author zhong
 */
@Configuration
public class SpringDocConfig {

    @Bean
    public OpenAPI defaultOpenAPI() {
//        return new OpenAPI()
//                .info(info())
//                .externalDocs(documentation())
//                .components(new Components().addSecuritySchemes("Authorization", new SecurityScheme().name("认证").type(SecurityScheme.Type.HTTP)
//                        .description("JWT认证").scheme("bearer").bearerFormat("JWT")));


        return new OpenAPI().
                info(info())
                .externalDocs(documentation());
    }

    public Info info() {
        return new Info()
                .title("SpringDoc OpenApi")
                .version("V1.0.0")
                .description("测试spring doc open api")
                .license(new License().name("许可证名称").url("许可证地址"))
                .contact(new Contact().name("联系人").url("联想人链接"))
                .summary("概要");
    }

    public ExternalDocumentation documentation() {
        return new ExternalDocumentation().description("文档描述").url("文档地址");
    }

    @Bean
    public GroupedOpenApi testApi() {
        return GroupedOpenApi.builder()
                .displayName("测试接口")
                .group("test")
                .packagesToScan("org.example.controller.test")
                .build();
    }

    @Bean
    public GroupedOpenApi userApi() {
        return GroupedOpenApi.builder()
                .displayName("用户接口")
                .group("user")
                .packagesToScan("org.example.controller.user")
                .addOpenApiCustomiser(openApiCustomiser())
                .addOperationCustomizer(operationCustomizer())
                .build();
    }

    public OpenApiCustomiser openApiCustomiser() {
        return api ->
                api.components(new Components()
                        .addSecuritySchemes("Authorization", new SecurityScheme().name("认证").type(SecurityScheme.Type.HTTP)
                                .description("JWT认证").scheme("bearer").bearerFormat("JWT"))
                );
    }

    public OperationCustomizer operationCustomizer() {
        return (operation, handlerMethod) -> {
            operation.addSecurityItem(new SecurityRequirement().addList("Authorization"));
            return operation;
        };
    }
}

2.3.2 关于接口鉴权问题(jwt方式)

如以上配置所示,user接口设置了鉴权设置

对一个分组的接口添加鉴权的方式

@Bean
    public GroupedOpenApi userApi() {
        return GroupedOpenApi.builder()
                .displayName("用户接口")
                .group("user")
                .packagesToScan("org.example.controller.user")
                .addOpenApiCustomiser(openApiCustomiser())
                .addOperationCustomizer(operationCustomizer())
                .build();
}
public OpenApiCustomiser openApiCustomiser() {
    return api ->
            api.components(new Components()
                    .addSecuritySchemes("Authorization", new SecurityScheme().name("认证").type(SecurityScheme.Type.HTTP)
                            .description("JWT认证").scheme("bearer").bearerFormat("JWT"))
            );
}

public OperationCustomizer operationCustomizer() {
    return (operation, handlerMethod) -> {
        operation.addSecurityItem(new SecurityRequirement().addList("Authorization"));
        return operation;
    };
}

如果嫌麻烦,可以设置全局设置

例如配置代码注释的部分添加全局配置

 @Bean
    public OpenAPI defaultOpenAPI() {
        return new OpenAPI()
                .info(info())
                .externalDocs(documentation())
                .components(new Components().addSecuritySchemes("Authorization", new SecurityScheme().name("认证").type(SecurityScheme.Type.HTTP)
                        .description("JWT认证").scheme("bearer").bearerFormat("JWT")));

    }

2.4 启动效果

访问http://localhost:8080/swagger-ui/index.html

在这里插入图片描述

2.5 一些application的配置说明

2.5.1 springdoc-openapi 核心属性

官方链接:https://springdoc.org/#springdoc-openapi-core-properties

参数名称默认值描述
springdoc.api-docs.path/v3/api-docsString, 用于 Json 格式的 OpenAPI 文档的自定义路径。
springdoc.api-docs.enabledtrueBoolean. 禁用 springdoc-openapi 端点(默认为 /v3/api-docs)。
springdoc.packages-to-scan*List of Strings.要扫描的包列表(逗号分隔)
springdoc.paths-to-match/*List of Strings.要匹配的路径列表(逗号分隔)
springdoc.produces-to-match/*List of Strings.The list of produces mediaTypes to match (逗号分隔)
springdoc.headers-to-match/*List of Strings.要匹配的标题列表(逗号分隔)
springdoc.consumes-to-match/*List of Strings.要匹配的消耗媒体类型列表(逗号分隔)
springdoc.paths-to-excludeList of Strings.要排除的路径列表(逗号分隔)
springdoc.packages-to-excludeList of Strings.要排除的包列表(逗号分隔)
springdoc.default-consumes-media-typeapplication/jsonString. 默认使用媒体类型。
springdoc.default-produces-media-type**/**String.默认产生媒体类型。
springdoc.cache.disabledfalseBoolean. 禁用计算 OpenAPI 的 springdoc-openapi 缓存。
springdoc.show-actuatorfalseBoolean. 显示执行器端点。
springdoc.auto-tag-classtrueBoolean. 禁用 springdoc-openapi 自动标签。
springdoc.model-and-view-allowedfalseBoolean. 允许带有 ModelAndView 返回的 RestControllers 出现在 OpenAPI 描述中。
springdoc.override-with-generic-responsetrueBoolean. 当为 true 时,自动将 @ControllerAdvice 响应添加到所有生成的响应中。
springdoc.api-docs.groups.enabledtrueBoolean. 禁用 springdoc-openapi 组。
springdoc.group-configs[0].groupString.群名
springdoc.group-configs[0].display-nameString.组的显示名称。
springdoc.group-configs[0].packages-to-scan*List of Strings.要扫描组的包列表(逗号分隔)
springdoc.group-configs[0].paths-to-match/*List of Strings.组匹配的路径列表(逗号分隔)
springdoc.group-configs[0].paths-to-exclude``List of Strings.要为组排除的路径列表(逗号分隔)
springdoc.group-configs[0].packages-to-excludeList of Strings.要排除的包列表(逗号分隔)
springdoc.group-configs[0].produces-to-match/*List of Strings.The list of produces mediaTypes to match (逗号分隔)
springdoc.group-configs[0].consumes-to-match/*List of Strings.要匹配的消耗媒体类型列表(逗号分隔)
springdoc.group-configs[0].headers-to-match/*List of Strings.要匹配的标题列表(逗号分隔)
springdoc.webjars.prefix/webjarsString, 把swagger-ui的URL可见的webjars前缀换成spring-webflux。
springdoc.api-docs.resolve-schema-propertiesfalseBoolean. 在@Schema 上启用属性解析器(名称、标题和描述)。
springdoc.remove-broken-reference-definitionstrueBoolean. 禁用删除损坏的引用定义。
springdoc.writer-with-default-pretty-printerfalseBoolean. 启用 OpenApi 规范的漂亮打印。
springdoc.model-converters.deprecating-converter.enabledtrueBoolean. 禁用弃用模型转换器。
springdoc.model-converters.polymorphic-converter.enabledtrueBoolean. 禁用多态模型转换器。
springdoc.model-converters.pageable-converter.enabledtrueBoolean. 禁用可分页模型转换器。
springdoc.model-converters.sort-converter.enabledtrueBoolean. 禁用排序转换器。
springdoc.use-fqnfalseBoolean. 启用完全限定名称。
springdoc.show-endpointfalseBoolean. 使 spring security 登录端点可见。
springdoc.pre-loading-enabledfalseBoolean. 预加载设置以在应用程序启动时加载 OpenAPI。
springdoc.writer-with-order-by-keysfalseBoolean. 启用确定性/字母顺序。
springdoc.use-management-portfalseBoolean. 在执行器管理端口上公开 swagger-ui。
springdoc.disable-i18nfalseBoolean. 使用 i18n 禁用自动翻译。
springdoc.show-spring-cloud-functionstrueBoolean. 显示 spring-cloud-function Web 端点。
springdoc.api-docs.versionopenapi_3_0String. 选择OpenAPI 3.0OpenAPI 3.1(使用值OPENAPI_3_1)。
springdoc.default-flat-param-objectfalseBoolean. 默认展平参数。
springdoc.default-support-form-datafalseBoolean. 指定api接受表单数据时默认设置参数为表单数据。
springdoc.nullable-request-parameter-enabledtrueBoolean. 在 Kotlin 中默认启用对可空请求参数的支持。
springdoc.show-oauth2-endpointsfalseBoolean. 使 spring security oauth2-endpoint 可见。

2.5.2 swagger-ui核心属性

官方链接https://springdoc.org/#swagger-ui-properties

参数名称默认值描述
springdoc.swagger-ui.path/swagger-ui.htmlString, 用于 swagger-ui HTML 文档的自定义路径。
springdoc.swagger-ui.enabledtrueBoolean. 禁用 swagger-ui 端点(默认为 /swagger-ui.html)。
springdoc.swagger-ui.configUrl/v3/api-docs/swagger-configString. 从中获取外部配置文档的 URL。

2 从SpringFox迁移

  • 删除 springfox 和 swagger 2 依赖项。添加springdoc-openapi-ui依赖项。
   <dependency>
      <groupId>org.springdoc</groupId>
      <artifactId>springdoc-openapi-ui</artifactId>
      <version>1.7.0</version>
   </dependency>
  • 用 swagger 3 注释替换 swagger 2 注释(它已经包含在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")
  • 如果您使用一个对象来捕获多个请求查询参数,请注释该方法参数@ParameterObject
  • 此步骤是可选的:仅当您有多个 Docketbeans 时才用GroupedOpenApibeans 替换它们。

前:

  @Bean
  public Docket publicApi() {
      return new Docket(DocumentationType.SWAGGER_2)
              .select()
              .apis(RequestHandlerSelectors.basePackage("org.github.springshop.web.public"))
              .paths(PathSelectors.regex("/public.*"))
              .build()
              .groupName("springshop-public")
              .apiInfo(apiInfo());
  }

  @Bean
  public Docket adminApi() {
      return new Docket(DocumentationType.SWAGGER_2)
              .select()
              .apis(RequestHandlerSelectors.basePackage("org.github.springshop.web.admin"))
              .paths(PathSelectors.regex("/admin.*"))
              .apis(RequestHandlerSelectors.withMethodAnnotation(Admin.class))
              .build()
              .groupName("springshop-admin")
              .apiInfo(apiInfo());
  }

现在:

  @Bean
  public GroupedOpenApi publicApi() {
      return GroupedOpenApi.builder()
              .group("springshop-public")
              .pathsToMatch("/public/**")
              .build();
  }
  @Bean
  public GroupedOpenApi adminApi() {
      return GroupedOpenApi.builder()
              .group("springshop-admin")
              .pathsToMatch("/admin/**")
              .addOpenApiMethodFilter(method -> method.isAnnotationPresent(Admin.class))
              .build();
  }

如果你只有一个 Docket - 删除它并添加属性到你的application.properties

springdoc.packagesToScan=package1, package2
springdoc.pathsToMatch=/v1, /api/balance/**
  • 添加OpenAPI类型的bean。参见示例:
  @Bean
  public OpenAPI springShopOpenAPI() {
      return new OpenAPI()
              .info(new Info().title("SpringShop API")
              .description("Spring shop sample application")
              .version("v0.0.1")
              .license(new License().name("Apache 2.0").url("http://springdoc.org")))
              .externalDocs(new ExternalDocumentation()
              .description("SpringShop Wiki Documentation")
              .url("https://springshop.wiki.github.org/docs"));
  }

3 使用 knife4j美化

在这里插入图片描述

3.1 使用方法

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

官网:https://doc.xiaominfo.com/

首先,引用Knife4j的starter,Maven坐标如下:

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

然后删除之前的springdoc-openapi-ui

在这里插入图片描述

3.2 常用配置项

官方说明地址:https://doc.xiaominfo.com/docs/features/enhance

## knife4j的增强配置,不需要增强可以不配
knife4j:
  enable: true
  setting:
    language: zh_cn
    enable-home-custom: true
    home-custom-path: classpath:markdown/api-home.md
    enable-footer-custom: true
    footer-custom-content: 系统文档

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/459517.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

springboot项目需要读取非application.yml/properties 的配置文件

目录&#xff1a; 1、操作步骤2、总结3、扩展4、第二种方法获取配置文件bean 1、操作步骤 1.新建配置文件&#xff1a; 2.编辑配置文件&#xff1a; test-serverrd-dev02.jr.rong360.com3.新建Config类&#xff1a; Component PropertySource(value "kirara.properti…

销量破亿,董洁直播间凭何出圈?

近期&#xff0c;“没有五位数走不出”的董洁直播间火了…… 纵观这几年各大平台直播带货&#xff0c;火已不是什么新鲜事&#xff0c;而为何董洁的直播能火上热搜呢&#xff1f;本期&#xff0c;千瓜将解析董洁直播&#xff0c;同品牌方聊聊小红书直播的那些事儿。董洁「种草式…

Win10分辨率怎么看?2种必须学会的方法!

案例&#xff1a;win10分辨率 【为了方便办公&#xff0c;最近我的电脑连接了2个显示屏&#xff0c;但感觉电脑显示怪怪的&#xff0c;可能是分辨率设置不对&#xff0c;大家知道应该怎么查看电脑的分辨率吗&#xff1f;感谢感谢&#xff01;】 我们的win10系统支持多种分辨率…

ChatGPT的未来:人工智能技术的新发展趋势

第一章&#xff1a;人工智能技术的新发展趋势 近年来&#xff0c;随着人工智能技术的不断发展和应用&#xff0c;ChatGPT这样的大型自然语言处理模型已经成为人工智能技术的重要组成部分。未来&#xff0c;人工智能技术的发展将更加快速&#xff0c;我们可以看到以下几个方面的…

制造型企业为何需要MES管理系统,企业怎样选择合适的MES

MES管理系统是专门针对制造型企业而设计的&#xff0c;能实现对生产车间、工厂信息化管理&#xff0c;帮助制造型企业提高生产效率&#xff0c;加快数字化转型。目前针对制造型企业生产效率、企业竞争力和生产管理状况的需求&#xff0c;MES管理系统已经成为实现生产经营目标的…

MySQL创建用户并赋权限

MySQL创建用户并赋权限 省流1.创建mysql用户1.1 新建用户1.2 查询用户信息 2. 授权用户2.1 指定数据库和表赋权2.2 赋予全部权限2.3 查看用户权限2.4 回收用户权限 3. 修改用户密码4. 删除用户5. 刷新权限(务必执行) 省流 如果只是希望新建一个用户并且赋予全部执行权限&#…

android react native报错

1.报错图片 解决方案&#xff1a; android下的build.gradle文件 修改 如图 报错 E:/androidData/caches/transforms-2/files-2.1/399126eae79af6235d7a4ae871926a31/jetified-kotlin-stdlib-1.6.10.jar!/META-INF/kotlin-stdlib.kotlin_module: Module was compiled with an i…

华为云 HCIP云迁移 学习课程提供的考试样题提交之后没有反馈正确答案的问题

最近在考HCIP的云迁移&#xff0c;但是他提供的考试样题昨晚发现没有正确答案&#xff0c;只会告诉你对错&#xff0c;判断题还好解决&#xff0c;但是多选题就麻烦了。这边研究了一下&#xff0c;share一下&#xff0c;方便大家学习和验证自己的学习成果 这边去看了他的 api r…

杰理-OTA升级电量限制

杰理-OTA升级电量限制 获取升级异常状态标志位&#xff08;升级过程中断开重新连接&#xff0c;不做电量限制&#xff09;

【观察】华为:运力算力存力“协同”,推动数字生产力“跃升”

可以看到&#xff0c;过去几年数字化转型已经席卷全球&#xff0c;随着新技术的广泛应用&#xff0c;新的机会和价值正在不断被发现和创造。从某种程度上说&#xff0c;数字化转型不再是“可选项”&#xff0c;而变成了“必选项”。 确实如此&#xff0c;目前已经有超过170多个…

基于JS简单甘特图(IT枫斗者)

基于JS简单甘特图 基于JS简单甘特图 先来看一下效果吧&#xff0c;这里的需求是从早上的5点为开始时间&#xff0c;到第二天到凌晨5点 前期准备 其实网上有很多甘特图的实现方式&#xff0c;但是他们都只能具象到天&#xff0c;不能具体到某个时间点&#xff0c;而且每一个…

ESD/EMI防护设计

内容摘取自<Rockchip_RK3568_Hardware_Design_Guide_V1.0_CN.pdf> 1.1概述 本章对于RK3568产品设计中的ESD/EMI防护设计给出了建议&#xff0c;帮助客户更好的提高产品的抗静电、抗电 磁干扰水平。 1.2 术语解释 本章中的术语解释如下&#xff1a;  ESD&#xff08;E…

直播预告丨打破 Python 束缚:Level 2 因子的脚本优化实践

有人说&#xff0c;DolphinDB 是一个时序数据库&#xff1b; 也有人说&#xff0c;DolphinDB 就是 Python 加数据库的结合&#xff1b;还有人说&#xff0c;DolphinDB 是一个支持流数据处理的实时计算软件…… 我们经常会听到类似的理解&#xff0c;其实很多小伙伴都会有好奇…

Python爱心表白,快去发给你心仪的人叭~

作者主页&#xff1a;爱笑的男孩。的博客_CSDN博客-深度学习,YOLO,活动领域博主爱笑的男孩。擅长深度学习,YOLO,活动,等方面的知识,爱笑的男孩。关注算法,python,计算机视觉,图像处理,深度学习,pytorch,神经网络,opencv领域.https://blog.csdn.net/Code_and516?typecollect个人…

Hive ---- Hive入门

Hive ---- Hive入门 1. 什么是Hive1. Hive简介2. Hive本质 2. Hive架构原理1. 用户接口&#xff1a;Client2. 元数据&#xff1a;Metastore3. 驱动器&#xff1a;Driver4. Hadoop 1. 什么是Hive 1. Hive简介 Hive是由Facebook开源&#xff0c;基于Hadoop的一个数据仓库工具&a…

关于 mysql本地使用ODBC连接突然无法连接上且无法搜索到database的 解决方法

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/130360385 红胖子网络科技的博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软…

关于Open Shift(OKD) 中应用管理部署的一些笔记

写在前面 因为参加考试&#xff0c;会陆续分享一些 OpenShift 的笔记博文内容为介绍 openshift 不同的创建应用的方式&#xff0c;包括&#xff1a; 基于 IS 创建应用基于镜像创建应用基于源码和 image 创建应用基于源码和 IS 创建应用基于模板创建应用 学习环境为 openshift v…

ChatGPT + MindShow 三分钟搞定PPT制作

制作一份“通用性”的PPT需要几步&#xff1f; 三步 接下来&#xff0c;我们借助ChatGPT和MindShow&#xff0c;大概三分钟完成操作&#xff0c;就能制作出来完胜大部分人的PPT文件。具体可看文末效果导示。 解锁更多AIGC&#xff08;ChatGPT、AI绘画&#xff09;玩法&#…

与其关注“孔乙己的长衫”,不如来看看什么是套接字

孔乙已是鲁迅笔下人物&#xff0c;穷困流倒还穿着象征读书人的长衫&#xff0c;迁腐、麻木。最近&#xff0c;大家自我调佩是“当代孔乙己”&#xff0c;学历成为思想负担&#xff0c;找工作时高不成低不就。 套接字概念 Socket本身有“插座”的意思&#xff0c;在Linux环境下…

Model-Contrastive Federated Learning 论文解读(CVPR 2021)

Model-Contrastive Federated Learning 论文解读 对比学习SimCLR 对比学习的基本想法是同类相聚&#xff0c;异类相离 从不同的图像获得的表征应该相互远离&#xff0c;从相同的图像获得的表征应该彼此靠近 具体框架&#xff1a; T随机数据增强模块&#xff1a;随机裁剪然…