Spring Boot 3.x 中使用 SpringDoc 2 / Swagger3(详解)

大家好,我是码哥,《Redis 高手心法》作者。

SpringBoot 已经成为 Java 开发的首选框架,今天码哥跟大家聊一聊 Spring Boot3 如何与 Swagger3 集成打造一个牛逼轰轰的接口文档。

为什么要用 Swagger

唐二婷:我最讨厌两件事:

  1. 别人接口不写注释;

  2. 自己写接口注释。

我们都被接口文档折磨过,前端抱怨后端的接口文档一坨屎;后端觉得写接口文档浪费时间。

每个项目都有成百上千个接口调用,这时候再要求人工编写接口文档并且保证文档的实时更新几乎是一件不可能完成的事,所以这时候我们迫切需要一个工具,一个能帮我们自动化生成接口文档以及自动更新文档的工具。

它就是 Swagger。

Swagger 的核心思想是通过定义和描述 API 的规范、结构和交互方式,以提高 API 的可读性、可靠性和易用性,同时降低 API 开发的难度和开发者之间的沟通成本。

这里我采用了 Swagger3.0(Open API 3.0)的方式集成到 SpringBoot。springfox-boot-start 和 springfox-swagger2 都是基于 Swagger2.x 的。

这里将介绍 springdoc-openapi-ui,它是 SpringBoot 基于 Open API 3.0(Swagger3.0)

SpringFox 与 Swagger 的关系

Springfox 是一套可以帮助 Java 开发者自动生成 API 文档的工具,它是基于 Swagger 2.x 基础上开发的。

除了集成 Swagger 2.x,Springfox 还提供了一些额外功能,例如自定义 Swagger 文档、API 版本控制、请求验证等等。

但是随着时间的推移,Swagger2.x 终究成为历史,所以我们可以看出 springfox-boot-starter 的坐标从 3.0.0 版本(2020 年 7 月 14 日)开始就一直没有更新;

也得注意的是 springfox-swagger2 坐标和 springfox-boot-start 是一样的,但 springfox-boot-start 只有 3.0.0 版本。这里我就不在使用 Swagger2.x 版本

SpringDoc(推荐)

SpringDoc 对应坐标是 springdoc-openapi-ui,它是一个集成 Swagger UI 和 ReDoc 的接口文档生成工具,在使用上与 springfox-boot-starter 类似,但提供了更为灵活、功能更加强大的工具。

其中除了可以生成 Swagger UI 风格的接口文档,还提供了 ReDoc 的文档渲染方式,可以自动注入 OpenAPI 规范的 JSON 描述文件,支持 OAuth2、JWT 等认证机制,并且支持全新的 OpenAPI 3.0 规范

SpringBoot 3 集成 Swagger3.0

唐二婷:开干吧,Spring Boot3 如何集成这么吊炸天的工具。

需要注意的是,我们一般不会选择原生的 Swagger maven 坐标来集成 Swagger。而是通过 springdoc-openapi-ui 的 Maven 坐标。

它可以很好的和 Spring 或 SpringBoot 项目集成;这个坐标也被 Spring 社区广泛支持和认可,并被认为是集成 Swagger UI 和 OpenAPI 规范的一个优秀选择。

引入 Maven

在该示例中,我使用 Spring Boot 3.0.2 集成 Swagger 3.0。

springdoc-openapi-starter-webmvc-ui:目前最新版本是 2.6.0,适用于 Spring Boot 3.x 和 Spring Framework 6。支持 Jakarta 命名空间(例如,jakarta.validation),适合 Spring Boot 3 的 Jakarta EE 转换。

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></dependency><dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-starter-webmvc-ui</artifactId><version>2.6.0</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies>

配置 SwaggerOpenApiConfig

我们通过配置类的方式创建一个 OpenAPI 的 Bean 对象就可以创建 Swagger3.0 的文档说明。

import io.swagger.v3.oas.models.ExternalDocumentation;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class Swagger3Config {@Beanpublic OpenAPI springShopOpenAPI() {return new OpenAPI().info(new Info().title("码哥跳动 Swagger3 详解").description("Swagger3 Spring Boot 3.0 application").version("v0.0.1").license(new License().name("Apache 2.0").url("http://springdoc.org"))).externalDocs(new ExternalDocumentation().description("swagger 3 详解").url("https://springshop.wiki.github.org/docs"));}}

OpenAPI 对象是 Swagger 中的核心类之一,用于描述整个 API 的结构和元数据。

Swagger2 和 Swagger3 使用的是完全不同的两套注解,所以原本使用 Swagger2 相关注解的代码页需要完全迁移,改为使用 Swagger3 的注解。

Swagger2Swagger3
@Api@Tag
@ApiOperation@Operation
@ApiImplicitParams@Parameters
@ApiImplicitParam@Parameter
@ApiModel@Schema
@ApiModelProperty@Schema
@ApiResponses@ApiResponses
@ApiResponse@ApiResponse
@ApiIgnore@Hidden 或者 其他注解的 hidden = true 属性

配置文件

通过以下配置来控制 swagger 的开关和访问地址:WEB 界面的显示基于解析 JSON 接口返回的结果, 如果 api-docs 关闭, swagger-ui 即使 enable 也无法使用。

server:port: 8013spring:application:name: magebyte-swaggerspringdoc:api-docs:enabled: true # 开启OpenApi接口path: /v3/api-docs  # 自定义路径,默认为 "/v3/api-docs"swagger-ui:enabled: true # 开启swagger界面,依赖OpenApi,需要OpenApi同时开启path: /swagger-ui.html # 自定义路径,默认为"/swagger-ui/index.html"# Packages to include,多个用 , 分割packagesToScan: zero.magebyte.magebyte.swagger.controller

需要注意的是,packagesToScan 用于指定 Controller 接口包路径。

@Schema

Swagger3 用 @Schema 注解对象和字段, 以及接口中的参数类型。

@Setter
@Getter
@Schema(description = "响应返回数据对象")
public class Result<T> implements Serializable {@Schema(title = "code",description = "响应码",format = "int32",requiredMode = Schema.RequiredMode.REQUIRED)private Integer code;@Schema(title = "msg",description = "响应信息",accessMode = Schema.AccessMode.READ_ONLY,example = "成功或失败",requiredMode = Schema.RequiredMode.REQUIRED)private String message;@Schema(title = "data", description = "响应数据", accessMode = Schema.AccessMode.READ_ONLY)private T data;
}

返回对象定义

@Data
@AllArgsConstructor
@Schema(title = "学生模型VO", description = "响应视图学生模型VO")
public class StudentVO implements Serializable {@Schema(name = "学生ID", description = "学生ID属性", format = "int64", example = "1")private Long id;            // 学生ID@Schema(name = "学生姓名", description = "学生姓名属性", example = "jack")private String name;        // 学生姓名@Schema(name = "学生年龄", description = "学生年龄属性", format = "int32", example = "24")private Integer age;        // 学生年龄@Schema(name = "学生地址", description = "学生地址属性", example = "安徽合肥")private String address;     // 学生地址@Schema(name = "学生分数", description = "学生分数属性", format = "double", example = "55.50")private Double fraction;    // 学生分数@Schema(name = "学生爱好", description = "学生爱好属性(List类型)",type = "array", example = "[\"玩\", \"写字\"]")private List<String> likes; // 学生爱好
}

@Paramete

@Parameter 注解用于描述方法参数。如果不希望显示某个参数, 用@Parameter(hidden = true)修饰。

@Parameters({@Parameter(name = "currentPage", description = "当前页码", required = true),@Parameter(name = "size", description = "当前页大小", example = "10"),@Parameter(name = "queryUser", description = "用户查询条件")
})

Controller 接口定义

启动项目,打开链接:http://localhost:8013/swagger-ui/index.html

@RestController
@RequestMapping("/students")
@Tag(name = "StudentControllerAPI", description = "学生控制器接口", externalDocs = @ExternalDocumentation(description = "这是一个接口文档介绍"))
public class StudentController {@Operation(summary = "根据Id查询学生信息", description = "根据ID查询学生信息,并返回响应结果信息",parameters = {@Parameter(name = "id", description = "学生ID", required = true, example = "1")},responses = {@ApiResponse(responseCode = "200",description = "响应成功",content = @Content(mediaType = "application/json",schema = @Schema(title = "Resul和StudentVO组合模型",description = "返回实体,AjaxResult内data为StudentVO模型",anyOf = {Result.class, StudentVO.class}))),@ApiResponse(responseCode = "500",description = "响应失败",content = @Content(mediaType = "application/json",schema = @Schema(title = "Resul模型",description = "返回实体,Result内 data为空",implementation = Result.class)))})@GetMapping("/{id}")public Result<StudentVO> findOneStudent(@PathVariable(value = "id") Long id) {//模拟学生数据List<String> likes = Arrays.asList("抓鱼", "爬山", "写字");StudentVO studentVO = new StudentVO(id, "张三", 22, "惠州", 93.5, likes);return new Result<StudentVO>(200, "成功", studentVO);}@Operation(summary = "查询全部学生数据",description = "查询学生信息,并返回响应结果信息",responses = {@ApiResponse(responseCode = "200",description = "响应成功",content = @Content(mediaType = "application/json",schema = @Schema(title = "AjaxResul和StudentVO组合模型",description = "返回实体,Result内data为StudentVO模型(并且StudentVO为集合)",anyOf = {Result.class, StudentVO.class})))})@GetMapping("/lists")public Result<List<StudentVO>> findAllStudent() {//模拟学生数据List<String> likes = Arrays.asList("抓鱼", "爬山", "写字");StudentVO student1 = new StudentVO(1L, "张三", 22, "深圳", 93.5, likes);StudentVO student2 = new StudentVO(2L, "李四", 24, "惠州", 99.5, likes);return new Result(200, "成功", Arrays.asList(student1, student2));}@Operation(summary = "学生查询接口", description = "学生查询接口")@GetMapping("/query")public Result<List<StudentVO>> queryStudent(QueryStudentDTO queryStudentDTO) {//模拟学生数据List<String> likes = Arrays.asList("抓鱼", "爬山", "写字");StudentVO student1 = new StudentVO(1L, "张三", 22, "广东深圳", 93.5, likes);StudentVO student2 = new StudentVO(2L, "李四", 24, "广东惠州", 99.5, likes);return new Result<List<StudentVO>>(200, "成功", Arrays.asList(student1, student2));}@Operation(summary = "学生添加接口", description = "学生添加接口")@PostMappingpublic Result saveStudent(@RequestBody StudentDTO studentDTO) {System.out.println("成功添加数据:" + studentDTO);return new Result(200, "成功", null);}}
7e2ba0def92f8ac5a7278e13957f3d55.png d7229271bad981107d11d4082e55baa6.png ed0512f44aa528f67fc1014b7ed80c2f.png

专栏介绍

最后,介绍下《Java 面试高手心法 58 讲》专栏,内容涵盖 Java 基础、Java 高级进阶、Redis、MySQL、消息中间件、微服务架构设计等面试必考点、面试高频点。

本专栏不会单纯教你背八股文知识,而是结合实际大厂高并发项目的场景,提取码哥多年的工作经验和面试经验,每篇文章平均画了 4 张图,让你高效的学习面试技术要点,掌握互联网 Java 流行技术体系要点难点,让你系统化的提升技术,做到事半功倍,拿下高薪 Offer。

丢掉你收藏的那些所谓的「面试宝典」,因为它们大多数深度不够,甚至内容还有错误,这也是为何每次面试你都回答不好的原因,你只会看完就忘,还浪费时间。

原价 128 元,现在双十一优惠 19 元,另外,我向平台申请 100 张 9 折优惠券,用完为止,机不可失,大家抓住机会上车!

扫描下方二维码即可使用优惠券直接购买。

078651ac66c7ecbbe16ab13c35eeea21.png

1830d38b83905df71b27315b2bf14a91.jpeg

往期推荐

今天面试了一个候选人,当场想给他 Offer

10w 级的并发场景,JVM 有哪些方面值得优化呢?

我的新书出版后,小伙伴们问是不是赚翻了?

支撑每秒数百万订单无压力,SpringBoot + Disruptor 太猛了!

简单实用!利用Redis轻松实现高并发全局ID生成器

参考资料

  1. https://swagger.io/docs/open-source-tools/swagger-ui/usage/configuration/

  2. https://springdoc.org/#getting-started

  3. https://springdoc.org/#migrating-from-springfox

  4. https://www.cnblogs.com/antLaddie/p/17418078.html

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

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

相关文章

Java中四种引用类型【快速理解】图文

一、强引用 我们正常手动new出来的对象都是强应用&#xff0c;不对他进行别的操作的时候它是不会进行垃圾回收的。除非将它的引用断开&#xff0c;此时调用垃圾回收器才会将它回收。 二、软引用 三、虚引用 虚引用的意思就是&#xff0c;引用关系是虚的&#xff0c;如果创造出…

C语言-详细讲解-洛谷P1075 [NOIP2012 普及组] 质因数分解

1.题目要求 2.题目解析 解题点在于如何分解质因数&#xff0c;这里介绍一下短除法。&#xff08;虽然解决这个问题可以不用短除法&#xff09; 3.代码实现 贴一下自己的代码 #include <stdio.h> #include <math.h>int main() {int n, i;scanf("%d",…

Kubernetes Extended Resource 扩展资源使用简介

Kubernetes 除了提供基于 CPU 和内存的传统计算资源调度外&#xff0c;还支持自定义的 Extended Resource 扩展资源&#xff0c;以便调度和管理其它各种类型的资源。 Extended Resource Extended Resource 扩展资源的创建和使用过程如下图所示&#xff1a; 定义资源&#xff…

javaweb基于springboot社区养老服务管理系统

简介&#xff1a; 系统整体设计分为三个角色&#xff0c;分别是社区员工、社区老人、社区系统管理员。在功能模块上分为三大块&#xff1a;人员管理模块、健康管理模块和活动管理模块。 人员管理模块能够对社区系统管理员信息、社区员工信息、社区老人信息进行管理。健康管理模…

鸿蒙应用App测试-专项测试(DevEco Testing)

注意&#xff1a;大家记得先学通用测试在学专项测试 鸿蒙应用App测试-通用测试-CSDN博客 注意&#xff1a;博主有个鸿蒙专栏&#xff0c;里面从上到下有关于鸿蒙next的教学文档&#xff0c;大家感兴趣可以学习下 如果大家觉得博主文章写的好的话&#xff0c;可以点下关注&am…

Jenkins应用详解(Detailed Explanation of Jenkins Application)

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页…

《大道平渊》· 廿肆 —— 欲望应当内敛,而非张扬。

《大道平渊》 廿肆 什么是欲望&#xff1f;哲学家德勒兹认为&#xff0c;欲望没有客体。 其本身&#xff0c;就是一种渴望维持自身的运动。 欲望是由生物的本性产生的、想达到某种目的的要求&#xff0c;无善恶之分。 . 那么欲望的本身是什么&#xff1f; 是一种情绪和思想…

支持向量机相关证明 解的稀疏性

主要涉及拉格朗日乘子法&#xff0c;对偶问题求解

ProtoBuf 快速上手

关于 ProtoBuf 的含义和安装推荐看&#xff1a;ProtoBuf 的含义和安装 步骤0&#xff1a;引⼊ ProtoBuf 包 <!-- protobuf ⽀持 Java 核⼼包 --> <dependency><groupId>com.google.protobuf</groupId><artifactId>protobuf-java</artifactI…

apt镜像源制作-ubuntu22.04

# 安装必要的软件 sudo apt-get install -y apt-mirror # 编辑/etc/apt/mirror.list,添加以下内容 set base_path /var/spool/apt-mirror # 指定要镜像的Ubuntu发布和组件-null dir jammy-updates main restricted universe multiverse # 镜像的Ubuntu发布和组件的URL-n…

TLU - Net:一种用于钢材表面缺陷自动检测的深度学习方法

摘要&#xff1a; 钢铁表面缺陷检测是钢铁板制造过程中的一个关键步骤。近年来&#xff0c;已经研究了许多基于机器学习的自动化视觉检测 (AVI) 方法。然而&#xff0c;由于 AVI 方法的训练时间和准确性问题&#xff0c;大多数钢铁制造行业仍然使用人工视觉检测。自动钢铁缺陷检…

设计模式讲解02—责任链模式(Chain)

1. 概述 定义&#xff1a;责任链模式是一种行为型模式&#xff0c;在这个模式中&#xff0c;通常创建了一个接收者对象的链来处理请求&#xff0c;该请求沿着链的顺序传递。直到有对象处理该请求为止&#xff0c;从而达到解耦请求发送者和请求处理者的目的。 解释&#xff1a;责…

Java | Leetcode Java题解之第542题01矩阵

题目&#xff1a; 题解&#xff1a; class Solution {static int[][] dirs {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};public int[][] updateMatrix(int[][] matrix) {int m matrix.length, n matrix[0].length;// 初始化动态规划的数组&#xff0c;所有的距离值都设置为一个很大…

ServletContext介绍

文章目录 1、ServletContext对象介绍1_方法介绍2_用例分析 2、ServletContainerInitializer1_整体结构2_工作原理3_使用案例 3、Spring案例源码分析1_注册DispatcherServlet2_注册配置类3_SpringServletContainerInitializer 4_总结 ServletContext 表示上下文对象&#xff0c;…

virtualBox部署minikube+istio

环境准备 virtualBox安装 直接官网下载后安装即可&#xff0c;网上也有详细教程。镜像使用的centos7。 链接&#xff08;不保证还可用&#xff09;&#xff1a;http://big.dxiazaicc.com/bigfile/100/virtualbox_v6.1.26_downcc.com.zip?auth_key1730185635-pWBtV8LynsxPD0-0-…

QT 实现绘制汽车仪表盘

1.界面实现效果 以下是具体的项目需要用到的效果展示,通常需要使用QPainter类来绘制各种图形和文本,包括一个圆形的仪表盘、刻度、指针和数字。 2.简介 分为以下几个部分,首先设置抗锯齿 painter.setRenderHint(QPainter::Antialiasing)。 QPainter p(this);p.setRender…

Node.js——fs模块-文件读取

1、文件读取&#xff1a;通过程序从文件中去除其中的数据 2、方法 方法 说明 readFile 异步读取 readFileSync 同步读取 createReadStrean 流式读取 3、readFile 异步读取 语法&#xff1a; 本文的分享到此结束&#xff0c;欢迎大家评论区一同讨论学习&#xff0c;下一…

cv2.threshold利用OSTU方法分割图像的前景和背景

OSTU方法&#xff0c;又称大津法或最大类间方差法&#xff0c;是一种在图像处理中广泛应用的自动阈值选择方法。该方法由日本学者大津&#xff08;Nobuyuki Otsu&#xff09;于1979年提出&#xff0c;旨在通过最大化前景与背景之间的类间方差来自动确定一个最佳阈值&#xff0c…

Perforce《2024游戏技术现状报告》Part2:游戏引擎、版本控制、IDE及项目管理等多种开发工具的应用分析

游戏开发者一直处于创新前沿。他们的实践、工具和技术受到各行各业的广泛关注&#xff0c;正在改变着组织进行数字创作的方式。 近期&#xff0c;Perforce发布了《2024游戏技术现状报告》&#xff0c;通过收集来自游戏、媒体与娱乐、汽车和制造业等高增长行业的从业者、管理人…

编写虚拟的GPIO控制器的驱动程序:和pinctrl的交互使用

往期内容 本专栏往期内容&#xff1a; Pinctrl子系统和其主要结构体引入Pinctrl子系统pinctrl_desc结构体进一步介绍Pinctrl子系统中client端设备树相关数据结构介绍和解析inctrl子系统中Pincontroller构造过程驱动分析&#xff1a;imx_pinctrl_soc_info结构体Pinctrl子系统中c…