SpringBoot整合Swagger-UI实现在线API文档

310 阅读8分钟

SpringBoot整合Swagger-UI实现在线API文档

1.前言☕

大家好,我是Leo哥🫣🫣🫣,今天给大家带来关于精品SpringBoot专栏,暂且就给他起名为循序渐进学SpringBoot,这里我参考了我上一个专栏:循序渐进学SpringSecurity6。有需要的朋友可以抓紧学习来哈,带你从SpringSecurity从零到实战项目。好了,我们进入正题,为什么会有SpringBoot这个专栏呢,是这样的,今年Leo哥也是正在重塑知识体系,从基础到框架,而SpringBoot又是我们框架中的核心,我觉得很有必要通过以博客的形式将我的知识系列进行输出,同时也锻炼一下自己的写作能力,如果能帮到大家那就更好啦!!!本地系列教程会从SpringBoot基础讲起,会以知识点+实例+项目的学习模式由浅入深对Spring Boot框架进行学习&使用。好了,话不多说让我们开始吧😎😎😎。

2.什么是swagger

Swagger 是一个开源的 API 设计和文档工具,它可以帮助开发人员更快、更简单地设计、构建、文档化和测试 RESTful API。Swagger 可以自动生成交互式 API 文档、客户端 SDK、服务器 stub 代码等,从而使开发人员更加容易地开发、测试和部署 API。

image-20240324144917933

简单来说就是把我们的后端接口暴露出去,在页面中,我们开发者可以很直观的进行调用以及代码测试,大大提高了我们的开发效率。

有了 Swagger 后,可以通过简单的配置生成接口的展示页面,把接口的请求参数、返回结果通过可视化的形式展示出来,并且提供了便捷的测试服务。

  • 前端程序员可以通过接口展示页面查看需要传递的请求参数和返回的数据格式,不需要后端程序员再编写接口文档了;
  • 后端程序员可以通过接口展示页面测试验证自己的接口是否符合预期,降低了开发阶段的调试成本。

没有swagger我们前后端分离开发,前后端接口文档不一致的问题搞的确实头疼,前端经常抱怨后端给的接口文档与实际情况不一致。后端又觉得编写及维护接口文档会耗费不少精力,经常来不及更新。

我画一张图来描述一下具体的场景:

image-20240324150833804

3.Swagger 如何帮助实现 API

Swagger 可以帮助开发人员更容易地设计、文档化、测试和部署 RESTful API。Swagger 的自动化工具可以加快 API 的开发速度和测试速度,并且可以减少错误和提高代码的可维护性。因此,Swagger 已成为一个流行的 API 设计和文档工具,被广泛应用于各种 Web 应用程序和云服务中。

Swagger 帮助实现 API 的方式包括:

  • 设计和文档化 API:Swagger 提供了一种简单、易于使用的方式来设计和文档化 RESTful API。开发人员可以使用 Swagger UI 来创建和编辑 API 规范,然后使用 Swagger Editor 生成符合 OpenAPI 规范的 API 文档。Swagger UI 可以生成可交互的 API 文档,使开发人员更容易了解 API 的结构和用法。
  • 自动生成代码:Swagger 可以自动从 OpenAPI 规范中生成客户端 SDK 和服务器 stub 代码。这些代码可以减少开发人员的工作量,加快代码开发速度。
  • 测试 API:Swagger 提供了一个集成的测试工具,可以帮助开发人员测试 API 的功能、性能和可靠性。Swagger UI 中提供了一个测试页面,允许开发人员使用各种 HTTP 请求方法来测试 API 的不同端点。
  • 集成和部署:Swagger 可以与许多流行的开发和部署工具(如 Git、Jenkins、Docker 等)集成,以便更容易地部署和管理 API。Swagger 可以自动生成 Swagger UI,使开发人员可以直接从浏览器访问 API 文档和测试页面。

4.SpringBoot整合swagger-UI

4.1 环境说明

环境说明:Windows11 + Idea2023.3.4 + Jdk1.8 + SpringBoot 2.3.1.RELEASE + MySQL8 + MyBaitsPlus3.5.3 + springfox3

4.2 导入Maven依赖

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--引入mybatisplus -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-boot-starter</artifactId>
            <version>3.0.0</version>
        </dependency>

不是说添加 Swagger 的依赖吗?怎么添加的是 springfox-boot-starter 呢?

这是因为:

  • Swagger 是一种规范。

  • springfox-swagger 是一个基于 Spring 生态系统的,Swagger 规范的实现。

    springfox-boot-starter 是 springfox 针对 SpringBoot 项目提供的一个starter,简化 Swagger 依赖的导入,否则我们就需要在 pom.xml 文件中添加 springfox-swagger、springfox-swagger-ui 等多个依赖。

4.3 添加swagger配置

package org.javatop.swagger.config;
​
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.oas.annotations.EnableOpenApi;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
​
/**
 * @author : Leo
 * @version 1.0
 * @date 2024-03-23 21:08
 * @description : swagger配置
 */
@Configuration
@EnableOpenApi
public class SwaggerConfig {
    @Bean
    public Docket docket() {
        Docket docket = new Docket(DocumentationType.OAS_30)
                .apiInfo(apiInfo()).enable(true)
                .select()
                //apis: 添加swagger接口提取范围
                .apis(RequestHandlerSelectors.basePackage("org.javatop.swagger.controller"))
                .paths(PathSelectors.any())
                .build();
​
        return docket;
    }
​
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("Leo哥SpringBoot项目教程合集")
                .description("Leo哥SpringBoot项目教程合集之swagger学习")
                .contact(new Contact("程序员Leo", "https://gaoziman.blog.csdn.net/","m2942894660@163.com"))
                .version("v1.0")
                .build();
    }
}
  1. @Configuration:这是一个Spring框架的注解,表示这个类是一个配置类。当这个类被扫描到时,Spring会自动创建它的Bean对象。
  2. @EnableOpenApi:这也是Spring框架的注解,表示启用Swagger功能。
  3. SwaggerConfig类:这是用于配置Swagger框架的类。
  4. docket()方法:这是一个Bean方法,用于创建一个Docket对象。Docket是一个用于管理Swagger配置的类,它负责生成API文档。
  5. docket()方法中,调用了Docket构造方法,并传入了一些参数。
  6. DocumentationType.OAS_30:表示使用OpenAPI 3.0的规范。
  7. apiInfo()方法:这是一个Bean方法,用于创建一个ApiInfo对象。ApiInfo用于存储API的标题、描述等信息。
  8. apiInfo()方法中,使用了ApiInfoBuilder来构建ApiInfo对象。
  9. title:设置API的标题。
  10. description:设置API的描述。
  11. contact:设置API的联系人信息,包括姓名、URL和邮箱。
  12. version:设置API的版本号。
  13. build():调用ApiInfoBuilderbuild()方法,将所有设置好的参数合并成一个ApiInfo对象。
  14. select():调用Docketselect()方法,用于设置Swagger接口提取范围。
  15. .apis(RequestHandlerSelectors.basePackage("org.javatop.swagger.controller")):设置接口提取范围,只包括org.javatop.swagger.controller包下的所有API。
  16. .paths(PathSelectors.any()):设置路径匹配规则,任何路径的API都会被提取。
  17. .build():调用Docketbuild()方法,将所有设置好的参数合并成一个Docket对象。
  18. 最后,返回创建好的Docket对象。

4.4 编写controller代码

这里就是一个很简单的CRUD的基本代码,下面直接给出。

package org.javatop.swagger.controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.javatop.swagger.domain.User;
import org.javatop.swagger.service.UserService;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;

/**
 * (user)表控制层
 *
 * @author Leo
 */
@RestController
@Api(tags = "用户管理")
@RequestMapping("/user")
public class UserController {
​
    @Resource
    private UserService userService;
​
​
    /**
     * 获取用户列表
     *
     * @return
     */
    @ApiOperation("查询所有用户")
    @GetMapping("/list")
    public List<User> getUserList() {
        return userService.list();
    }
​
​
    /**
     * 根据id获取用户信息
     *
     * @param id 用户id
     * @return 用户
     */
    @ApiOperation("根据id查询用户")
    @GetMapping("/{id}")
    public User getUser(@PathVariable Integer id) {
        return userService.getById(id);
    }
​
​
    /**
     * 新增用户信息
     *
     * @param user 用户
     * @return 新增结果
     */
    @ApiOperation("新增用户")
    @PostMapping("/save")
    public boolean saveUser(@RequestBody User user) {
        return userService.save(user);
    }
​
​
    /**
     * 修改用户信息
     *
     * @param user 用户
     * @return 修改结果
     */
    @ApiOperation("修改用户")
    @PutMapping("/update")
    public boolean updateUser(@RequestBody User user) {
        return userService.updateById(user);
    }
​
​
    /**
     * 删除用户信息
     *
     * @param id 用户id
     * @return 删除结果
     */
    @ApiOperation("删除用户")
    @DeleteMapping("/{id}")
    public boolean deleteUser(@PathVariable Integer id) {
        return userService.removeById(id);
    }
​
}

但是注意:

  1. @Api注解,用在类上,该注解将控制器标注为一个 Swagger 资源。该注解有 3 个属性:

    image-20240324151815289

  • tags,具有相同标签的 API 会被归在一组内展示
  • value,如果 tags 没有定义,value 将作为 API 的 tags 使用。
  • description,已废弃
  1. @ApiOperation注解,用在方法上,描述这个方法是做什么用的。该注解有 4 个属性:

    image-20240324151835960

  • value 操作的简单说明,长度为120个字母,60个汉字。
  • notes 对操作的详细说明。
  • httpMethod HTTP请求的动作名,可选值有:"GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS" and "PATCH"。
  • code 默认为200,有效值必须符合标准的HTTP Status Code Definitions。

4.5 启动项目测试

在浏览器中输入 http://localhost:8007/swagger-ui/ 就可以访问 Swagger 生成的 API 文档了。

image-20240324151956597

接下来,我们随便选择一个接口来进行页面测试。

首先点开查询所有用户,点击 Ty it out,然后Execute执行即可看到结果。

4.8 版本不兼容问题

因SpringBoot2.6与springfox3有版本不兼容,大家可以注意,Leo哥这里SpringBoot版本使用的是 2.3.12.RELEASE

如果使用SpringBoot2.6的同学,启动项目可能会直接报错。

大概是这样的:

Caused by: java.lang.NullPointerException: Cannot invoke "org.springframework.web.servlet.mvc.condition.PatternsRequestCondition.getPatterns()" because "this.condition" is null

当然在Github有大佬已经给出了解决方案,凡事不会我们直接上Github,里面大神集云。

这里给出链接:github.com/spring-proj…

image-20240324152528194

当然还有一种解决方式就是和Leo哥一样,把SpringBoot的版本降低一些,直接从根源上面解决问题。

5.源码仓库

Github源码:github.com/gaoziman/Le…