前言
上篇介绍了SpringBoot集成SpringDoc的基础配置,本文重点解析常用注解、UI测试操作,助你快速理解提升开发效率。
SpringDoc中的基础注解
@SecurityScheme
这个注解是做什么的呢?下...
前言
SpringDoc中的基础注解
@SecurityScheme
这个注解是做什么的呢?下面我们来用一个例子简单的解释一下
想象我们的API接口就像一个个风格各异的房间:
有些是开放的茶室,谁都可以进(不需要认证的接口)
有些是机密档案室,只有授权才能进(需要认证的接口)
当我们想要保护这些机密房间时,需要两个关键步骤:
制作特殊的通行证
这就是@SecurityScheme干的事!它像是一个"安全通行证的制作说明书",告诉你:
通行证叫什么名字?(OAuth2、JWT等)
去哪里办理?(授权URL)
怎么办理?(提交什么信息)
有什么权限等级?(token能访问的范围)
给房间挂上"请出示通行证"的牌子
这是另一注解@SecurityRequirement做的事!它像在房间门口贴个告示:
“进入此房间需要’高级通行证’”(也就是指定这个接口需要哪种认证)
@SecurityScheme与@SecurityRequirement搭配完成获取通行证,给房间挂牌的整套流程,在这里我们先讲制作特殊通行证的流程,而给房间挂牌的流程放在后面
@SecurityScheme(
// 通行证名称 (后续在门禁系统识别时使用该名称)
name = "OAuth2",
/**
* 通行证类型 (选择哪种安防体系)
* 当前选择:OAUTH2协议认证体系
* 类似还有:API钥匙串(APIKEY)、基础密码锁(HTTP)等
*/
type = SecuritySchemeType.OAUTH2,
/**
* 发证流程说明
* 这里配置如何获取通行证的具体步骤
* 可以设置多种办证方式(当前选择最安全的授权码模式)
*/
flows = @OAuthFlows(
// 授权码模式 (最常用的安全认证流程)
authorizationCode = @OAuthFlow(
// 办证窗口:用户需要前往此地址提交申请
authorizationUrl = "https://auth.example.com/authorize",
// 领证窗口:凭申请码在此处兑换正式通行证(token)
tokenUrl = "https://auth.example.com/token",
/**
* 通行证权限范围说明
* 就像办公室门禁卡有不同权限级别:
* - 普通员工卡只能进入公共区域
* - 经理卡可进入敏感区域
* 这里定义该通行证能解锁哪些操作
*/
scopes = {
// 读取权限:可查看用户信息(普通权限)
@OAuthScope(name = "user:read", description = "读取用户信息"),
// 写入权限:可修改用户信息(高级权限)
@OAuthScope(name = "user:write", description = "修改用户信息")
}
)
)
)
不知道大家看上面这段代码加上注释能不能看懂,如果不懂的话,也没关系,我再给大家上一个效果图,大家就能看懂了

怎么说,大家看这个图能不能看懂呢?
其中有一个scopes属性,我觉得有必要跟大家解释一下:
scopes 就像给你的"钥匙"添加权限标签
每次申请钥匙时,系统会问:“这把钥匙想要哪些权限?”
界面上列出所有权限选项(如「只能看」「可以改」等 权限标签)
你勾选需要的权限 → 拿到带标签的钥匙
用这把钥匙开锁时:
锁上标着"钥匙需含「只能看」标签" → 开门
锁上要求"钥匙需含「可以改」标签" → 开门失败!
@OpenAPIDefinition
该注解用在配置类上方:主要作用是用来展示以及配置Swagger的一些基础信息
@OpenAPIDefinition(
// 基础信息
info = @Info(
title = "电商平台API",
version = "1.2.0",
description = "核心业务API",
contact = @Contact(name = "技术支持", url = "https://support.example.com"),
license = @License(name = "商业许可")
),
// 多环境配置
servers = {
@Server(url = "/api/v1", description = "默认网关路由"),
@Server(url = "http://dev.example.com", description = "开发环境")
},
// 全局标签
tags = {
@Tag(name = "会员中心", description = "用户账户相关接口"),
@Tag(name = "支付服务", description = "付款和退款处理")
},
// 外部文档
externalDocs = @ExternalDocumentation(
description = "数据库设计文档",
url = "https://docs.example.com/db-schema"
),
// 扩展信息
extensions = {
@Extension(name = "x-sla", properties = {
@ExtensionProperty(name = "response-time", value = "<500ms"),
@ExtensionProperty(name = "availability", value = "99.9%")
})
},
// 安全要求
security = @SecurityRequirement(name = "OAuth2")
)
@SecurityScheme(
name = "OAuth2",
type = SecuritySchemeType.OAUTH2,
flows = @OAuthFlows(
authorizationCode = @OAuthFlow(
authorizationUrl = "https://auth.example.com/authorize",
tokenUrl = "https://auth.example.com/token",
scopes = {
@OAuthScope(name = "user:read", description = "读取用户信息"),
@OAuthScope(name = "user:write", description = "修改用户信息")
}
)
)
)
@Configuration
public class SpringDocConfig {
}
大家先不要害怕哈,我这里由于是写教程,所以把大部分属性都写了上去,实际开发过程中根本用不到这么多属性,大部分属性大家了解下就好ლ(・ヮ・ლ)
info属性
info属性主要用于定义SwaggerUI界面的一些基础信息,这里不多讲,只需要放张图,大家就明白了

怎么样,是不是一目了然
servers属性
servers属性呢,其使用过PostMan或者ApiFox或者ApiPost的小伙伴,一眼就能认出来这个是做什么的,无非就是多环境配置嘛,选择不同的环境,请求不同的基础路径对吧ヽ( ̄~ ̄ )ノ

tags属性
这个属性其实是用来定义全局所有接口可以公用的tag标签的,这里不多讲,因为下面会讲到一个@Tag标签和一个方法上的tags属性,会详细展开讲,这里就不浪费篇幅了,只简单的提一嘴,也就是在这里定义的标签,无论在每个分组中是否有属于这个标签的方法,都会展现在每个组中,如下图:


externalDocs 属性
这个属性呢是用来链接外部文档的,可以将一些与这里有关联的外部文档放在这里,用户可以点击这里跳转到相应的文档,大家看下面的图,是不是很方便

extensions属性
这个属性就稍微复杂一点,他其实是用来定义一些自定义属性的,什么意思呢?
首先,我们使用SpringDoc的目的是什么呢?其中一个是不是可以生成接口文档?那么我现在有一个需求,就是我需要在生成的接口文档中添加一些自定义的信息,比如开发者姓名、开发小组、联系人、背锅侠之类的,我们该咋写,我们发现如果仅仅使用官方提供的标准属性,没地方写,那么自定义属性在这个时候就派上用场了,不多说废话,直接上代码,大家一看就明白
@OpenAPIDefinition(
extensions = {
@Extension(properties = {
@ExtensionProperty(name = "x-team", value = "billing-team"),
@ExtensionProperty(name = "x-sla", value = "99.9%")
})
}
)
{
"openapi": "3.0.1",
"info": {
"title": "API文档",
"version": "1.0.0"
},
"paths": { ... },
"components": { ... },
"x-team": "billing-team",
"x-sla": "99.9%"
}
大家明白了吗,当然,我这里展示的仅仅是最简单的一种,还有很多复杂场景,我这里了就不展开了,毕竟用的也不多,如果展开的话太多废话,文章会拉得很长,大家如果有兴趣,可以私聊我,我会对有需要的小伙伴单独解释
security
security 是做什么的呢,简单来说他是用来做权限控制的,security 属性指定访问该接口所需的安全认证方案。当客户端调用此接口时,必须提供符合声明的认证凭证(如 OAuth2 令牌、API Key 等),否则请求会被拒绝。
什么意思呢?其实上面我们在讲@SecurityScheme的时候已经讲过了一个制作钥匙,加锁的流程,上面说过了@SecurityScheme是用来制作钥匙的,那么谁是用来加锁的呢?诶,就是这里了,嘿嘿
下面我仅仅简单介绍下代码的书写方式以及基础概念,因为如果完全没有接触过权限认证的小伙伴,这里是不太好理解的,所以可以先跳过,等大家明白了权限认证,在回过头来看这里就很容易了,而接触过权限认证的小伙伴,相信大家看一下下面的代码,应该可以明白个七七八八
@Configuration // 标识为 Spring 配置类
@OpenAPIDefinition( // 定义 OpenAPI 全局规范
security = @SecurityRequirement(name = "OAuth2") // ⭐️全局安全要求:所有接口默认需 OAuth2 认证
)
@SecurityScheme(
name = "OAuth2",
type = SecuritySchemeType.OAUTH2,
flows = @OAuthFlows(
authorizationCode = @OAuthFlow(
authorizationUrl = "https://auth.example.com/authorize",
tokenUrl = "https://auth.example.com/token",
scopes = {
@OAuthScope(name = "user:read", description = "读取用户信息"),
@OAuthScope(name = "user:write", description = "修改用户信息")
}
)
)
)
public class SpringDocConfig {
}
大家看上面这个例子,我告诉程序我需要OAuth2这个类型的钥匙,并且已经使用@SecurityScheme定义了获取OAuth2这种钥匙的方式,大家看看效果

看,当我们配置了这个之后,页面上出现了一把锁,点击这把锁,就会弹出这个页面让用户提供认证信息,页面中还会有我们配置的认证流程之类的,只有用户按照要求提供了认证信息,通过认证之后,访问我们的接口,才可以正常访问,所以,大家懂了吗
另外这里有几个注意点
页面上展示的锁的状态:
锁打开表示:未认证:未提供有效凭证或未完成OAuth2流程,无法正常访问接口
锁关闭表示:已认证:已获得有效访问令牌,可以正常访问接口
在配置类上加了security = @SecurityRequirement(name =“OAuth2”)之后表示整个环境中所有接口默认都需要认证才可以访问,这明显不合理,针对这种结果,我们有三种处理方式
第一种是我们在这里开启全局认证后,在后面不需要的方法上面添加@SecurityRequirements()注解即可取消掉该接口的权限认证(后面会讲到)
第二种是在Controller类的上方添加@SecurityRequirements()注解即可取消掉该类所有接口的权限认证(后面会讲到)
第三种方式是这里不要添加这个属性(不开启全局认证),只使用@SecurityScheme注解定义认证方式,等到后面需要认证的接口上面单独开启认证(一样后面会讲)
第二个需要注意的点是这里可以添加多个security 属性,让用户选择使用哪种方式进行认证
@Tag
该注解用在Controller类上方:主要作用是标志当前Controller在UI界面的显示名称,以及当前Controller的描述
对应SpringFox的@Api注解
同时SpringDoc中也支持使用@Api这个注解,只是相对来说更推荐SpringDoc专属的注解
@RestController
@RequestMapping("/api/member")
@Tag(
// 当前Controller在UI界面所显示的名称
name = "会员controller",
// 当前Controller在UI界面的描述
description = "会员controller",
// extensions 用于添加自定义属性,而 @Extension 就是定义这些扩展属性的关键注解。
// OpenAPI 规范提供了标准字段(如 name, description),但实际项目中可能需要额外的元数据(如排序、权限、业务分类等)。
// 扩展属性以 x- 前缀开头(如 x-order),是 OpenAPI 允许的自定义字段,不影响规范核心功能。
// 以x-order举例,x-order属性用于定义当前Controller在当前分组显示的顺序,值越小显示越靠前。
extensions = {
@Extension(name = "x-order", properties = @ExtensionProperty(name = "priority", value = "0"))
}
)
public class MemberController {
@GetMapping("/list")
@Operation(summary = "会员列表", description = "会员列表")
public String list(@Parameter(description = "memberName", required = true) String memberName) {
return "请求成功";
}
}
举个栗子
基础属性很简单,所以不多啰嗦,这里主要举例说明自定义属性,以x-order举例,如果当前分组下我有两个Controller,一个MemberController,一个MemberAccountController,并且两个Controller都不设置显示顺序,那么他就按照默认顺序进行显示,如下:
但是如果我给MemberController设置一个显示顺序属性,设置为0,会怎样呢?大家看:

发现了吗,MemberController跑到前面去了,所以大家明白了吗( ̄▽ ̄)ノ
@Operation
@RestController
@RequestMapping("/api/member")
@Tag(
// 当前Controller在UI界面所显示的名称
name = "会员controller",
// 当前Controller在UI界面的描述
description = "会员controller"
}
)
public class MemberController {
@GetMapping("/list")
@Operation(
// 接口摘要说明(简洁描述接口功能)
summary = "会员列表",
// 详细接口描述(可包含具体行为说明)
description = "会员列表",
// 接口所属标签
tags = {"测试会员标签"}, // 支持多标签,如{"认证","公共接口"}
// 标记接口是否已废弃(true时UI会有删除线提示,并且接口颜色会变为灰色)
deprecated = false, // 默认false
// 是否在文档中隐藏该接口(true时不在UI显示)
hidden = false, // 默认false
// 接口安全需求(声明此接口需要何种认证方式)
security = @SecurityRequirement(name = "OAuth2") // 对应securitySchemes定义的方案名
)
public String list(@Parameter(description = "memberName", required = true) String memberName) {
return "请求成功";
}
}
上面这个注解中,像summary、description、deprecated 、hidden等属性,配合注释,应该不用解释,相信以大家的聪明才智很容易就理解了,这里着重说一下tags与security
tags属性
先说tags,相信大家发现了,tags与Controller上面的@Tag很像,那么他们有什么关系,有什么区别呢?先上图,大家对照着看会更容易理解


大家看,由于我同时使用了@Tag注解和tags属性,于是发生了一个相同的接口出现在了两个不同的标签组中的情况,于是我们得到一个结论,当类的上方与方法上方同时存在tag相关的内容时,涉及到的方法会同时出现在两个位置
那么如果我们没有在类的层面使用@Tag,仅仅在方法层面使用了tags这个属性会怎样呢?


看,会员Controller消失了ヽ(°〇°)ノ,于是我们又得到一个结论,当类的上方没有@Tag注解,只有方法上方的注解存在tags属性时,该方法只会出现在方法指定的tags中,同时类的模块会隐藏
那我,我们再想想,上方这个类中只有一个方法,并且类上方没有添加@Tag注解,而方法上方添加了tags属性,所以类的模块被隐藏了,只出现了我们自定义的标签,那我们如果在上方的基础上稍微改一下,就是在类里面如果有两个或两个以上的方法,那么没有自定义tags属性的方法会出现在哪里呢?我们来看效果


大家猜到了吗?如果这个类上方没有添加@Tag注解,但是这个类中存在没有自定义标签属性的方法,那么就会出现一个以Controller名字为命名的标签来展示这些其他方法
可能有点绕,但是我相信大家看图应该很容易理解,同时注意tags可以写多个标签哦
我的习惯是,如果在类的层面定义了@Tag,就不在方法层面使用tags属性,当然具体如何使用还是看大家的习惯(‘-’*ゞ
security属性
大家看到这个,是不是很熟悉呢,是的,这个跟上面配置类@OpenAPIDefinition注解上的security属性以及@SecurityScheme注解都是配套使用的,大家只要搞懂了上面,这里几句话就能解释的明白
简单的说,放在配置类上的@OpenAPIDefinition注解的security属性是用来全局开启认证的,而放在这里的@Operation注解的security属性是针对某个方法开启认证的,当你没有开启全局认证的时候,只要你使用@SecurityScheme注解配置了具体的获取认证的方式,这里就可以使用这个属性来对这个方法单独开启权限认证了
//全局未开启认证,但是配置了认证方式,该方法需要开启认证
@Operation(
// 接口摘要说明(简洁描述接口功能)
summary = "会员列表",
// 详细接口描述(可包含具体行为说明)
description = "会员列表",
// 接口所属标签
tags = {"测试会员标签"}, // 支持多标签,如{"认证","公共接口"}
// 接口安全需求(声明此接口需要何种认证方式)
// 这里支持多种认证方式(注意这里要用到的所有认证方式一定要现在配置类中定义才可以)
security = {
@SecurityRequirement(name = "OAuth2"),
@SecurityRequirement(name = "ApiKey")
}
)
public String list(@Parameter(description = "memberName", required = true) String memberName) {
return "请求成功";
}

@SecurityRequirements
这个注解呢,其实和@OpenAPIDefinition注解的security属性和@Operation注解的security属性功能差不多,大家理解了上面的两个内容,这里很容易理解,只不过他是一个单独的注解,并且功能更全面一些
第一种使用方式:不包含属性(表示清空权限认证)
@RestController
@RequestMapping("/api/member")
@SecurityRequirements()
public class MemberController {
@GetMapping("/list")
@Operation(
// 接口摘要说明(简洁描述接口功能)
summary = "会员列表",
// 详细接口描述(可包含具体行为说明)
description = "会员列表"
)
//注意这个注解可以单独放在类上或者单独放在方法上,但是如果类上面已经覆盖了,这里就没必要在加了
//@SecurityRequirements()
public String list(@Parameter(description = "memberName", required = true) String memberName) {
return "请求成功";
}
}
这个注解的这种使用方式是用来覆盖全局认证的,什么意思呢?
上面讲过,配置类中可以使用@OpenAPIDefinition的security属性来配置全局接口都需要进行安全认证,但是不太合理,如果我某个接口或者某个Controller不需要进行安全认证,要怎么做?
这个时候就可以用这个注解进行清除安全认证了,当这个注解加载类上,那么这个类的所有接口都不需要进行安全认证了,当这个接口加在方法上,那么单独这个方法不需要进行安全认证
第二种使用方式:包含属性(表示当前接口可以使用哪些权限认证,覆盖全局配置)
@GetMapping("/list")
@Operation(
// 接口摘要说明(简洁描述接口功能)
summary = "会员列表",
// 详细接口描述(可包含具体行为说明)
description = "会员列表"
)
@SecurityRequirements({
@SecurityRequirement(name = "API-Key"), // 要求1:API-Key
@SecurityRequirement(name = "OAuth2", scopes = {"user:write"}) // 要求2:OAuth2且具有user:write权限
})
public String list(@Parameter(description = "memberName", required = true) String memberName) {
return "请求成功";
}
大家看上面这种使用方式,它其实和@OpenAPIDefinition注解的security属性和@Operation注解的security属性用法基本一样了,表示访问这个接口,可以使用两种认证方式(任选其一即可),但是当使用OAuth2认证方式时需要具有user:write权限
@Parameter
@GetMapping("/list")
@Operation(
// 接口摘要说明(简洁描述接口功能)
summary = "会员列表",
// 详细接口描述(可包含具体行为说明)
description = "会员列表"
)
@SecurityRequirements({
@SecurityRequirement(name = "API-Key"), // 要求1:API-Key
@SecurityRequirement(name = "OAuth2", scopes = {"user:write"}) // 要求2:OAuth2且具有payment:write权限
})
public String list(
@Parameter(description = "memberName", required = true) String memberName,
@Parameter(
// 定义参数的名称
name = "memberType",
// 参数的详细描述
description = "会员类型:0-普通,1-VIP,2-管理员",
// 提供参数示例值
example = "1",
// 参数是否必填
required = true,
// 定义参数的数据类型和约束
schema = @Schema(type = "integer", allowableValues = {"0", "1", "2"}),
// 指定参数传递的位置
in = ParameterIn.QUERY
) String memberType) {
return "请求成功";
}
@Parameter注解呢主要是针对接口参数使用的,如果不加这个注解,那么首先这个参数没有一个解释,调用接口的时候,会很迷茫(这什么鬼玩意),于是就需要这个注解
这个注解中的name、description、example、required等属性不用多说,配合注释,大家一看就能理解
这里主要说一说schema和in属性
schema
这个属性主要是用来对参数进行一系列限制的
type = “integer”,表示当前参数只可以使用integer类型
allowableValues = {“0”, “1”, “2”},表示取值范围,限定参数只允许取值为 0, 1, 2(对应普通用户、VIP、管理员)
in
这个属性主要是指定参数传递的位置
QUERY:参数需通过 URL 查询字符串传递(如 /api/list?userType=1)。
PATH:参数须通过URL 路径中的变量传递(如/api/user/profile/456)。
HEADER:参数须通过 HTTP 头传递(如X-Auth-Token: abcde12345)。
COOKIE:参数须通过浏览器 Cookie 传递(如:Cookie: sessionId=9a8b7c6d5e)
@Schema
@Schema(description = "会员基础信息模型")
public class Member {
/** 会员ID */
@Schema(
description = "会员唯一ID", // 字段描述:说明字段含义
example = "1", // 示例值:文档中显示的示例数据
accessMode = Schema.AccessMode.READ_ONLY, // 访问模式:表示该字段仅用于响应(不可修改)
minimum = "10000", // 最小值:限定ID最小值为10000
maximum = "99999", // 最大值:限定ID最大值为99999
type = "integer" // 数据类型:限定为整数类型
)
private Integer memberId;
/** 会员姓名 */
@Schema(
description = "用户名", // 字段描述
minLength = 4, // 最小长度:用户名至少4个字符
maxLength = 20, // 最大长度:用户名最多20个字符
pattern = "^[a-zA-Z0-9_]+$", // 正则规则:只允许字母/数字/下划线
defaultValue = "guest", // 默认值:未传值时使用默认值"guest"
type = "string"
)
private String memberName;
/** 会员手机号 */
@Schema(description = "会员手机号",type = "string")
private String memberPhone;
/** 会员邮箱 */
@Schema(description = "会员邮箱",type = "string")
private String memberEmail;
/** 会员地址 */
@Schema(description = "会员地址",type = "string")
private String memberAddress;
/** 会员类型 */
@Schema(
description = "会员类型", // 字段描述:说明字段含义
type = "short",// 字段类型限制
allowableValues = {"0", "1", "2"}// 限定范围
)
private Short memberType;
@Schema(
description = "角色列表", // 字段描述
implementation = Role.class, // 关联模型:说明数组元素对应的数据模型
type = "array" // 数据类型:明确声明为数组类型(可省略)
)
private List<Role> roles;
}
这个注解很简单,相信大家看上面的代码示例,加上注释应该能够一目了然
下面给大家列出几个使用场景吧:
场景一:当标注了@Schema的实体类作为参数使用时
//添加会员
@GetMapping("/add")
@Operation(
// 接口摘要说明(简洁描述接口功能)
summary = "添加会员",
// 详细接口描述(可包含具体行为说明)
description = "添加会员"
)
public String add(Member member) {
return "请求成功";
}
页面显示效果如下:
场景二:当标注了@Schema的实体类作为返回值使用时
@GetMapping("/detail")
@Operation(
// 接口摘要说明(简洁描述接口功能)
summary = "会员详情",
// 详细接口描述(可包含具体行为说明)
description = "会员详情"
)
public Member detail(@Parameter(description = "memberId", required = true) Integer memberId) {
return new Member();
}
效果如下:
嘿嘿,一样的效果
怎么样,是不是很简单?一看就懂
@ParameterObject
这个注解相当简单,他配合上面的@Schema进行使用,我只需要上几张图,加几句话解释,大家瞬间就明白了
我们来看两段代码
//第一段代码,不加@ParameterObject注解
@GetMapping("/add")
@Operation(
// 接口摘要说明(简洁描述接口功能)
summary = "添加会员",
// 详细接口描述(可包含具体行为说明)
description = "添加会员"
)
public String add(Member member) {
return "请求成功";
}
看看效果:

//第二段代码,加了@ParameterObject注解
@GetMapping("/add")
@Operation(
// 接口摘要说明(简洁描述接口功能)
summary = "添加会员",
// 详细接口描述(可包含具体行为说明)
description = "添加会员"
)
public String add(@ParameterObject Member member) {
return "请求成功";
}
看看效果:

欧吼,大家发现了什么?没错,当一个参数类型是一个实体类,并且这个实体类内部使用@Schema对字段进行了标注时,如果不加@ParameterObject,那么这个参数就还是以一个实体类的形式进行传递,但是如果加了@ParameterObject,那么参数会自动按照实体类中的配置进行解构,然后进行传递
怎么样,是不是超简单(・ε・`)
@ApiResponse
@PostMapping("/create")
@Operation(summary = "创建新用户")
@ApiResponse( // 描述接口的返回状态响应
responseCode = "201", // HTTP响应状态码(如201表示创建成功)
description = "用户创建成功", // 响应描述信息
content = @Content( // 定义响应体内容
mediaType = "application/json", // 响应内容类型(JSON格式)
schema = @Schema(implementation = UserResult.class) // 关联的数据模型
)
)
@ApiResponse( // 第二个响应声明
responseCode = "400", // 400表示客户端请求错误
description = "无效的用户数据", // 描述问题原因
content = @Content( // 错误响应内容
mediaType = "application/json",
schema = @Schema(implementation = ErrorResponse.class) // 错误模型
)
)
public ResponseEntity<?> createUser(...) { ... }
Emmm…
这个注解,怎么说呢,是不是一看就大概能猜出来他是干啥的?是的,他是用来定义json文档的返回结果的,如下:
/create-user:
post:
responses:
'201':
description: 用户创建成功
content:
application/json:
schema:
$ref: '#/components/schemas/UserResult' # 指向UserResult模型
'400':
description: 无效的用户数据
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse' # 指向错误模型
这个没什么难的,但是有一点要注意,大家千万不要把这个注解当成这个方法的真正返回结果,OpenAPI的注解,它的影响力只到文档层面,不会对业务层面的返回有任何实际的效果,这个接口最终要返回什么,还是要看大家方法中的实际返回
@Hidden
@Hidden // 隐藏整个控制器
@RestController
public class InternalController {
@GetMapping("/secret")
@Hidden // 隐藏单个方法
public String secretMethod() {
return "秘密数据";
}
}
这个注解一看就懂他是干啥的,无非就是在UI界面隐藏这个方法或者Controller类的显示嘛,其实就是用在SpringDoc在配置扫描时,扫描到了这个类或者方法,但是这个类或者方法不想展示,这个时候@Hidden就派上用场了
总结
本文把 SpringDoc 的核心注解和在 Swagger UI 里的效果都给大伙儿掰扯清楚了。
本来想一口气把 Swagger UI 的操作也手把手教了,结果光注解就唠了这么老长!键盘都让我敲出火星子了
下期咱专门肝操作指南!点个关注不迷路,更新时第一时间踹你来看~
如果觉得有用,赶紧点赞收藏 !给我码字加个氮气加速,我们下期见!(ง •_•)ง