优雅哥 SpringBoot 2.7.2 实战基础 - 04 -集成 Spring Doc 接口文档和 knife4j

前面已经集成 MyBatis Plus、Druid 数据源,开发了 5 个接口。在测试这 5 个接口时使用了 HTTP Client 或 PostMan,无论是啥都比较麻烦:得自己写请求地址 URL、请求参数等,于是多年前就出现了 Swagger 这个玩意。Swagger 可以自动生成接口文档,还能很方便的测试各个接口。但不幸的是,MVN Repository 上面 Springfox Swagger2 的版本停止于 2020 年 7月,而写下这篇文章是 2022 年 8 月,已经两年过去没有动静了,与此同时,springdoc-openapi 悄然出现。

spring doc open api 支持 Open API 3、Swagger-ui等,可以很方便与 Spring Boot 整合,配置和使用与 Springfox Swagger2 类似。

1 集成 Spring Doc

1.1 添加依赖

springdoc-openapi 不是 Spring Framework 官方团队开发的,而是社区项目,没有包含在 spring-boot-dependencies 中。故需要先定义版本号:

  1. <properties>
  2. ....
  3. <springdoc-openapi-ui.version>1.6.9</springdoc-openapi-ui.version>
  4. </properties>

添加依赖:

  1. <dependency>
  2. <groupId>org.springdoc</groupId>
  3. <artifactId>springdoc-openapi-ui</artifactId>
  4. <version>${springdoc-openapi-ui.version}</version>
  5. </dependency>

该依赖里面使用了 swagger-ui,以HTML形式展示文档。

1.2 编写配置类

其实配置类写不写都可以,如果不写配置类,就通过注解定义文档信息就可以。创建类:com.yygnb.demo.config.SpringDocConfig

  1. package com.yygnb.demo.config;
  2. import io.swagger.v3.oas.models.ExternalDocumentation;
  3. import io.swagger.v3.oas.models.OpenAPI;
  4. import io.swagger.v3.oas.models.info.Info;
  5. import org.springframework.context.annotation.Bean;
  6. import org.springframework.context.annotation.Configuration;
  7. @Configuration
  8. public class SpringDocConfig {
  9. private String title = "Hero SpringBoot Demo";
  10. private String description = "Hero Demo for usage of Spring Boot";
  11. private String version = "v0.0.1";
  12. private String websiteName = "Hero Website";
  13. private String websiteUrl = "http://www.yygnb.com";
  14. @Bean
  15. public OpenAPI heroOpenAPI() {
  16. return new OpenAPI()
  17. .info(new Info().title(title)
  18. .description(description)
  19. .version(version))
  20. .externalDocs(new ExternalDocumentation().description(websiteName)
  21. .url(websiteUrl));
  22. }
  23. }

上面的配置定义了展示的文档的信息,与界面上对应关系如下:

在配置文件中除了可以配置文档的信息,还可以配置文档分组、Authorization 等,在后面的企业级实战文章中会具体描写,将会在网关层 spring cloud gateway 中集成所有微服务的接口。

1.3 配置yml

在 application.yml 配置 springdoc:

  1. # 接口文档
  2. springdoc:
  3. packages-to-scan: com.yygnb.demo.controller
  4. swagger-ui:
  5. enabled: true

这两项不配置也可以,packages-to-scan 默认为启动类所在的路径;springdoc.swagger-ui.enabled 默认为true,配置后可以在不同的环境中开启或关闭。

1.4 添加注解

springdoc-openapi 与 springfox-swagger2 提供的注解有很大差别:

swagger 2 spring doc 描述
@Api @Tag 修饰 controller 类,类的说明
@ApiOperation @Operation 修饰 controller 中的接口方法,接口的说明
@ApiModel @Schema 修饰实体类,该实体的说明
@ApiModelProperty @Schema 修饰实体类的属性,实体类中属性的说明
@ApiImplicitParams @Parameters 接口参数集合
@ApiImplicitParam @Parameter 接口参数
@ApiParam @Parameter 接口参数

修改实体类 Computer,添加 springdoc-openapi 注解:

  1. @Schema(title = "电脑")
  2. @Data
  3. @NoArgsConstructor
  4. @AllArgsConstructor
  5. @Builder
  6. public class Computer implements Serializable {
  7. private static final long serialVersionUID = 1L;
  8. @TableId(value = "id", type = IdType.AUTO)
  9. private Long id;
  10. @Schema(title = "尺寸")
  11. private BigDecimal size;
  12. @Schema(title = "操作系统")
  13. private String operation;
  14. @Schema(title = "年份")
  15. private String year;
  16. }

修改控制器 ComputerController,添加注解:

  1. @Tag(name = "电脑相关接口")
  2. @RequiredArgsConstructor
  3. @RestController
  4. @RequestMapping("/computer")
  5. public class ComputerController {
  6. private final IComputerService computerService;
  7. @Operation(summary = "根据id查询电脑")
  8. @GetMapping("/{id}")
  9. public Computer findById(
  10. @Parameter(name = "id", required = true, description = "电脑id") @PathVariable Long id) {
  11. return this.computerService.getById(id);
  12. }
  13. @Operation(summary = "分页查询电脑列表")
  14. @Parameters(value = {
  15. @Parameter(name = "page", description = "页面,从1开始", example = "2"),
  16. @Parameter(name = "size", description = "每页大小", example = "10")
  17. })
  18. @GetMapping("/find-page/{page}/{size}")
  19. public Page<Computer> findPage(@PathVariable Integer page, @PathVariable Integer size) {
  20. return this.computerService.page(new Page<>(page, size));
  21. }
  22. @Operation(summary = "新增电脑")
  23. @PostMapping()
  24. public Computer save(@RequestBody Computer computer) {
  25. computer.setId(null);
  26. this.computerService.save(computer);
  27. return computer;
  28. }
  29. @Operation(summary = "根据id修改电脑")
  30. @PutMapping("/{id}")
  31. public Computer update(
  32. @Parameter(name = "id", required = true, description = "电脑id") @PathVariable Long id,
  33. @RequestBody Computer computer) {
  34. computer.setId(id);
  35. this.computerService.updateById(computer);
  36. return computer;
  37. }
  38. @Operation(summary = "根据id删除电脑")
  39. @DeleteMapping("/{id}")
  40. @Parameter(name = "id", required = true, description = "电脑id")
  41. public void delete(@PathVariable Long id) {
  42. this.computerService.removeById(id);
  43. }
  44. }

1.5 运行测试

启动服务,在浏览器中访问:

  1. http://localhost:9099/swagger-ui/index.html

2 api-docs

在文档标题下面有一个小链接:/v3/api-docs,点击该链接,会在新页面中显示一大坨 JSON 数据。

看似很无聊的数据,却有着重大意义,swagger-ui 就是通过这些数据渲染出页面的。此外,这些JSON数据在某种程度上可以简化前端的开发及前后端网络请求的工作量。

hero-admin-ui

优雅哥正在开发的基于 Vue 3 + TypeScript 的开源项目 hero-admin-ui,其特色就是基于 JSON Schema 的表单和列表。通过 JSON Schema 可以快速渲染出一个列表、表单,甚至是搜索页和详情表单页。如果独立使用 hero-admin-ui,需要手动编写 JSON Schema,但如果后端接口整合了 Swagger 或 Spring Doc,上面 api-docs 返回的 JSON,就包含了 JSON Schema,二者结合可以快速实现搜索页、表单页等。目前 hero-admin-ui 已发布在 npmjs 上,也已经提交到 github上,大家可以搜索关键字 hero-admin-ui 查看。在后面的实战篇中,前端部分将会使用这个组件库实现前端页面。

3 自定义配置

在 ”1.2 编写配置类“ 一节,文档信息都是写死在代码中的,如果多个微服务都要集成 spring doc,可以把前面写的 SpringDocConfig 提取到公共模块中,通过maven 依赖引用,在 application.yml 中配置不同的变量。

3.1 添加依赖

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-configuration-processor</artifactId>
  4. <optional>true</optional>
  5. </dependency>

配置该依赖的目的是在编写 application.yml 时,自定义的属性有代码提示。它会生成配置元数据,无需自己手动编写。

3.2 定义配置的实体类

创建 com.yygnb.demo.config.DocInfo,将 SpringDocConfig 中写死的属性都移到这个配置实体类中:

  1. @Data
  2. @Component
  3. @ConfigurationProperties(prefix = "doc-info")
  4. public class DocInfo {
  5. private String title = "Demo Title";
  6. private String description = "Demo Description";
  7. private String version = "v0.0.1";
  8. private String websiteName = "Demo Website";
  9. private String websiteUrl = "http://www.yygnb.com";
  10. }

注解 @ConfigurationProperties(prefix = "doc-info") 声明配置属性,在 application.yml 配置时就可以使用 doc-info。

3.3 重构 SpringDocConfig

在 SpringDocConfig 中引入 DocInfo,并通过构造函数进行注入:

  1. @RequiredArgsConstructor
  2. @Configuration
  3. public class SpringDocConfig {
  4. private final DocInfo docInfo;
  5. @Bean
  6. public OpenAPI springShopOpenAPI() {
  7. return new OpenAPI()
  8. .info(new Info().title(docInfo.getTitle())
  9. .description(docInfo.getDescription())
  10. .version(docInfo.getVersion()))
  11. .externalDocs(new ExternalDocumentation().description(docInfo.getWebsiteName())
  12. .url(docInfo.getWebsiteUrl()));
  13. }
  14. }

补充一个小点:注解 @RequiredArgsConstructor 是 lombok 中提供的,它等价于在类中编写了方法:

  1. public SpringDocConfig(DocInfo docInfo) {
  2. this.docInfo = docInfo;
  3. }

构造注入时,在构造函数中写大量的属性,毫无意义。既然已经使用了 @Data 注解,为啥不用 @RequiredArgsConstructor 呢?

3.4 使用自定义配置

自定义配置已经完成,可以在 application.yml 中使用 DocInfo 对应的配置了:

  1. doc-info:
  2. title: SpringBoot Demo演示
  3. description: 学习 Spring Boot 2.7.2

DocInfo 所有属性都定义了默认值,在 application.yml 可以覆盖默认值,如上面的 titledescription 属性。重启服务查看运行效果:

4 集成 knife4j

在之前 springfox-swagger 的时代,很多同学不喜欢 swagger-ui 的界面风格,会集成 knife4j 的 ui。Spring Doc 也可以集成 knife4j。

如果要使用 knife4j ,Spring Doc 的配置中需要添加分组配置,我们这里添加一个最简单的分组配置。

com.yygnb.demo.config.SpringDocConfig

  1. @RequiredArgsConstructor
  2. @Configuration
  3. public class SpringDocConfig {
  4. private final DocInfo docInfo;
  5. @Bean
  6. public OpenAPI heroOpenAPI() {
  7. return new OpenAPI()
  8. .info(new Info().title(docInfo.getTitle())
  9. .description(docInfo.getDescription())
  10. .version(docInfo.getVersion()))
  11. .externalDocs(new ExternalDocumentation().description(docInfo.getWebsiteName())
  12. .url(docInfo.getWebsiteUrl()));
  13. }
  14. @Bean
  15. public GroupedOpenApi publicApi() {
  16. return GroupedOpenApi.builder()
  17. .group(docInfo.getTitle())
  18. .pathsToMatch("/**")
  19. .build();
  20. }
  21. }

如果不添加这个 GroupedOpenApi 实例,knife4j ui就显示不出来。

在 pom.xml 中引入 knife4j

  1. <properties>
  2. ...
  3. <knife4j-springdoc-ui.version>3.0.3</knife4j-springdoc-ui.version>
  4. </properties>
  5. <dependencies>
  6. ...
  7. <dependency>
  8. <groupId>com.github.xiaoymin</groupId>
  9. <artifactId>knife4j-springdoc-ui</artifactId>
  10. <version>${knife4j-springdoc-ui.version}</version>
  11. </dependency>
  12. </dependencies>

启动服务,访问:

  1. http://localhost:9099/doc.html

显示 knife4j 的ui:



今日优雅哥(工\/youyacoder)学习结束,期待关注留言分享~~

集成 Spring Doc 接口文档和 knife4j-SpringBoot 2.7.2 实战基础的更多相关文章

  1. Spring Boot 集成 Swagger生成接口文档

    目的: Swagger是什么 Swagger的优点 Swagger的使用 Swagger是什么 官网(https://swagger.io/) Swagger 是一个规范和完整的框架,用于生成.描述. ...

  2. Spring Boot 集成 Swagger 构建接口文档

    在应用开发过程中经常需要对其他应用或者客户端提供 RESTful API 接口,尤其是在版本快速迭代的开发过程中,修改接口的同时还需要同步修改对应的接口文档,这使我们总是做着重复的工作,并且如果忘记修 ...

  3. Springboot集成swagger2生成接口文档

    [转载请注明]: 原文出处:https://www.cnblogs.com/jstarseven/p/11509884.html    作者:jstarseven    码字挺辛苦的.....   一 ...

  4. Springboot系列(七) 集成接口文档swagger,使用,测试

    Springboot 配置接口文档swagger 往期推荐 SpringBoot系列(一)idea新建Springboot项目 SpringBoot系列(二)入门知识 springBoot系列(三)配 ...

  5. spring boot使用swagger生成api接口文档

    前言 在之前的文章中,使用mybatis-plus生成了对应的包,在此基础上,我们针对项目的api接口,添加swagger配置和注解,生成swagger接口文档 具体可以查看本站spring boot ...

  6. SpringBoot 如何生成接口文档,老鸟们都这么玩的!

    大家好,我是飘渺. SpringBoot老鸟系列的文章已经写了两篇,每篇的阅读反响都还不错,果然大家还是对SpringBoot比较感兴趣.那今天我们就带来老鸟系列的第三篇:集成Swagger接口文档以 ...

  7. springboot+swagger接口文档企业实践(上)

    目录 1.引言 2.swagger简介 2.1 swagger 介绍 2.2 springfox.swagger与springboot 3. 使用springboot+swagger构建接口文档 3. ...

  8. restful接口文档

    1.先理清业务bai流程 2.定义前后端开发的接口规范.比如json的格dao式,url的格式 3.定内义接口文容档,这里的接口文档一般就是对应后台的实体reqVo(调用后台接口<控制器> ...

  9. SpringCloud微服务实战——搭建企业级开发框架(六):使用knife4j集成Swagger2接口文档

    knife4j是为集成Swagger生成api文档的增强解决方案,前后端Java代码以及前端Ui模块进行分离,在微服务架构下使用更加灵活, 提供专注于Swagger的增强解决方案,不同于只是改善增强前 ...

随机推荐

  1. Dockerfile指令与Docker-compose容器编排-搭建docker私有仓库

    目录 一:部署应用映射外部目录(持久化) 总结 二:迁移与备份(容器保存为镜像) 1.django执行gitee,项目提交到远端 2.其他操作 3.操作步骤 4.容器保存为镜像 5.把镜像打包成压缩包 ...

  2. 【工程应用七】接着折腾模板匹配算法 (Optimization选项 + no_pregeneration模拟 + 3D亚像素插值)

    在折腾中成长,在折腾中永生. 接着玩模板匹配,最近主要研究了3个课题. 1.创建模型的Optimization选项模拟(2022.5.16日) 这两天又遇到一个做模板匹配隐藏的高手,切磋起来后面就还是 ...

  3. goose消元

    ps.改了标题 魔板 思路:按序消除变量,用当前行(i)[行i消\(x_i\)元素],消后面的每一行的i元素 最后按逆序回代值 注意若有i~n行i元素系数都为0说明没有唯一解(其余x的解跟i元素有关) ...

  4. HTML5续集

    H5 input新增属性 1.color 拾色器 2.Email 电子邮件 3.tel 电话 4.datetime-local 本地日期和时间 5.range 范围 6.url 路径,地址 7.sea ...

  5. 在jupyter中配置c++内核

    安装 xeus-cling conda install xeus-cling -c conda-forg xeus-cling 是一个用于编译解释于C++的Jupyter内核目前,支持Mac与Linu ...

  6. 『忘了再学』Shell流程控制 — 35、多分支case条件语句

    目录 1.case条件语句介绍 2.case语句需要注意的内容 3.练习 示例1 示例2 1.case条件语句介绍 case语句和if-elif-else语句一样都是多分支条件语句,不过和if多分支条 ...

  7. BUUCTF-你竟然赶我走

    你竟然赶我走 首先看到这个图片没啥感觉,直接用16进制打开了.拖到最下面果然有flag flag{stego_is_s0_bor1ing}

  8. TypeScript(7)泛型

    泛型 指在定义函数.接口或类的时候,不预先指定具体的类型,而在使用的时候再指定具体类型的一种特性. 引入 下面创建一个函数, 实现功能: 根据指定的数量 count 和数据 value , 创建一个包 ...

  9. 集成学习——XGBoost(手推公式)

  10. Prometheus安装教程

    Prometheus安装教程 欢迎关注H寻梦人公众号 参考目录 docker安装Prometheus 基于docker 搭建Prometheus+Grafana prometheus官方文档 dock ...