【OpenAPI】Spring3 集成 OpenAPI 生成接口文档

Spring3 集成 OpenAPI 生成接口文档

1. 依赖

Spring 版本:3.0.5

Java 版本:jdk21

OpenAPI 依赖:

<!-- https://mvnrepository.com/artifact/org.springdoc/springdoc-openapi-starter-webmvc-ui -->
<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
    <version>2.6.0</version>
</dependency>

官网:OpenAPI 规范 | OpenAPI 官方文档中文版 (xiniushu.com)

不要包含其他的接口文档的框架,大概率是冲突的

目前我还没有找到 Spring3 的其他接口文档方案,swagger2 和 swagger3 都因为不兼容搞不了;

2. 配置文件

默认整个类路径全扫描

@Configuration
public class OpenApiConfig {

    @Bean
    public OpenAPI springOpenAPI() {
        return new OpenAPI().info(new Info()
                .title("SpringDoc API Test")
                .description("SpringDoc Simple Application Test")
                .version("1.0"));
    }

}

3. 关键用法

3.1 Tag 注解

对接口文档进行分组,一个 controller 类为单位

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1")
@Tag(name = "xxx")
public class xxxController {
    
}

3.2 Operation 注解

对接口进行描述,一个目标方法为单位

@PostMapping("/create")
@Operation(summary = "创建一个 XXX")
public SystemJsonResponse<CustomClass> createXXX() {
    
}

3.3 Parameter 与 Header 注解

Parameter 描述一个接口的参数与路径参数,Header 描述一个接口的请求头,他们作用于目标方法的形参

@PostMapping("/get/{id}")
@Operation(summary = "获得一个 XXX")
public SystemJsonResponse<CustomClass> getXXX(@RequestHeader("token") @Header(description = "token") String token,
                                              @PathVariable("id") @Parameter(description = "id") Long id,
                                              @RequestParam(name = "state") @Parameter(description = "state") Integer state) {
}

3.4 Schema 注解

Schema 描述一个数据模型,也可以描述一个属性,作用于类或者字段

name 可指定属性的名称,description 是属性的描述

name 作为数据模型(类)的名称,description 是数据模型(类)的描述

属性得 public 或者有 public 的 Getter 和 Setter,否则会被标注只读或只写,如果都没有则直接忽略,如果一个数据模型属性都没有,忽略这个数据模型,复杂点的情况还会出现莫名其妙的现象

总而言之规范地写就没问题,框架也没义务和精力去控制各种奇奇怪怪地情况,我们也没必要总结

@TableName(value ="user")
@Schema(description = "用户")
@Data
public class User implements Serializable {

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

    @Schema(description = "昵称")
    private String nickname;

    private static final long serialVersionUID = 1L;
}

3.5 SchemaProperty 注解

SchemaProperty 作用于一个字段,无法设置属性名,name 作为属性的描述

这个注解不能作用于自定义的数据模型,自定义对象会被认定为 string,因为这个注解就是作用于普通的字段,并不支持递归扫描,这个时候应该用 Schema

  • 建议都用 Schema,SchemaProperty 功能还是太弱了
@SchemaProperty(name = "ID")
private Long id;

3.6 Hidden

作用于字段,表示忽略字段

@Hidden
private String nickname;

3.7 nullable = true

注解参数设置这个代表参数可以为 null

@Schema(description = "昵称", nullable = true)
private String nickname;

3.8 响应的数据模型

OpenAPI 提供了 @ApiRespnse 注解,但是很不方便,不如直接去 Postman 或者 Apifox 上进行操作,理想状态就是直接扫描出「请求body对象」和「响应body对象」 Schema 注解描述的数据模型

请求的话,作为参数是类型是确定的,OpenAPI 框架自然是扫描的到的,但是响应的数据模型,一般是统一响应格式的:

@Schema(name = "统一响应")
@NoArgsConstructor
@Getter
public class SystemJsonResponse implements Serializable {

    private static final long serialVersionUID = 1L;

    @JsonInclude
    @Schema(description = "状态码")
    private int code;

    @JsonInclude
    @Schema(description = "描述语")
    private String message;

    @JsonInclude
    @Schema(nullable = true)
    private Object data;
}

返回的时候,构造 json 是没问题的,但是框架扫描不出来这个 data 数据模型,因为框架只知道 data 是 Object 类型

你可能想问:“框架拿到 data 用 getClass 不就知道了吗?”

是的,但是接口文档生成是在这个接口被调用之前,所以并没有一个 data 数据提供给框架

你很容易想到用范型来定义统一响应:

@Schema(name = "统一响应")
@NoArgsConstructor
@Getter
public class SystemJsonResponse<T> implements Serializable {

    private static final long serialVersionUID = 1L;

    @JsonInclude
    @Schema(description = "状态码")
    private int code;

    @JsonInclude
    @Schema(description = "描述语")
    private String message;

    @JsonInclude
    @Schema(nullable = true)
    private T data;
}

但是实践这个方式,你会发现生成的接口文档,data 仍然是 object

其实原因很简单,用 @Schema 将 SystemJsonResponse 描述作一个固定的数据模型,那每个以此对象为返回值的目标方法,接口文档都直接使用这个数据模型

而泛型在定义的时候,本质还是 Object

解决方案也很简单,去掉 @Schema 即可,这样框架扫描目标方法返回的 SystemJsonResponse<CustomClass> 的时候,都会创建一个新的数据模型,这个时候就可以通过泛型类型确定准确的响应数据模型了,若存在一个一模一样的才会复用

注意:

  1. 不支持通配符:SystemJsonResponse<?>
  2. SystemJsonResponse<? extends CustomClass>,则仅仅扫描 CustomClass

3.9 补充

GetMapping 的接口,RequestBody 会被扫描成 queryString,而不是 json

4. 访问

http://[host]:[post]/swagger-ui/index.html

http://[host]:[post]/v3/api-docs

在这里插入图片描述

更多细节需要去查去探索这里不一一罗列

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

如何通过 PhantomJS 模拟用户行为抓取动态网页内容

引言 随着网页技术的不断进步&#xff0c;JavaScript 动态加载内容已成为网站设计的新常态&#xff0c;这对传统的静态网页抓取方法提出了挑战。为了应对这一挑战&#xff0c;PhantomJS 作为一个无头浏览器&#xff0c;能够模拟用户行为并执行 JavaScript&#xff0c;成为了获…

GeoPandas在地理空间数据分析中的应用

GeoPandas是一个开源的Python库&#xff0c;专门用于处理和分析地理空间数据。它建立在Pandas库的基础上&#xff0c;扩展了Pandas的数据类型&#xff0c;使得用户能够在Python中方便地进行GIS操作。GeoPandas的核心数据结构是GeoDataFrame&#xff0c;它是Pandas的DataFrame的…

uniapp小程序,使用腾讯地图获取定位

本篇文章分享一下在实际开发小程序时遇到的需要获取用户当前位置的问题&#xff0c;在小程序开发过程中经常使用到获取定位功能。uniapp官方也提供了相应的API供我们使用。 官网地址&#xff1a;uni.getLocation(OBJECT)) 官网获取位置的详细介绍这里就不再讲述了&#xff0c;大…

红光一字激光器在工业中的性能指标怎样

红光一字激光器作为现代工业中不可或缺的重要设备&#xff0c;以其独特的性能和广泛的应用场景&#xff0c;成为众多行业的首选工具。本文就跟大家详细探讨红光一字激光器在工业中的性能指标&#xff0c;以及这些指标如何影响其在实际应用中的表现。 光束质量 红光一字激光器以…

【痛点解决】跨网跨区域的文件传输摆渡解决办法指南

跨网跨区域的文件传输摆渡&#xff0c;顾名思义就是需要跨越不同网络、不同地区&#xff0c;或者是不同安全域的文件传输&#xff0c;一般有这样传输需求的机构&#xff0c;在组织架构、网络结构&#xff0c;或者传输需求上&#xff0c;都会比较复杂。 跨网跨区域文件传输是什…

51单片机快速入门之定时器和计数器

51单片机快速入门之定时器 断开外部输入 晶振振荡 假设为 12MHz 12分频之后,为1MHz 当其从0-65536 时,需要65536μs 微秒 也就是65.536ms 毫秒 溢出(值>65536 时)>中断>执行中断操作 假设需要1ms后产生溢出,则需要设置初始值为64536 此时定时器会从 64536 开始计…

掌握 JavaScript ES6+:现代编程技巧与模块化实践

掌握 JavaScript ES6&#xff1a;现代编程技巧与模块化实践 一 . 变量声明 let二 . 声明常量 const三 . 模板字符串四 . 函数的参数默认值五 . 箭头函数六 . 对象初始化七 . 解构7.1 接收 JSON 对象7.2 接收数组 八 . 延展操作符九 . 导入和导出9.1 方式一9.2 方式二 这篇文章我…

Android视频编辑:利用FFmpeg实现高级功能

在移动设备上进行视频编辑的需求日益增长&#xff0c;用户期望能够在智能手机或平板电脑上轻松地编辑视频&#xff0c;以满足社交媒体分享或个人存档的需求。Android平台因其广泛的用户基础和开放的生态系统&#xff0c;成为视频编辑应用的理想选择。FFmpeg&#xff0c;作为一个…

Maven入门学习笔记

一、maven介绍 Maven是一款自动化构建工具&#xff0c;专注服务于JAVA平台的项目构建和依赖管理。在javaEE开发的历史上构建工具的发展也经历了一系列的演化和变迁。 管理jar包 当我们使用SSM之后我们就需要使用非常多的jar包 没有maven找jar包非常的麻烦。 使用maven下载…

简单了解 JVM

目录 ♫什么是JVM ♫JVM的运行流程 ♫JVM运行时数据区 ♪虚拟机栈 ♪本地方法栈 ♪堆 ♪程序计数器 ♪方法区/元数据区 ♫类加载的过程 ♫双亲委派模型 ♫垃圾回收机制 ♫什么是JVM JVM 是 Java Virtual Machine 的简称&#xff0c;意为 Java虚拟机。 虚拟机是指通过软件模…

WPF DataGrid 列表中,DataGrid.Columns 列根据不同的值显示不同内容

需求&#xff1a;在WPF DataGrid 控件中&#xff0c;有以下列&#xff0c;绑定了一个LogType&#xff0c;值分别是0,1,2&#xff0c;根据不同的值&#xff0c;显示不同的内容以及背景 <DataGrid ItemsSource"{Binding EventLog}"><DataGrid.Columns><…

代码管理工具——git及阿里云云效的使用(包含git的使用及云效自动化部署)

1、做项目开发时都会用到代码管理工具,像是我之前使用过gitHub,Visual Studio等一些代码管理工具&#xff0c;这里介绍的是阿里云云效的使用。 2、首先登录阿里云云效&#xff0c;登录进去之后会看到公司给你开放的一个仓库。 3、进入仓库&#xff0c;点击克隆/下载&#xff0…

Google大数据架构技术栈

数据存储层 Colossus Colossus作为Google下一代GFS&#xff08;Google File System&#xff09;。 GFS本身存在一些不足 单主瓶颈 GFS 依赖单个主节点进行元数据管理&#xff0c;随着数据量和访问请求的增长&#xff0c;出现了可扩展性瓶颈。想象一下&#xff0c;只有一位…

网红酒店|基于java的网红酒店预定系统(源码+数据库+文档)

酒店预定|网红酒店|网红酒店预定系统 目录 基于java的网红酒店预定系统 一、前言 二、系统设计 三、系统功能设计 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂码农|毕设布道师&am…

R语言统计分析——功效分析(比例、卡方检验)

参考资料&#xff1a;R语言实战【第2版】 1、比例检验 当比较两个比例时&#xff0c;可使用pwr.2p.test()函数进行功效分析。格式为&#xff1a; pwr.2p.test(h, n, sig.level, power, alternative) 其中&#xff0c;h是效应值&#xff0c;n是各相同的样本量。效应值h的定义如…

智能头盔语音识别声控芯片,AI离线语音识别ic方案,NRK3301

头盔是交通事故中保护电动车车主安全的最后一道屏障。为了增加骑行用户的安全保护&#xff0c;改善骑行用户的出行体验&#xff0c;让用户从被动使用头盔到主动佩戴头盔&#xff0c;头盔厂家与九芯电子合作&#xff0c;推出了语音智能头盔&#xff0c;它具备首家骑行专用的智能…

C++核心编程和桌面应用开发 第三天(C和C++的封装)

目录 1.封装 1.1C语言封装缺陷 1.2C下的封装 1.3封装的访问权限 2.C中struct和class的区别&#xff1a; 1.封装 1.1C语言封装缺陷 1.2C下的封装 优点1&#xff1a;将属性和行为作为整体&#xff0c;表现生活中的事务 优点2&#xff1a;将属性和行为加以访问权限控制 1…

vue的路由

v2用3版本&#xff0c;v3用4版本 import Vue from vue import VueRouter from vue-router Vue.use(VueRouter) const routes [] const router new VueRouter({ routes }) export default router import Vue from vue import App from ./App.vue import router from /router V…

kkFileView PDF Image Mode Preview BUG

kkFileView PDF & Image Mode Preview BUG lazyload.js officePicture.ftl pdf.ftl kkFileView getCorsFile?urlPath 会触发SSRF漏洞 kkFileView SSRF-CSDN博客 commonHeader.ftl initWaterMark() 修改代码的工作量&#xff0c;主要是先部署项目&#xff0c;解…

微信小程序开发——比较两个数字大小

在这里我们使用的工具是 需要自行安装和配置。 在微信小程序中比较两个数字大小有以下几种方式&#xff1a; 一、普通条件判断 在小程序的.js 文件中&#xff0c;先定义两个数字&#xff0c;如let num1 5; let num2 3;。通过if - else if - else语句&#xff0c;根据num1与…