【微服务】springboot整合swagger多种模式使用详解

目录

一、前言

1.1 编写API文档

1.2 使用一些在线调试工具

1.3 postman

1.4 swagger

二、swagger简介

2.1 背景

2.2 swagger优缺点

2.2.1 swagger优点

2.2.2 swagger缺点

2.2.3 swagger使用场景

三、swagger常用的几种整合模式

3.1 swagger2

3.2 knife4j

3.2.1 knife4j特点

3.2.2 knife4j版本说明

3.3 Springdoc

3.3.1 SpringDoc简介

四、springboot整合swagger多种模式案例

4.1 springboot整合swagger2

4.1.1 添加如下核心依赖

4.1.2 配置文件

4.1.3 自定义swagger配置类

4.1.4 自定义测试接口

4.1.5 自定义实体类

4.1.6 访问swagger界面

4.2 springboot整合knife4j

4.2.1 引入核心依赖

4.2.2 自定义配置类

4.2.3 添加测试接口

4.2.4 自定义实体类

4.2.5 访问UI界面

4.3 springboot整合springdoc

4.3.1 添加核心依赖

4.3.2 核心配置文件

4.3.3 自定义配置类

4.3.4 自定义测试接口

4.3.5 访问UI界面

五、写在结尾


一、前言

在如今迭代速度越来越快的开发模式下,使用springboot作为服务端框架进行开发的项目越来越多,当后端API开发并自测完成后,如何能让前端同事与你快速高效的对接API呢?可能大家知道的有下面几种方式:

1.1 编写API文档

这是很多公司比较传统的做法,一般来说,这种方式对API开发者有着较高的要求,因为文档的编写过程相对耗时,所以API在开发之前,需要对API的各项参数进行严格的评审,以便减少在对接过程中的改动带来的事件成本。文档可以使用传统的word文档,或者使用markdown编辑。

1.2 使用一些在线调试工具

如今市面上出现了很多在线接口调试工具,只需要将你的API服务部署到服务器,然后就可以在线远程调试了。

1.3 postman

这是一个比较传统但也很好用的本地调试工具,对于团队来说,服务端开发人员可将A开发完成的API录入进去,然后通过团队分享的模式将API分享出去,前端就可以拿到API列表进行调试对接了。

1.4 swagger

随着swagger的使用规模越来越大,知名度也越来越高,尤其是在敏捷开发模式下具备更多的优势而被很多开发团队接纳,只需要服务端集成swagger依赖,再做简单的配置即可使用了,而且使用学习成本可以说几乎为零。

二、swagger简介

2.1 背景

在当前前后端分离成了产品快速迭代的基本模式后,如何快速完成API与前端的快速联调成了产品阶段性发布的关键因素,在这个背景下,尽管前端可以通过mock数据完成自身的功能验证,但是没有与服务端进行真实数据的联调,总觉得不踏实,但不同的团队联调的方式不一样,这就造成了有的团队使用的工具简单,联调效率高,有的复杂,造成联调效率很低,甚至带来了新的学习成本。

在这样的背景下,如何提升与API的快速联调,并尽可能的降低团队人员的学习成本呢?于是swagger的出现就很好的解决了这样一个难题。

2.2 swagger优缺点

2.2.1 swagger优点

使用swager具备如下优点:

  • 整合简单,只需要引入一个swagger的jar包,并做简单的配置即可;
  • 自动生成文档,只需在接口中使用swagger的相关注解进行标注,就能生成对应的接口文档;
  • 自动更新文档,由于是动态生成的,所以如果你修改了接口,文档也会自动对应修改(如果你也更新了注解的话)。这样就不会发送我修改了接口,却忘记更新接口文档的情况;
  • 支持在线调试,swagger提供了在线调用接口的功能;

2.2.2 swagger缺点

尽管swagger为API的管理带来了便利,但仍然存在一些缺点,

  • 不能创建测试用例,只能提供一个简单的在线调试,如果你想存储测试用例,则需要选择其他的工具了,比如postman,或者通过swagger导出yaml文件进行存储;
  • 程序中需要遵循一些基本的编码规范。比如你需要返回一个json数据,而这个数据可能是一个Map格式的,那么我们此时不能标注这个Map格式的返回数据的每个字段的说明,而如果是一个实体类的话,则需要为实体类中的属性标注特定的注解,这样带来的问题很明显就是程序的实体类中看起来有些乱,不够整洁,显得冗余;
  • 做不到API的动态刷新,假如当前前端正在使用的某个接口你在本地改了之后忘了重启,可能前端用到的还是老接口;
  • 存在一定程度的安全问题,UI界面上会暴露太多的信息,比如某个接口中,前端可能只需要3个必填的参数,但是在swagger的UI界面上,会把对象的所有字段信息都填进去,这样看起来显得比较凌乱冗余;

2.2.3 swagger使用场景

并不是所有的项目都适合使用swagger,比如一些比较老的项目,可能因为版本的问题如果强势集成,带来的时间人力成本巨大,还有一些比如对安全性要求特别高的项目,不允许随意暴露服务端的API到外网,使用swagger就不太合适了,不过从目前的趋势来看,swagger的使用还是能够整体提升开发和对接效率的,这里总结下面的一些场景提供参考:

  • 业务体量较小,功能迭代迅速,对开发时间要求很紧的项目,可以考虑使用swagger;
  • 对安全性要求较低,或者仅在公司内网环境使用,或者仅仅是开发阶段使用,这种也是可以考虑在开发阶段使用swagger的;
  • 服务端框架是springboot的,springboot目前占据着微服务框架的主流,因此与swagger的集成比较方便;

三、swagger常用的几种整合模式

以springboot与swagger整合为例,提供了多种方式可以使用,常用的主要有下面几种,掌握这几种应该足够可以应对大多数的场景了,

3.1 swagger2

这是原始的一种方式,也是很多小团队经常使用的一种方式,直接引入swagger的基本依赖jar包就可以使用了。与springboot的整合主要包括下面几个包:

  • springfox-swagger2;
  • springfox-swagger-ui;

3.2 knife4j

Knife4j的前身是swagger-bootstrap-ui,前身swagger-bootstrap-ui是一个纯swagger-ui的ui皮肤项目;

项目初衷是为了写一个增强版本的swagger的前端ui,但随着项目的发展,面对越来越多个性化需求,不得不编写后端Java代码以满足新的需求。

在swagger-bootstrap-ui的1.8.5~1.9.6版本之间,采用的是后端Java代码和Ui都混合在一个Jar包里面的方式提供给开发者使用。这种方式虽说对于集成swagger来说很方便,只需要引入jar包即可,但是在微服务架构下显得有些臃肿。因此项目正式更名为knife4j,取名knife4j是希望她能像一把匕首一样小巧,轻量,并且功能强悍。更名也是希望把她做成一个为Swagger接口文档服务的通用性解决方案,不仅仅只是专注于前端Ui前端。

3.2.1 knife4j特点

  • swagger-bootstrap-ui的所有特性都会集中在knife4j-spring-ui包中,并且后续规划也会满足开发者更多的个性化需求;
  • 主要的变化是,项目的相关类包路径更换为com.github.xiaoymin.knife4j前缀,开发者使用增强注解时需要替换包路径;
  • 后端Java代码和ui包分离为多个模块的jar包,以面对在目前微服务架构下,更加方便的使用增强文档注解(使用SpringCloud微服务项目,只需要在网关层集成UI的jar包即可,因此分离前后端);
  • knife4j沿用swagger-bootstrap-ui的版本号,第1个版本从1.9.6开始,关于使用方法,请参考文档(摘自 knife4j 官方介绍);

3.2.2 knife4j版本说明

knife4j 主要的版本基本如下

1.9.6 蓝色皮肤风格,开始更名,增加更多后端模块
2.0~2.0.5 Ui重写,底层依赖的springfox框架版本是2.9.2
2.0.6~ springfox框架版本升级知2.10.5,OpenAPI规范是v2
3.0~ 底层依赖springfox框架版本升级至3.0.3,OpenAPI规范是v3

3.3 Springdoc

相对前两种来说,目前springdoc的热度很高,一是这个框架比较新,而且代码维护更新速度快,而且在与springboot项目整合的时候还提供了安全插件,可以在一定程度上提升使用的安全性。git的地址为:springdoc源码地址

3.3.1 SpringDoc简介

SpringDoc是一款可以结合SpringBoot使用的API文档生成工具,基于OpenAPI 3,目前在Github上已有1.7K+Star,更新发版还是挺勤快的,是一款更好用的Swagger库!值得一提的是SpringDoc不仅支持Spring WebMvc项目,还可以支持Spring WebFlux项目,甚至Spring Rest和Spring Native项目,总之非常强大,下面是一张SpringDoc的架构图。

四、springboot整合swagger多种模式案例

以上从理论上对swagger常用的几种使用方式做了了解,接下来将通过实际案例分别做详细的说明。

4.1 springboot整合swagger2

前置准备,搭建springboot工程,目录结构如下

4.1.1 添加如下核心依赖

如下仅为核心依赖,可以根据自身情况酌情添加

<dependencies>

        <dependency>
            <groupId>org.modelmapper</groupId>
            <artifactId>modelmapper</artifactId>
            <version>3.1.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--swagger API获取-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>

        <!--swagger-ui API获取-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>


    </dependencies>

4.1.2 配置文件

使用这种方式不需要有太多配置,这里只配置一个端口即可

server.port=8088

4.1.3 自定义swagger配置类

该类是整个整合过程中最重要的一个配置,主要包括:

  • 定义接口的扫描路径;
  • swagger-ui的界面显示信息;
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.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class SwaggerConfig {


    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                //用于生成API信息
                .apiInfo(apiInfo())
                //select()函数返回一个ApiSelectorBuilder实例,用来控制接口被swagger做成文档
                .select()
                //用于指定扫描哪个包下的接口
                .apis(RequestHandlerSelectors.basePackage("com.congge.controller"))
                //选择所有的API,如果你想只为部分API生成文档,可以配置这里
                .paths(PathSelectors.any())
                .build();
    }

    /**
     * 用于定义API主界面的信息,比如可以声明所有的API的总标题、描述、版本
     * @return
     */
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                //用来自定义API的标题
                .title("SpringBoot项目SwaggerAPIAPI测试")
                //用来描述整体的API
                .description("SpringBoot项目SwaggerAPI描述信息")
                //创建人信息
                .contact(new Contact("测试人员","http://localhost:8082/swagger-ui.html","[email protected]"))
                //用于定义服务的域名
                //.termsOfServiceUrl("")
                .version("1.0") //可以用来定义版本
                .build();
    }

}

4.1.4 自定义测试接口

自定义一个测试接口,可以说为了能够让工程中的接口在swagger-ui中能够调试,最重要的就是需要在类上添加这个注解:@Api,其他的方法上面的一些注解,可以参考官方文档进行配置即可;

//http://localhost:8088/swagger-ui.html  主页访问地址

@RestController
@Api(tags = "UserController", description = "UserController | 测试swagger")
public class UserController {

    @GetMapping("getById")
    @ApiOperation(value="getById 方法", notes="getById,根据ID获取账户信息")
    public User getById(){
        return new User("001","jerry","123456");
    }

    @PostMapping("/save")
    public String saveUser(UserRequest userRequest){
        User user = new User();
        BeanUtils.copyProperties(userRequest,user);
        return "success";
    }

}

4.1.5 自定义实体类

在很多情况下,接口中的参数是对象类型,这时候为了让前端对接的同事知道对象中的每个参数的含义,最好按照swagger的规范,给每个对象的属性添加一些swagger的注解,下面提供一个示例;

@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(value="用户登录表单对象",description="用户登录表单对象")
public class User implements Serializable {

    private static final long serialVersionUID = -2896873555774275129L;

    @ApiModelProperty(value = "用户ID",required = true,example = "001")
    private String id;

    @ApiModelProperty(value = "用户名称",required = true,example = "jerry")
    private String userName;

    @ApiModelProperty(value = "密码",required = true,example = "123456")
    private String passWord;

}

4.1.6 访问swagger界面

启动服务,然后浏览器访问:http://localhost:8088/swagger-ui.html,至于怎么调试使用的话,有兴趣的同学可以自行尝试下,还是比较简单的;

4.2 springboot整合knife4j

上文简单介绍了knife4j的背景,接下来看看在springboot中整合knife4j的详细步骤,首先还是提前创建一个空的springboot工程,目录结构如下

4.2.1 引入核心依赖

这里做演示只需要两个包,如果有其他的需求可以继续追加即可;

    <dependencies>
        <!-- Spring Boot Web依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.github.xiaoymin</groupId>
            <artifactId>knife4j-spring-boot-starter</artifactId>
            <version>3.0.3</version>
        </dependency>

    </dependencies>

4.2.2 自定义配置类

这个和上面整合swagger2类似,需要自定义一个类,里面定义UI界面的显示信息,以及扫描的接口类所在的包路径等信息

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.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
public class Knife4jConfiguration {

    @Bean(value = "defaultApi2")
    public Docket defaultApi2() {
        String groupName="3.X版本";
        Docket docket=new Docket(DocumentationType.OAS_30)
                .apiInfo(new ApiInfoBuilder()
                        .title("这是knife4j API ")
                        .description("这是knife4j,记录了API相关的出参和入参信息")
                        .termsOfServiceUrl("http://yaomaoyang.com")
                        .contact(new Contact("congge","http://127.0.0.1","[email protected]"))
                        .version("3.0")
                        .build())
                //分组名称
                .groupName(groupName)
                .select()
                //这里指定Controller扫描包路径
                .apis(RequestHandlerSelectors.basePackage("com.congge.controller"))
                .paths(PathSelectors.any())
                .build();
        return docket;
    }
}

4.2.3 添加测试接口

为了能够让接口在UI界面上展示,最重要的就是在类上添加的这个@Api注解,其他的注解可根据需要在接口类方法上进行标注即可,和上面使用swagger类似;

@RestController
@RequestMapping(value = "/user")
@Api(tags = "用户管理API")
public class UserController {

    /**
     * 根据ID获取账户信息
     * @param id
     * @return
     */
    @GetMapping(value = "/getById")
    @ApiImplicitParam(name = "name",value = "姓名",required = true)
    @ApiOperation("根据ID获取账户信息")
    public User test(@RequestParam("id") String id){
        User user = new User();
        user.setId(id);
        user.setPassWord("123456");
        user.setUserName("jerry");
        return user;
    }

}

4.2.4 自定义实体类

某些接口中接收的参数如果是一个对象的话,为了让其他同学能够看懂对象中的参数,可以在对象上添加knife4j提供的注解,下面给一个示例

@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(value="用户登录表单对象",description="用户对象参数")
public class User implements Serializable {

    private static final long serialVersionUID = -2896873555774275129L;

    @ApiModelProperty(value = "用户ID",required = true,example = "001")
    private String id;

    @ApiModelProperty(value = "用户名称",required = true,example = "jerry")
    private String userName;

    @ApiModelProperty(value = "密码",required = true,example = "123456")
    private String passWord;

}

4.2.5 访问UI界面

启动工程,然后通过这个地址访问界面:http://localhost:8082/doc.html,看这个界面是不是觉得风格上显得更专业一点;

4.3 springboot整合springdoc

springdoc相比前两种,出现的稍晚,但是目前来看,其受欢迎的程度似乎更好,一方面来说swagger的基本功能它都有,同时,在访问的安全性上有一定的保障,下面来看具体的整合步骤,提前创建一个springboot工程,目录结构如下:

4.3.1 添加核心依赖

 其他的依赖柯根据自身的情况酌情引用

    <dependencies>
        <!-- Spring Boot Web依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- springdoc swagger ui -->
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-ui</artifactId>
            <version>1.7.0</version>
        </dependency>

        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-javadoc</artifactId>
            <version>1.7.0</version>
        </dependency>
    </dependencies>

4.3.2 核心配置文件

在application.yml文件中添加如下配置,这些配置见名知意这里就不做过多解释,其中:

api-docs.path: /v3/api-docs这个配置是为了获取接口的yml文档的地址

里面还有更丰富的配置可以参阅网上的资料,都有比较详细的说明,比如还可以配置打开UI界面的前置路径等;

# springdoc配置
springdoc:
  # 分组配置
  group-configs:
    - group: 用户管理
      packages-to-scan: com.congge.controller
      paths-to-match: /users/**
    - group: 角色管理
      packages-to-scan: com.congge.controller
      paths-to-match: /roles/**
  api-docs:
    enabled: true
    path: /v3/api-docs

server:
  port: 8087

4.3.3 自定义配置类

自定义配置可以对项目中的各类API进行分组管理,以bean的方式注入到spring容器中;

import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.ExternalDocumentation;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.servers.Server;
import org.springdoc.core.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Arrays;

@Configuration
public class OpenApiConfig {

    /*@Bean
    public OpenAPI springShopOpenAPI() {
        return new OpenAPI()
                .info(new Info().title("Springdoc OAS3.0 - RESTful API")
                        .description("Springdoc OAS3.0 构建RESTful API")
                        .version("1.0")
                        .license(new License().name("Apache 2.0").url("http://springdoc.org")))
                .servers(Arrays.asList(
                        new Server().description("开发环境").url("http://localhost:8087")
                ))
                .externalDocs(new ExternalDocumentation()
                        .description("SpringShop Wiki Documentation")
                        .url("https://springshop.wiki.github.org/docs"));
    }*/

    @Bean
    public OpenAPI openAPI() {
        return new OpenAPI()
                .components(new Components())
                .info(new Info()
                        .title("User Manager API")
                        .description("用户管理系统API.")
                        .version("1.0"));
    }

    @Bean
    public GroupedOpenApi frontApi() {
        return GroupedOpenApi.builder()
                .group("frontApi")
                .pathsToMatch(new String[]{"/users/**", "/roles/**"})
                .packagesToExclude("com.congge.controller")
                .build();
    }
}

4.3.4 自定义测试接口

注意接口类上的这个注解,@Tag,是UI界面上能够识别的关键;

//http://localhost:8087/swagger-ui/index.html?urls.primaryName=%E7%94%A8%E6%88%B7%E7%AE%A1%E7%90%86

@Tag(name = "用户管理", description = "用户管理FrontApi")
@RestController
@RequestMapping("/users")
public class UserController {

    /**
     * 查询用户详细信息
     *
     * @param id 用户ID
     * @return 用户信息
     */
    @GetMapping("/get")
    public UserInfo getUser(@RequestParam String id) {
        return new UserInfo();
    }

}

@Data
@Schema(description = "用户返回实体对象")
class UserInfo {
    @Schema(description = "用户名称")
    private String userName;
    @Schema(description = "用户密码")
    private String passWord;
}

4.3.5 访问UI界面

启动工程,访问界面地址:http://localhost:8087/swagger-ui/index.html,看到如下效果,具体在UI界面上进行接口调试的时候与上面两种是类似的;

五、写在结尾

本篇详细总结了springboot整合swagger的多种使用方式,希望能够为您的日常开发带去帮助,本篇到此结束,感谢观看!

猜你喜欢

转载自blog.csdn.net/congge_study/article/details/130996112