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

Spring3 集成 OpenAPI 生成接口文档

1. 依赖

Spring 版本:3.0.5

Java 版本:jdk21

OpenAPI 依赖:

xml 复制代码
<!-- 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. 配置文件

默认整个类路径全扫描

java 复制代码
@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 类为单位

java 复制代码
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1")
@Tag(name = "xxx")
public class xxxController {
    
}

3.2 Operation 注解

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

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

3.3 Parameter 与 Header 注解

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

java 复制代码
@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,否则会被标注只读或只写,如果都没有则直接忽略,如果一个数据模型属性都没有,忽略这个数据模型,复杂点的情况还会出现莫名其妙的现象

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

java 复制代码
@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 功能还是太弱了
java 复制代码
@SchemaProperty(name = "ID")
private Long id;

3.6 Hidden

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

java 复制代码
@Hidden
private String nickname;

3.7 nullable = true

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

java 复制代码
@Schema(description = "昵称", nullable = true)
private String nickname;

3.8 响应的数据模型

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

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

java 复制代码
@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 数据提供给框架

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

java 复制代码
@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

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

相关推荐
小bo波6 小时前
枚举实战
java·设计模式·枚举·后端开发·代码重构
夜微凉47 小时前
三、Spring
java·后端·spring
橘右今7 小时前
2026 Java后端高频面试宝典
java·开发语言·面试
xyzzklk8 小时前
解决Salesforce无法向外发送邮件
android·java·开发语言·网络·crm·salesforce·客户关系管理
biubiubiu07068 小时前
SpringBoot关于外部化配置
java·spring boot·spring
Full Stack Developme8 小时前
Spring Bean 依赖注入
python·spring·log4j
zzz_23688 小时前
【Spring】面试突击系列(二):SpringBoot 入门与自动配置原理
java·spring boot·spring
Full Stack Developme8 小时前
Spring AOP 与 AspectJ
java·后端·spring
快乐的木子李9 小时前
最新版Maven免安装配置教程
java·maven
wuminyu10 小时前
Java锁机制之Java对象重量级锁源码剖析
java·linux·c语言·jvm·c++