> 技术文档 > SpringDoc详解(从入门到精通,一文搞定)

SpringDoc详解(从入门到精通,一文搞定)


Swagger3.0—OpenAPI3.0

Sawgger3.0又叫OpenAPI3.0,对应的依赖包有两种,分别为Springfox以及SpringDoc,但是Springfox以及停止维护,无法支持SpringBoot3,以下围绕SpringDoc进行讲解。


文章目录

  • Swagger3.0---OpenAPI3.0
  • 一、集成SpringDoc
    • 1.引入依赖
    • 2.配置文档信息
    • 3.访问(ip:端口/swagger-ui/index.html)
    • 4.测试(Post请求为例)
    • 注意:
  • 二、常用注解
    • 1.常用注解汇总
    • 2.常用注解示例
      • @Tag
      • @Operation
      • @Parameter
      • @Parameters
      • @Schena
      • @ApiRequest/@Content
      • @ApiRequests
      • @ResquestBody
      • `结合使用`
      • 扩展@ResponseStatus
  • 三、分组
  • 四、认证授权

一、集成SpringDoc

1.引入依赖

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

2.配置文档信息

后面会解释配置信息与文档的对应关系

package org.example.config;import com.google.common.collect.Maps;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 org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import java.util.Map;/** * 文件名: SwaggerConfig.java Swagger配置类 * * @author fengqing * @version 1.0.00 * @since 2025/3/214 */@Configurationpublic class SwaggerConfig { @Bean public OpenAPI openAPI() { return new OpenAPI() .info(new Info() .title(\"标题---JsustPlay\") .description(\"描述信息---JsustPlay API文档\") .version(\"版本说明---1.0.0\") .license(new License() .name(\"API文档的许可信息---这里模拟一下,转跳百度了\") .url(\"http://www.baidu.com\")) .contact(new Contact() .name(\"作者name---fengqing\") .email(\"作者email--- 可以直接跳转邮箱发邮件,这里是假的\") .extensions((Map<String, Object>) Maps.newHashMap().put(\"x-xxx-x\",\"扩展字段,key必须以x开头\")) .url(\"http://www.baidu.com\"))) .externalDocs(new ExternalDocumentation() .description(\"外部文档描述---这里也转跳百度的\") .url(\"http://www.baidu.com\") ); }}

3.访问(ip:端口/swagger-ui/index.html)

SpringDoc详解(从入门到精通,一文搞定)
以上即为配置信息与文档信息的对应关系,每个信息类的属性几乎都都涉及的,还有部分非常用属性信息为涉及,感兴趣的可以看下对应类的源码进行了解。

4.测试(Post请求为例)

package org.example.controller;import org.example.dto.StudentDto;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import io.swagger.v3.oas.annotations.tags.Tag;/** * 文件名: Demo001.java 模型001 * * @author zhaochengfeng * @version 1.0.00 * @since 2025/3/21 V${1.0.00} */@RestController@RequestMapping(\"/demo001\")@Tag(name = \"Demo001\",description = \"示例001\")public class Demo001 { @PostMapping(\"/demo001_1\") public StudentDto demo001_1(@RequestBody StudentDto studentDto){ return BeanUtil.toBean(studentDto,StudentDto.class); }}
package org.example.dto;import io.swagger.v3.oas.annotations.media.Schema;import lombok.Data;/** * @Description: StudentDto * @Author: 风清 * @CreateTime: 2025-03-26 21:08 */@Datapublic class StudentDto { private String name; private Integer age;}

SpringDoc详解(从入门到精通,一文搞定)

SpringDoc详解(从入门到精通,一文搞定)

SpringDoc详解(从入门到精通,一文搞定)

注意:

默认情况下,Swagger3.0会根据请求类型来映射请求参数
我们将上述请求改为Get在进行测试

 @GetMapping(\"/demo001_1\") public StudentDto demo001_1(@RequestBody StudentDto studentDto){ return BeanUtil.toBean(studentDto,StudentDto.class); }

SpringDoc详解(从入门到精通,一文搞定)
SpringDoc详解(从入门到精通,一文搞定)
可以看到虽然填写请求体的时候仍然是Json格式,但是在发请求的时候数据被当做@RequestParam进行映射了

二、常用注解

1.常用注解汇总

注解 定位 @Tag 作用在Controller类上,用于描述API类信息。 @Operation 作用在Controller类的方法上,用于描述API方法信息,该注解可以包含一下全部注解。 @Parameter 作用在Controller类的方法上,用于描述 API 方法的参数信息。 @Parameters 作用在Controller类的方法上,用于描述API方法的多个参数。 @Schema 作用在实体类或者实体类属性上,用于描述实体类/实体类属性的信息,该实体类一般作为入参。或者结合在一些注解的schema属性中来描述参数信息(入参,返回值) @ApiResponse 作用在Controller类的方法上,用于描述API方法单个响应信息。 @ApiResponses 作用在Controller类的方法上,用于描述API方法多个响应信息。 @Hidden 隐藏某个类、方法或参数,不将其包含在生成的文档中。 @ResquestBody 作用在Controller类的方法上、用于描述请求体信息。 @Content 通常用于 @ApiResponse 或 @Parameter 注解中,用来定义 API 响应或参数的具体内容结构。

2.常用注解示例

@Tag

  • 作用
    为控制器或方法分组,便于组织和分类 API。

  • 常用属性
    name:标签名称。
    description:标签描述信息。

  • 示例

package org.example.controller;import org.example.dto.StudentDto;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import io.swagger.v3.oas.annotations.tags.Tag;/** * 文件名: Demo001.java 模型001 * * @author zhaochengfeng * @version 1.0.00 * @since 2025/3/21 V${1.0.00} */@RestController@RequestMapping(\"/demo001\")@Tag(name = \"Demo001\",description = \"示例001\")public class Demo001 { @PostMapping(\"/demo001_1\") public void demo001_1(@RequestBody StudentDto studentDto){ return BeanUtil.toBean(studentDto,StudentDto.class); }}
package org.example.dto;import io.swagger.v3.oas.annotations.media.Schema;import lombok.Data;/** * @Description: StudentDto * @Author: 风清 * @CreateTime: 2025-03-26 21:08 */@Datapublic class StudentDto { private String name; private Integer age;}
  • Swagger呈现结果

这里顺便说一Swagger的三大部分,如下图

SpringDoc详解(从入门到精通,一文搞定)

@Operation

  • 作用
    为控制器或方法分组,便于组织和分类 API。

  • 常用属性
    summary:标签名称。
    description:标签描述信息。
    deprecated:标记方法是否已废弃。(默认为false)

  • 示例

package org.example.controller;import cn.hutool.core.bean.BeanUtil;import io.swagger.v3.oas.annotations.Operation;import org.example.dto.StudentDto;import org.springframework.web.bind.annotation.*;import io.swagger.v3.oas.annotations.tags.Tag;/** * 文件名: Demo001.java 模型001 * * @author zhaochengfeng * @version 1.0.00 * @since 2025/3/21 V${1.0.00} */@RestController@RequestMapping(\"/demo001\")@Tag(name = \"Demo001\",description = \"示例001\")public class Demo001 { @PostMapping(\"/demo001_1\") @Operation(summary = \"Sdemo001_1\",description = \"Ddemo001_1\", deprecated = true) public StudentDto demo001_1(@RequestBody StudentDto studentDto){ return BeanUtil.toBean(studentDto,StudentDto.class); } @PostMapping(\"/demo001_2\") @Operation(summary = \"Sdemo001_2\",description = \"Ddemo001_2\", deprecated = false) public StudentDto demo001_2(@RequestBody StudentDto studentDto){ return BeanUtil.toBean(studentDto,StudentDto.class); }}
package org.example.dto;import io.swagger.v3.oas.annotations.media.Schema;import lombok.Data;/** * @Description: StudentDto * @Author: 风清 * @CreateTime: 2025-03-26 21:08 */@Datapublic class StudentDto { private String name; private Integer age;}
  • Swagger呈现结果

SpringDoc详解(从入门到精通,一文搞定)

@Parameter

  • 作用
    描述方法参数的含义。

  • 常用属性
    name:参数名(使用时与参数一致)
    description:参数描述信息。
    in:参数位置。示例代码中进行说明。
    schema:参数类型。
    required:是否必填,默认为false。
    example:示例值。

  • 注意
    该注解用于@RequestParam、@PathVariable参数,Sawgger通过@RequestBody注解来修饰@RequestBody类型参数。

  • 示例

package org.example.controller;import cn.hutool.core.bean.BeanUtil;import io.swagger.v3.oas.annotations.Operation;import io.swagger.v3.oas.annotations.Parameter;import io.swagger.v3.oas.annotations.enums.ParameterIn;import io.swagger.v3.oas.annotations.media.Schema;import org.example.dto.StudentDto;import org.springframework.web.bind.annotation.*;import io.swagger.v3.oas.annotations.tags.Tag;/*** 文件名: Demo001.java 模型001** @author zhaochengfeng* @version 1.0.00* @since 2025/3/21 V${1.0.00}*/@RestController@RequestMapping(\"/demo001\")@Tag(name = \"Demo001\",description = \"示例001\")public class Demo001 { /* in:参数位置,ParameterIn.PATH表示参数在路径中, ParameterIn.QUERY表示参数在查询字符串中, ParameterIn.HEADER表示参数在请求头中, ParameterIn.COOKIE表示参数在cookie中。 */ @PostMapping(\"/{id}\") @Operation(summary = \"Sdemo001_1\",description = \"Ddemo001_1\") public String demo001_1(  @Parameter(name = \"id\",  description = \"学生id\",  in = ParameterIn.PATH,  schema = @Schema(type = \"integer\"), required = true,example = \"1\")  @PathVariable Integer id,  @Parameter(name = \"name\",  description = \"学生姓名\",  in = ParameterIn.QUERY,  schema = @Schema(type = \"string\"), required = true,example = \"张三\")  @RequestParam String name ){ return name+\":\"+id; } //作用在类似修饰@RequestBody参数,上面说过,swagger有对应处理@RequestBody参数的注解@RequestBody,所以这里就不进行展示了,记住这种方式不要用即可 @PostMapping(\"/demo001_1\") @Operation(summary = \"Sdemo001_1\",description = \"Ddemo001_1\") @Parameter(deprecated = true,description = \"学生信息\", schema = @Schema(implementation = StudentDto.class), required = true,example = \"{\\\"name\\\":\\\"张三\\\",\\\"age\\\":18}\") public StudentDto demo001_1(@RequestBody StudentDto studentDto){ return BeanUtil.copyProperties(studentDto, StudentDto.class); }
  • Swagger呈现结果

SpringDoc详解(从入门到精通,一文搞定)

@Parameters

  • 作用
    作用在实体类或者实体类属性上,用于描述实体类/实体类属性的信息,该实体类一般作为入参。或者结合在一些注解的schema属性中来描述参数信息(入参,返回值)

  • 常用属性
    value:Parameter的集合。

  • 示例

package org.example.controller;import cn.hutool.core.bean.BeanUtil;import io.swagger.v3.oas.annotations.Operation;import io.swagger.v3.oas.annotations.Parameter;import io.swagger.v3.oas.annotations.enums.ParameterIn;import io.swagger.v3.oas.annotations.media.Schema;import org.example.dto.StudentDto;import org.springframework.web.bind.annotation.*;import io.swagger.v3.oas.annotations.tags.Tag;/*** 文件名: Demo001.java 模型001** @author zhaochengfeng* @version 1.0.00* @since 2025/3/21 V${1.0.00}*/@RestController@RequestMapping(\"/demo001\")@Tag(name = \"Demo001\",description = \"示例001\")public class Demo001 { /* 3.in:参数位置,ParameterIn.PATH表示参数在路径中, ParameterIn.QUERY表示参数在查询字符串中, ParameterIn.HEADER表示参数在请求头中, ParameterIn.COOKIE表示参数在cookie中。 */ @PostMapping(\"/{id}\") @Operation(summary = \"Sdemo001_1\",description = \"Ddemo001_1\") public String demo001_1(  @Parameter(name = \"id\",  description = \"学生id\",  in = ParameterIn.PATH,  schema = @Schema(type = \"integer\"), required = true,example = \"1\")  @PathVariable Integer id,  @Parameter(name = \"name\",  description = \"学生姓名\",  in = ParameterIn.QUERY,  schema = @Schema(type = \"string\"), required = true,example = \"张三\")  @RequestParam String name ){ return name+\":\"+id; }
  • Swagger呈现结果

SpringDoc详解(从入门到精通,一文搞定)

@Schena

  • 作用
    作用在实体类或者实体类属性上,用于描述实体类/实体类属性的信息,该实体类一般作为入参。或者结合在一些注解的schema属性中来描述参数信息(入参,返回值)

  • 常用属性

    • 作用于实体类/实体类属性上
      description:模型或属性的描述。
      example:示例值。
      required:必需属性。
      hidden:是否隐藏属性。
    • 结合其他注解使用上
      type: 指定@RequestParam、@PathVariable参数类型(用法与上方@Parameter中一致)
      implementation:指定JSON(@RequestBody)参数类型(于下方@RequsetBody/@ApiRequest注解中演示)
  • 注意
    请求体或者响应体为json时,无论对应的Dto/Vo类无论是否被Schema注解都会被映射,Schema注解只是为响应/请求体添加了描述信息。

  • 示例

package org.example.dto;import io.swagger.v3.oas.annotations.media.Schema;import lombok.Data;/** * @Description: StudentDto * @Author: 风清 * @CreateTime: 2025-03-26 21:08 */@Data//无论是否有Schema注解Swagger都会将请求参数映射到Swagger文档上,Schema注解只是给Swagger文档上添加一些描述信息和示例信息@Schema(description = \"学生信息\", name = \"StudentDto\", example = \"{\\\"name\\\":\\\"张三\\\",\\\"age\\\":18}\")public class StudentDto { @Schema(name = \"name\", description = \"姓名\") private String name; @Schema(name = \"age\", description = \"年龄\",hidden = true) private Integer age;}
  • Swagger呈现结果

引入Swagger前(这里的schema会在用到的进行映射)

SpringDoc详解(从入门到精通,一文搞定)
引入后:可以看到多了示例值,并且隐藏了age。
SpringDoc详解(从入门到精通,一文搞定)

@ApiRequest/@Content

  • 作用
    作用在Controller类的方法上,用于描述API方法单个响应信息。

  • 常用属性
    responseCode:HTTP 状态码。
    description:响应描述信息。
    content:响应的内容类型(如 JSON、XML)。

    • @Content常用属性
      mediaType :响应格式。
      schema :响应结果格式。
  • 注意
    不通过@ApiRequest的content属性去指定响应体时,Swagger会自动映射返回体,当响应值非200时一般不需要显示响应体内容(展示是无意义的),这个是时候就需要为content属性赋值一个空的@Content。

  • 示例

package org.example.dto;import io.swagger.v3.oas.annotations.media.Schema;import lombok.Data;/** * @Description: StudentDto * @Author: 风清 * @CreateTime: 2025-03-26 21:08 */@Data//无论是否有Schema注解Swagger都会将请求参数映射到Swagger文档上,Schema注解只是给Swagger文档上添加一些描述信息和示例信息@Schema(description = \"学生信息\", name = \"StudentDto\", example = \"{\\\"name\\\":\\\"张三\\\",\\\"age\\\":18}\")public class StudentDto { @Schema(name = \"name\", description = \"姓名\") private String name; @Schema(name = \"age\", description = \"年龄\") private Integer age;}
package org.example.controller;import io.swagger.v3.oas.annotations.Operation;import io.swagger.v3.oas.annotations.media.Content;import io.swagger.v3.oas.annotations.media.Schema;import io.swagger.v3.oas.annotations.responses.ApiResponse;import org.example.dto.StudentDto;import org.springframework.web.bind.annotation.*;import io.swagger.v3.oas.annotations.tags.Tag;/** * 文件名: Demo001.java 模型001 * * @author zhaochengfeng * @version 1.0.00 * @since 2025/3/21 V${1.0.00} */@RestController@RequestMapping(\"/demo001\")@Tag(name = \"Demo001\",description = \"示例001\")public class Demo001 { @PostMapping(\"/{id}\") @Operation(summary = \"Sdemo001_1\",description = \"Ddemo001_1\") // 描述1 @ApiResponse( responseCode = \"200\", description = \"成功\", content = {@Content(  //响应类型  mediaType = \"application/json\",  //响应对象结果描述    schema = @Schema(implementation = StudentDto.class))} ) // 描述2 这里指定了一个空的@Content来实现swagger文档不展示响应体,否则会默认swagger会映射默认返回内容。 @ApiResponse(responseCode = \"405\", description = \"非法输入\",content = @Content) public StudentDto demo001_1( @PathVariable Integer id, @RequestParam String name ){ return StudentDto.builder().name(name).age(18).build(); }}
  • Swagger呈现结果

可以与上方默认的响应信息进行对比,可以看到响应200的描述信息由默认的ok改成了成功,类型有默认的*/*改成了application/json

SpringDoc详解(从入门到精通,一文搞定)

@ApiRequests

  • 作用
    作用在Controller类的方法上,用于描述API方法多个响应信息。

  • 常用属性
    value:ApiRequests集合。

  • 示例

package org.example.dto;import io.swagger.v3.oas.annotations.media.Schema;import lombok.Data;/** * @Description: StudentDto * @Author: 风清 * @CreateTime: 2025-03-26 21:08 */@Data//无论是否有Schema注解Swagger都会将请求参数映射到Swagger文档上,Schema注解只是给Swagger文档上添加一些描述信息和示例信息@Schema(description = \"学生信息\", name = \"StudentDto\", example = \"{\\\"name\\\":\\\"张三\\\",\\\"age\\\":18}\")public class StudentDto { @Schema(name = \"name\", description = \"姓名\") private String name; @Schema(name = \"age\", description = \"年龄\") private Integer age;}
package org.example.controller;import io.swagger.v3.oas.annotations.Operation;import io.swagger.v3.oas.annotations.media.Content;import io.swagger.v3.oas.annotations.media.Schema;import io.swagger.v3.oas.annotations.responses.ApiResponse;import io.swagger.v3.oas.annotations.responses.ApiResponses;import org.example.dto.StudentDto;import org.springframework.web.bind.annotation.*;import io.swagger.v3.oas.annotations.tags.Tag;/** * 文件名: Demo001.java 模型001 * * @author zhaochengfeng * @version 1.0.00 * @since 2025/3/21 V${1.0.00} */@RestController@RequestMapping(\"/demo001\")@Tag(name = \"Demo001\",description = \"示例001\")public class Demo001 { @PostMapping(\"/{id}\") @Operation(summary = \"Sdemo001_1\",description = \"Ddemo001_1\") @ApiResponses({ // 描述1 @ApiResponse( responseCode = \"200\", description = \"成功\", content = {@Content(  //响应类型  mediaType = \"application/json\",  //响应对象结果描述  schema = @Schema(implementation = StudentDto.class))}), // 描述2 @ApiResponse(responseCode = \"405\", description = \"非法输入\",,content = @Content) }) public StudentDto demo001_1( @PathVariable Integer id, @RequestParam String name ){ return StudentDto.builder().name(name).age(18).build(); }}
  • Swagger呈现结果(与上述一致)

SpringDoc详解(从入门到精通,一文搞定)

@ResquestBody

  • 作用
    作用在Controller类的方法上,用于描述请求体信息。

  • 常用属性
    description:请求体的描述。
    required:是否必需。
    content :请求的内容类型(与@ApiRequest一致)。

  • 示例

package org.example.dto;import io.swagger.v3.oas.annotations.media.Schema;import lombok.Builder;import lombok.Data;/** * @Description: StudentDto * @Author: 风清 * @CreateTime: 2025-03-26 21:08 */@Data@Builder@Schema(description = \"学生信息\", name = \"StudentDto\", example = \"{\\\"name\\\":\\\"张三\\\",\\\"age\\\":18}\")public class StudentDto { @Schema(name = \"name\", description = \"姓名\",example = \"张三\") private String name; @Schema(name = \"age\", description = \"年龄\",example = \"18\") private Integer age;}
package org.example.controller;import io.swagger.v3.oas.annotations.Operation;import io.swagger.v3.oas.annotations.media.Content;import io.swagger.v3.oas.annotations.media.Schema;import org.example.dto.StudentDto;import org.springframework.web.bind.annotation.*;import io.swagger.v3.oas.annotations.tags.Tag;/** * 文件名: Demo001.java 模型001 * * @author zhaochengfeng * @version 1.0.00 * @since 2025/3/21 V${1.0.00} */ @RestController@RequestMapping(\"/demo001\")@Tag(name = \"Demo001\",description = \"示例001\")public class Demo001 { @PostMapping(\"/{id}\") @Operation(summary = \"Sdemo001_1\",description = \"Ddemo001_1\") @io.swagger.v3.oas.annotations.parameters.RequestBody(  content = @Content(schema = @Schema(implementation = StudentDto.class)),  description = \"请求体\") public StudentDto demo001_1( @RequestBody StudentDto studentDto ){ return studentDto; }}
  • Swagger呈现结果

这里的mediaType 属性可以不进行描述默认就为application/json。

SpringDoc详解(从入门到精通,一文搞定)
对了,这里在提下,在请求/响应体的旁边有个schema点击会展示对应的请求/响应体信息
SpringDoc详解(从入门到精通,一文搞定)

结合使用

上面说过@Operation可以包含几乎全表Swagger3.0的注解,实际开发中这些注解通常也不会单独使用,而是包含在@Operation中。如下

package org.example.dto;import io.swagger.v3.oas.annotations.media.Schema;import lombok.Builder;import lombok.Data;/** * @Description: StudentDto * @Author: 风清 * @CreateTime: 2025-03-26 21:08 */@Data@Builder@Schema(description = \"学生信息\", name = \"StudentDto\", example = \"{\\\"name\\\":\\\"张三\\\",\\\"age\\\":18}\")public class StudentDto { @Schema(name = \"name\", description = \"姓名\",example = \"张三\") private String name; @Schema(name = \"age\", description = \"年龄\",example = \"18\") private Integer age;}
package org.example.controller;import io.swagger.v3.oas.annotations.Operation;import io.swagger.v3.oas.annotations.Parameter;import io.swagger.v3.oas.annotations.enums.ParameterIn;import io.swagger.v3.oas.annotations.media.Content;import io.swagger.v3.oas.annotations.media.Schema;import io.swagger.v3.oas.annotations.responses.ApiResponse;import org.example.dto.StudentDto;import org.springframework.web.bind.annotation.*;import io.swagger.v3.oas.annotations.tags.Tag;/** * 文件名: Demo001.java 模型001 * * @author zhaochengfeng * @version 1.0.00 * @since 2025/3/21 V${1.0.00} */@RestController@RequestMapping(\"/demo001\")@Tag(name = \"Demo001\",description = \"示例001\")public class Demo001 { @PostMapping(\"/{id}\") @Operation(summary = \"Sdemo001_1\",description = \"Ddemo001_1\", requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(  content = @Content(schema = @Schema(implementation = StudentDto.class)),  description = \"请求体\"), responses = {  @ApiResponse( responseCode = \"200\", description = \"成功\",  content = @Content(mediaType = \"application/json\",schema = @Schema(implementation = StudentDto.class) )  ),  @ApiResponse( description = \"找不到指定路径\", responseCode = \"404\", content = @Content()  ) } ) public StudentDto demo001_1( @RequestBody StudentDto studentDto ){ return studentDto; } @GetMapping(\"/id\") @Operation( summary = \"Sdemo001_2\", description = \"Ddemo001_2\", parameters = {  @Parameter( name = \"id\", description = \"id\", in = ParameterIn.QUERY, schema = @Schema(implementation = Integer.class)  ) }, responses = {  @ApiResponse( responseCode = \"200\", description = \"成功\", content = @Content()  ),  @ApiResponse( description = \"找不到指定路径\", responseCode = \"404\", content = @Content()  ) } ) public Integer demo001_2( @RequestParam(value = \"id\",required = false) Integer id ){ return id; }}
  • Swagger呈现结果

SpringDoc详解(从入门到精通,一文搞定)

扩展@ResponseStatus

上面我们通过@ApiResponse来设定响应信息,但实际上响应结果的种类是比较多的一个个设置很繁琐,而实际开发中通常会有统一的响应类以及全局异常处理器,我们通常通过Swagger的ResponseStatus注解结合全局异常处理器来实现响应信息的生成

  • 示例代码
package org.example.enums;/** * 文件名: AppHttpCodeEnum.java 响应枚举 * * @author fengqing * @version 1.0.00 * @since 2025/4/1 */public enum AppHttpCodeEnum { // 成功段0 SUCCESS(200,\"操作成功\"), // 登录段1~50 NEED_LOGIN(1,\"需要登录后操作\"), LOGIN_PASSWORD_ERROR(2,\"密码错误\"), // TOKEN50~100 TOKEN_INVALID(50,\"无效的TOKEN\"), TOKEN_EXPIRE(51,\"TOKEN已过期\"), TOKEN_REQUIRE(52,\"TOKEN是必须的\"), // SIGN验签 100~120 SIGN_INVALID(100,\"无效的SIGN\"), SIG_TIMEOUT(101,\"SIGN已过期\"), // 参数错误 500~1000 PARAM_REQUIRE(500,\"缺少参数\"), PARAM_INVALID(501,\"无效参数\"), PARAM_IMAGE_FORMAT_ERROR(502,\"图片格式有误\"), SERVER_ERROR(503,\"服务器内部错误\"), // 数据错误 1000~2000 DATA_EXIST(1000,\"数据已经存在\"), AP_USER_DATA_NOT_EXIST(1001,\"ApUser数据不存在\"), DATA_NOT_EXIST(1002,\"数据不存在\"), // 数据错误 3000~3500 NO_OPERATOR_AUTH(3000,\"无权限操作\"), NEED_ADMIND(3001,\"需要管理员权限\"); int code; String errorMessage; AppHttpCodeEnum(int code, String errorMessage){ this.code = code; this.errorMessage = errorMessage; } public int getCode() { return code; } public String getErrorMessage() { return errorMessage; }}
package org.example.exception;import org.example.enums.AppHttpCodeEnum;/** * 文件名: CustomException.java 自定义异常处理类 * * @author fengqing * @version 1.0.00 * @since 2025/4/1 */public class CustomException extends RuntimeException { private AppHttpCodeEnum appHttpCodeEnum; public CustomException(AppHttpCodeEnum appHttpCodeEnum){ this.appHttpCodeEnum = appHttpCodeEnum; } public AppHttpCodeEnum getAppHttpCodeEnum() { return appHttpCodeEnum; }}
package org.example.exception;import lombok.extern.slf4j.Slf4j;import org.example.enums.AppHttpCodeEnum;import org.example.vo.ResponseResult;import org.springframework.http.HttpStatus;import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.bind.annotation.ResponseStatus;/** * 文件名: ExceptionCatch.java 自定义异常处理类 * * @author fengqing * @version 1.0.00 * @since 2025/4/1 */@ControllerAdvice //控制器增强类, 表示如果在controller.service中任何一个地方出现了异常之后,都会自动调用该捕获类@Slf4jpublic class ExceptionCatch { /** * 处理不可控异常 * @param e * @return */ @ExceptionHandler(Exception.class) @ResponseBody @ResponseStatus(HttpStatus.SERVICE_UNAVAILABLE) public ResponseResult exception(Exception e){ e.printStackTrace(); log.error(\"catch exception:{}\",e.getMessage()); return ResponseResult.errorResult(AppHttpCodeEnum.SERVER_ERROR); } /** * 处理可控异常 自定义异常 * @param e * @return */ @ExceptionHandler(CustomException.class) @ResponseBody @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public ResponseResult exception(CustomException e){ log.error(\"catch exception:{}\",e); return ResponseResult.errorResult(e.getAppHttpCodeEnum()); }}
package org.example.vo;import org.example.enums.AppHttpCodeEnum;import java.io.Serializable;import java.util.ArrayList;import java.util.List;/** * 通用的结果返回类 * @param  */public class ResponseResult<T> implements Serializable { private String host; private Integer code; private String errorMessage; private T data; public ResponseResult() { this.code = 200; } public ResponseResult(Integer code, T data) { this.code = code; this.data = data; } public ResponseResult(Integer code, String msg, T data) { this.code = code; this.errorMessage = msg; this.data = data; } public ResponseResult(Integer code, String msg) { this.code = code; this.errorMessage = msg; } public static ResponseResult errorResult(int code, String msg) { ResponseResult result = new ResponseResult(); return result.error(code, msg); } public static ResponseResult okResult(int code, String msg) { ResponseResult result = new ResponseResult(); return result.ok(code, null, msg); } public static ResponseResult okResult(Object data) { ResponseResult result = setAppHttpCodeEnum(AppHttpCodeEnum.SUCCESS, AppHttpCodeEnum.SUCCESS.getErrorMessage()); if (data != null) { result.setData(data); } return result; } public static ResponseResult errorResult(AppHttpCodeEnum enums) { return setAppHttpCodeEnum(enums, enums.getErrorMessage()); } public static ResponseResult errorResult(AppHttpCodeEnum enums, String errorMessage) { return setAppHttpCodeEnum(enums, errorMessage); } public static ResponseResult setAppHttpCodeEnum(AppHttpCodeEnum enums) { return okResult(enums.getCode(), enums.getErrorMessage()); } private static ResponseResult setAppHttpCodeEnum(AppHttpCodeEnum enums, String errorMessage) { return okResult(enums.getCode(), errorMessage); } public ResponseResult<?> error(Integer code, String msg) { this.code = code; this.errorMessage = msg; return this; } public ResponseResult<?> ok(Integer code, T data) { this.code = code; this.data = data; return this; } public ResponseResult<?> ok(Integer code, T data, String msg) { this.code = code; this.data = data; this.errorMessage = msg; return this; } public ResponseResult<?> ok(T data) { this.data = data; return this; } public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } public String getErrorMessage() { return errorMessage; } public void setErrorMessage(String errorMessage) { this.errorMessage = errorMessage; } public T getData() { return data; } public void setData(T data) { this.data = data; } public String getHost() { return host; } public void setHost(String host) { this.host = host; }}
  • 展示结果

SpringDoc详解(从入门到精通,一文搞定)
可以看到这里多了500和503,点开对应的schema可以看到正是我们的统一响应结果类信息。

三、分组

业界一般会更具不同服务模块或功能模块对接口进行分组,提高可观性和测试效率,实现起来很简单,只需要在配置类中注入GroupedOpenApi示例即可。

  • 示例
package org.example.config;import org.springdoc.core.GroupedOpenApi;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/** * 文件名: SwaggerConfig.java Swagger配置类 * * @author fengqing * @version 1.0.00 * @since 2025/4/1 */@Configurationpublic class SpringDocConfig { @Bean public GroupedOpenApi publicApi() { return GroupedOpenApi.builder() //设置分组名称 .group(\"demo001\") //设置匹配路径 .pathsToMatch(\"/demo001/**\") .build(); } @Bean public GroupedOpenApi adminApi() { return GroupedOpenApi.builder() //分组名称 .group(\"demo002\") //匹配路径 .pathsToMatch(\"/demo002/**\") .build(); }}
package org.example.controller;import org.springframework.web.bind.annotation.*;import io.swagger.v3.oas.annotations.tags.Tag;/** * 文件名: Demo001.java 模型001 * * @author zhaochengfeng * @version 1.0.00 * @since 2025/3/21 V${1.0.00} */@RestController@RequestMapping(\"/demo001\")@Tag(name = \"demo001\",description = \"示例001\")public class Demo001 { @GetMapping(\"/id\") public Integer demo001( @RequestParam(value = \"id\",required = false) Integer id ){ return id; }}
package org.example.controller;import org.springframework.web.bind.annotation.*;import io.swagger.v3.oas.annotations.tags.Tag;/** * 文件名: Demo002.java 模型002 * * @author zhaochengfeng * @version 1.0.00 * @since 2025/4/1 V${1.0.00} */@RestController@RequestMapping(\"/demo002\")@Tag(name = \"demo002\",description = \"示例002\")public class Demo002 { @GetMapping(\"/id\") public Integer demo002( @RequestParam(value = \"id\",required = false) Integer id ){ return id; }}
package org.example.controller;import org.springframework.web.bind.annotation.*;import io.swagger.v3.oas.annotations.tags.Tag;/** * 文件名: Demo002.java 模型002 * * @author zhaochengfeng * @version 1.0.00 * @since 2025/4/1 V${1.0.00} */@RestController@RequestMapping(\"/demo002\")@Tag(name = \"demo002\",description = \"示例002\")public class Demo002 { @GetMapping(\"/id\") public Integer demo002( @RequestParam(value = \"id\",required = false) Integer id ){ return id; }}
  • 结果展示

SpringDoc详解(从入门到精通,一文搞定)

SpringDoc详解(从入门到精通,一文搞定)

四、认证授权

这里浅谈一下认证授权,其实就是把登录的token放到请求中,这里我就不在举具体的列子了,仅展示一下怎么将认证信息放到请求中(基于JavaAPI形式)。

  • 配置类
package org.example.config;import io.swagger.v3.oas.models.Components;import io.swagger.v3.oas.models.OpenAPI;import io.swagger.v3.oas.models.info.Info;import io.swagger.v3.oas.models.security.SecurityRequirement;import io.swagger.v3.oas.models.security.SecurityScheme;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/** * @Description: SpringDocSwaggerConfig * @Author: 风清 * @CreateTime: 2025-04-14 21:13 */@Configurationpublic class SpringDocSwaggerConfig { @Bean public OpenAPI testOpenAPI() { // 创建一个 OpenAPI 实例,并设置 API 的基本信息 OpenAPI openAPI = (new OpenAPI()).info((new Info()).title(\"Example API\").version(\"1.0\")); // 创建一个 Components 实例,用于管理 API 的组件,如安全方案等 Components components = new Components(); /*添加安全要求 为OpenAPI对象添加安全要求。SecurityRequirement表示一个安全要求,这里分别添加了 server-one、server-two、server-three、server-four和server-five这五个安全要求。 */ openAPI.addSecurityItem((new SecurityRequirement()).addList(\"server-one\")); openAPI.addSecurityItem((new SecurityRequirement()).addList(\"server-two\")); openAPI.addSecurityItem((new SecurityRequirement()).addList(\"server-three\")); openAPI.addSecurityItem((new SecurityRequirement()).addList(\"server-four\")); openAPI.addSecurityItem((new SecurityRequirement()).addList(\"server-five\")); /*定义安全方案 为Components对象添加安全方案。SecurityScheme表示一个安全方案,这里定义了五个安全方案, 名称分别为server-one、server-two、server-three、server-four和server-five, 类型为APIKEY,即使用 API 密钥进行身份验证,并且密钥要放在请求头中。 */ components.addSecuritySchemes(\"server-one\", (new SecurityScheme()).name(\"server-one\").type(SecurityScheme.Type.APIKEY).in(SecurityScheme.In.HEADER)); components.addSecuritySchemes(\"server-two\", (new SecurityScheme()).name(\"server-two\").type(SecurityScheme.Type.APIKEY).in(SecurityScheme.In.HEADER)); components.addSecuritySchemes(\"server-three\", (new SecurityScheme()).name(\"server-three\").type(SecurityScheme.Type.APIKEY).in(SecurityScheme.In.HEADER)); components.addSecuritySchemes(\"server-four\", (new SecurityScheme()).name(\"server-four\").type(SecurityScheme.Type.APIKEY).in(SecurityScheme.In.HEADER)); components.addSecuritySchemes(\"server-five\", (new SecurityScheme()).name(\"server-five\").type(SecurityScheme.Type.APIKEY).in(SecurityScheme.In.HEADER)); openAPI.components(components); return openAPI; }}
  • 在接口中打印下请求头信息
package org.example.controller;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;import io.swagger.v3.oas.annotations.tags.Tag;import javax.servlet.http.HttpServletRequest;import java.util.Enumeration;/** * 文件名: Demo002.java 模型002 * * @author zhaochengfeng * @version 1.0.00 * @since 2025/4/1 V${1.0.00} */@Slf4j@RestController@RequestMapping(\"/demo002\")@Tag(name = \"demo002\",description = \"示例002\")public class Demo002 { @Autowired private HttpServletRequest request; @GetMapping(\"/id\") public Integer demo002( @RequestParam(value = \"id\",required = false) Integer id ){ // 获取请求头 Enumeration<String> headerNames = request.getHeaderNames(); while (headerNames.hasMoreElements()){ String headName = headerNames.nextElement(); String headerValue = request.getHeader(headName); log.info(headName+\":\"+headerValue); } return id; }}

SpringDoc详解(从入门到精通,一文搞定)
基于携带的请求信息我们就可以进行对应的验证,测试时,一般会将token放入请求头中。当然这里的安全方案不只有这一种,感兴趣可以进行了解。