前提

SpringFox 介绍

  • SpringFox 是⼀个开源的 API Doc 的框架, 它的前⾝是 swagger-springmvc,可以将我们的 Controller 中的⽅法以⽂档的形式展现。

  • 官⽅定义为: Automated JSON API documentation for API’s built with Spring。

  • springfox 官网:http://springfox.github.io/springfox/

  • Github 仓库:https://github.com/springfox/springfox

  • 通常 SpringBoot 项目整合 swagger 需要用到两个依赖:springfox-swagger2 和 springfox-swagger-ui,用于自动生成 swagger 文档。

    • springfox-swagger2:这个组件的功能用于项目中自动生成描述 API 的 json 文件
    • springfox-swagger-ui:就是将描述 API 的 json 文件解析出来,用一种更友好的方式呈现出来。

Swagger 介绍

  • 对于 Rest API 来说很重要的一部分内容就是文档,Swagger 提供了一套通过代码和注解自动生成文档的方法,这一点对于保证 API 文档的及时性将有很大的帮助。
  • Swagger 是一套基于 OpenAPI 规范(OpenAPI Specification,OAS)构建的开源工具,可以帮助设计、构建、记录以及使用 Rest API。
  • OAS 本身是一个 API 规范,它用于描述一整套 API 接口,包括一个接口是哪种请求方式、哪些参数、哪些 header 等,都会被包括在这个文件中。它在设计的时候通常是 YAML 格式,这种格式书写起来比较方便,而在网络中传输时又会以 json 形式居多,因为 json 的通用性比较强。
  • Swagger 主要包含了以下三个部分:
    • Swagger Editor:基于浏览器的编辑器,可以使用它编写 OpenAPI 规范。
    • Swagger UI:它会将编写的 OpenAPI 规范呈现为交互式的 API 文档。
    • Swagger Codegen:它可以通过为 OpenAPI(以前称为 Swagger)规范定义的任何 API 生成服务器存根和客户端 SDK 来简化构建过程。
  • 最新版本为 3.0 ,官方文档: https://swagger.io/

SpringFox 与 Swagger

  • Swagger 是⼀种规范。

  • springfox-swagger 是基于 Spring ⽣态系统的该规范的实现。

  • springfox-swagger-ui 是对 swagger-ui 的封装,使得其可以使⽤ Spring 的服务。

  • Springfox 其实是⼀个通过扫描代码提取代码中的信息,⽣成 API ⽂档的⼯具 。

    • API ⽂档的格式不⽌ Swagger 的 OpenAPI Specification ,还有 RAML , jsonapi
    • Springfox 的⽬标同样包括⽀持这些格式。
    • 这就能解 释那个 swagger2 的后缀了,这只是 Springfox 对 Swagger 的⽀持。

集成 swagger2

导入 Swagger2 依赖

  • 依赖如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <springfox-swagger.version>2.8.0</springfox-swagger.version>
    <swagger-bootstrap-ui.version>1.7.2</swagger-bootstrap-ui.version>

    <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 -->
    <dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>${springfox-swagger.version}</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger-ui -->
    <dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>${springfox-swagger.version}</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/com.github.xiaoymin/swagger-bootstrap-ui -->
    <dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>swagger-bootstrap-ui</artifactId>
    <version>${swagger-bootstrap-ui.version}</version>
    </dependency>

配置 Swagger

  • SwaggerConfig.java

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    package com.fcant.service_acti.config;

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    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;

    /**
    * SwaggerConfig
    * <p>
    * encoding: UTF-8
    *
    * @author Fcant 下午 23: 41 2020/8/1/0001
    */
    @Configuration
    @EnableSwagger2
    public class SwaggerConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("swagger-ui.html")
    .addResourceLocations("classpath:/META-INF/resources/");
    registry.addResourceHandler("/webjars/**")
    .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }

    /**
    * @author Fcant 13: 44 2019/12/5
    */
    @Bean
    public Docket petApi() {
    return new Docket(DocumentationType.SWAGGER_2)
    .apiInfo(apiInfo())
    .select()
    .apis(RequestHandlerSelectors.basePackage("com.fcant.service_acti.controller"))
    .paths(PathSelectors.any())
    .build();
    }

    /**
    * 该套 API 说明,包含作者、简介、版本、host、服务 URL
    * @return
    */
    private ApiInfo apiInfo() {
    return new ApiInfoBuilder()
    .title("Activiti Service API")
    .contact(new Contact("fcant","null","fcscanf@outlook.com"))
    .version("0.1")
    .termsOfServiceUrl("localhost:8080/swagger")
    .description("Activiti Service API")
    .build();
    }

    }

访问

  • 在浏览器地址输入 localhost:8080/swagger-ui.html 进入

集成 swagger3

兼容性说明

  • 需要 Java 8

  • 需要 Spring5.x(未在早期版本中测试)

  • 需要 SpringBoot 2.2+(未在早期版本中测试)

  • 应用主类可以不用增加注解 @EnableOpenApi,删除之前版本的 SwaggerConfig.java。

  • 在 springfox-boot-starter-3.0.0.jar 下可以找到一个 spring.factories,这个是一个 Spring Boot 特有的 SPI 文件,能够自动的发现并注册 Starter 组件的配置。里面有这样的配置:

    1
    2
    3
    # Auto Configure
    org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
    springfox.boot.starter.autoconfigure.OpenApiAutoConfiguration
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    @Configuration
    @EnableConfigurationProperties(SpringfoxConfigurationProperties.class)
    @ConditionalOnProperty(value = "springfox.documentation.enabled", havingValue = "true", matchIfMissing = true)
    @Import({
    OpenApiDocumentationConfiguration.class,
    SpringDataRestConfiguration.class,
    BeanValidatorPluginsConfiguration.class,
    Swagger2DocumentationConfiguration.class,
    SwaggerUiWebFluxConfiguration.class,
    SwaggerUiWebMvcConfiguration.class
    })
    @AutoConfigureAfter({ WebMvcAutoConfiguration.class, JacksonAutoConfiguration.class,
    HttpMessageConvertersAutoConfiguration.class, RepositoryRestMvcAutoConfiguration.class })
    public class OpenApiAutoConfiguration {

    }
  • @ConditionalOnProperty 注解声明了当 springfox.documentation.enabledtrue 时启用配置,而且默认值就是 true。这非常有用,Swagger 仅仅建议在开发阶段使用,这个正好是个开关。另外有时候自定义配置的时候最好把这个开关也加上 @ConditionalOnProperty(value = "springfox.documentation.enabled", havingValue = "true", matchIfMissing = true)

添加依赖

  • 引⼊ maven 依赖,在你项⽬的 pom ⽂件中,引⼊下⾯依赖:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <!--配置swagger3-->
    <dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-boot-starter</artifactId>
    <version>3.0.0</version>
    </dependency>

    <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    </dependency>
    <dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.11</version>
    </dependency>
  • springfox-boot-starter 依赖可以实现零配置以及自动配置支持。也就是说,如果没有其他特殊需求,加一个这个依赖就行了,接口文档就自动生成了

配置 Swagger

application.yml 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
spring:
application:
name: springfox-swagger
server:
port: 8080
#springfox:
# documentation:
# #swagger文档开关,线上环境关闭
# enabled: true
# ===== 自定义swagger配置 ===== #
swagger:
enable: true
application-name: ${spring.application.name}
application-version: 1.0
application-description: springfox swagger 3.0整合Demo
try-host: http://localhost:${server.port}

启用 swagger 配置

  • Swagger3 不需要使用@EnableOpenApi 或者@EnableSwagger2 开启, 下面的两个导入类都可以在 OpenApiAutoConfiguration 找到,所以 Swagger3 提供的是全自动的集成。

    1
    2
    3
    4
    5
    6
    7
    @Import(Swagger2DocumentationConfiguration.class)
    public @interface EnableSwagger2 {
    }

    @Import(OpenApiDocumentationConfiguration.class)
    public @interface EnableOpenApi {
    }
    1
    2
    3
    4
    5
    // @EnableOpenApi
    @Configuration
    public class SwaggerConfig {

    }

自定义 swagger 配置类

  • SwaggerProperties

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    @Component
    @ConfigurationProperties("swagger")
    @Data
    public class SwaggerProperties {
    /**
    * 是否开启 swagger,生产环境一般关闭,所以这里定义一个变量
    */
    private Boolean enable;

    /**
    * 项目应用名
    */
    private String applicationName;

    /**
    * 项目版本信息
    */
    private String applicationVersion;

    /**
    * 项目描述信息
    */
    private String applicationDescription;

    /**
    * 接口调试地址
    */
    private String tryHost;
    }

springfox 完整配置

  • 添加配置,添加 swagger 的配置类(⾮必需)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    package tk.fulsun.demo.config;

    import io.swagger.models.auth.In;
    import org.apache.commons.lang3.reflect.FieldUtils;
    import org.springframework.boot.SpringBootVersion;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.util.ReflectionUtils;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    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.*;
    import springfox.documentation.spi.DocumentationType;
    import springfox.documentation.spi.service.contexts.SecurityContext;
    import springfox.documentation.spring.web.plugins.Docket;

    import java.lang.reflect.Field;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.LinkedHashSet;
    import java.util.List;
    import java.util.Set;

    /**
    * @author fulsun
    * @description: swagger 的配置类
    * @date 6/8/2021 2: 29 PM
    */
    // @EnableOpenApi
    @Configuration
    @ConditionalOnProperty(value = "springfox.documentation.enabled", havingValue = "true", matchIfMissing = true)
    public class SwaggerConfig implements WebMvcConfigurer {
    private final SwaggerProperties swaggerProperties;

    public SwaggerConfig(SwaggerProperties swaggerProperties) {
    this.swaggerProperties = swaggerProperties;
    }

    @Bean
    public Docket createRestApi() {
    return new Docket(
    // 设置使用 OpenApi 3.0 规范
    DocumentationType.OAS_30).pathMapping("/")
    // 定义是否开启 swagger,false 为关闭,可以通过变量控制
    .enable(swaggerProperties.getEnable())
    // 配置项目基本信息
    .apiInfo(apiInfo())
    // 接口调试地址
    .host(swaggerProperties.getTryHost())
    // 设置项目组名
    .groupName("后端开发组")
    // 选择那些路径和 api 会生成 document
    .select()
    // 对所有 api 进行监控
    .apis(RequestHandlerSelectors.any())
    // 扫描的路径包, 用于指定路径接口扫描设置
    // .apis(RequestHandlerSelectors.basePackage("com.swagger.example.controller"))
    // 对所有路径进行监控
    .paths(PathSelectors.any())
    // 忽略以 "/error" 开头的路径, 可以防止显示如 404 错误接口
    .paths(PathSelectors.regex("/error.*").negate())
    // 忽略以 "/actuator" 开头的路径
    .paths(PathSelectors.regex("/actuator.*").negate())
    .build()
    // 支持的通讯协议集合
    .protocols(newHashSet("https", "http"))
    // 授权信息设置,必要的 header token 等认证信息
    .securitySchemes(securitySchemes())
    // 授权信息全局应用
    .securityContexts(securityContexts());
    }

    // 生成接口信息,包括标题、联系人等
    private ApiInfo apiInfo() {
    return new ApiInfoBuilder()
    // 文档标题
    .title(swaggerProperties.getApplicationName() + " Api Doc")
    // 文档描述
    .description(swaggerProperties.getApplicationDescription())
    // 文档版本
    .version("Application Version: " + swaggerProperties.getApplicationVersion() + ", Spring Boot Version: " + SpringBootVersion.getVersion())
    // 设置许可声明信息
    .license("Apache LICENSE 2.0")
    // 设置许可证 URL 地址
    .licenseUrl("https://XXX.com")
    // 设置管理该 API 人员的联系信息
    .contact(new Contact("lyw", "https://fulsun.tk", "fl_6145@163.com"))
    .build();
    }


    /**
    * 设置授权信息
    */
    private List<SecurityScheme> securitySchemes() {
    ApiKey apiKey = new ApiKey("BASE_TOKEN", "token", In.HEADER.toValue());
    return Collections.singletonList(apiKey);
    }

    /**
    * 授权信息全局应用
    */
    private List<SecurityContext> securityContexts() {
    return Collections.singletonList(
    SecurityContext.builder()
    .securityReferences(Collections.singletonList(new SecurityReference("BASE_TOKEN", new AuthorizationScope[]{new AuthorizationScope("global", "")})))
    .build()
    );
    }

    @SafeVarargs
    private final <T> Set<T> newHashSet(T... ts) {
    if (ts.length > 0) {
    return new LinkedHashSet<>(Arrays.asList(ts));
    }
    return null;
    }

    /**
    * 通用拦截器排除 swagger 设置,所有拦截器都会自动加 swagger 相关的资源排除信息
    */
    @SuppressWarnings("unchecked")
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    try {
    Field registrationsField = FieldUtils.getField(InterceptorRegistry.class, "registrations", true);
    List<InterceptorRegistration> registrations = (List<InterceptorRegistration>) ReflectionUtils.getField(registrationsField, registry);
    if (registrations != null) {
    for (InterceptorRegistration interceptorRegistration : registrations) {
    interceptorRegistration
    .excludePathPatterns("/swagger**/**")
    .excludePathPatterns("/webjars/**")
    .excludePathPatterns("/v3/**")
    .excludePathPatterns("/doc.html");
    }
    }
    } catch (Exception e) {
    e.printStackTrace();
    }
    }
    }

访问

  • 3.0 中的接口地址也和之前有所不同,以前在 2.9.2 中主要访问两个地址:

  • 在 3.0 中,这两个地址也发生了变化:

  • 访问 http://localhost: 8080/swagger-ui/index.html

关闭文档

  • swagger 不只提供了 api 在线文档,同时还支持在线测试接口,一般在测试环境完成交互,线上环境需要关闭文档访问

  • 自动配置类如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    @Configuration
    @EnableConfigurationProperties(SpringfoxConfigurationProperties.class)
    @ConditionalOnProperty(value = "springfox.documentation.enabled", havingValue = "true", matchIfMissing = true)
    @Import({
    OpenApiDocumentationConfiguration.class,
    SpringDataRestConfiguration.class,
    BeanValidatorPluginsConfiguration.class,
    Swagger2DocumentationConfiguration.class,
    SwaggerUiWebFluxConfiguration.class,
    SwaggerUiWebMvcConfiguration.class
    })
    @AutoConfigureAfter({ WebMvcAutoConfiguration.class, JacksonAutoConfiguration.class,
    HttpMessageConvertersAutoConfiguration.class, RepositoryRestMvcAutoConfiguration.class })
    public class OpenApiAutoConfiguration {

    }
  • swagger3.0 依赖包提供了默认参数 springfox.documentation.enabled,线上环境对应的参数设置为 false 即可:

    1
    2
    #swagger文档开关,线上环境关闭
    springfox.documentation.enabled=false

Swagger注解

常用注解

1
2
3
4
@Api: 对整个 Controller 接口信息的描述。
@ApiOperation: 对某个接口信息进行描述。
@ApiImplicitParam: 对请求参数进行描述。
@ApiImplicitParams: 用于包含多个 @ApiImplicitParam 注解,对请求中的多个参数进行描述。

注解使用说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
@Api:用在请求的类上,表示对类的说明
tags = "说明该类的作用,可以在 UI 界面上看到的注解"
value = "该参数没什么意义,在 UI 界面上也看到,所以不需要配置"

@ApiOperation:用在请求的方法上,说明方法的用途、作用
value = "说明方法的用途、作用"
notes = "方法的备注说明"

@ApiImplicitParams:用在请求的方法上,表示一组参数说明
@ApiImplicitParam:用在@ApiImplicitParams 注解中,指定一个请求参数的各个方面
name:参数名
value:参数的汉字说明、解释
required:参数是否必须传
paramType:参数放在哪个地方
· header --> 请求参数的获取:@RequestHeader
· query --> 请求参数的获取:@RequestParam
· path(用于 restful 接口)--> 请求参数的获取:@PathVariable
· div(不常用)
· form(不常用)
dataType:参数类型,默认 String,其它值 dataType = "Integer"
defaultValue:参数的默认值

@ApiResponses:用在请求的方法上,表示一组响应
@ApiResponse:用在@ApiResponses 中,一般用于表达一个错误的响应信息
code:数字,例如 400
message:信息,例如 "请求参数没填好"
response:抛出异常的类

@ApiModel:用于响应类上,表示一个返回响应数据的信息
(这种一般用在 post 创建的时候,使用@RequestBody 这样的场景,
请求参数无法使用@ApiImplicitParam 注解进行描述的时候)
value–表示对象名
description–描述

@ApiModelProperty:用在属性上,描述响应类的属性
value–字段说明
   name–重写属性名字
   dataType–重写属性类型
   required–是否必填
   example–举例说明
   hidden–隐藏

@ApiImplicitParam() 用于 controller 方法
表示单独的请求参数
   name–参数 ming
   value–参数说明
   dataType–数据类型
   paramType–参数类型
   example–举例说明

@ApiImplicitParams() 用于 controller 方法
包含多个 @ApiImplicitParam

@ApiIgnore()用于类或者方法上
可以不被 swagger 显示在页面上

3.0 注解

  • 旧的注解还可以继续使用,不过在 3.0 中还提供了一些其他注解。

  • 例如可以使用 @EnableOpenApi 代替以前旧版本中的 @EnableSwagger2

  • 不过在实际体验中,感觉 @EnableOpenApi 注解的功能不明显,加不加都行。

  • 翻了下源码,@EnableOpenApi 注解主要功能是为了导入 OpenApiDocumentationConfiguration 配置类,如下:

    1
    2
    3
    4
    5
    6
    @Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME)
    @Target(value = {java.lang.annotation.ElementType.TYPE})
    @Documented
    @Import(OpenApiDocumentationConfiguration.class)
    public @interface EnableOpenApi {
    }
  • 然后又看了下自动化配置类 OpenApiAutoConfiguration,如下:

    • 以看到,自动化配置类里边也导入了 OpenApiDocumentationConfiguration。所以在正常情况下,实际上不需要添加 @EnableOpenApi 注解。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      @Configuration
      @EnableConfigurationProperties(SpringfoxConfigurationProperties.class)
      @ConditionalOnProperty(value = "springfox.documentation.enabled", havingValue = "true", matchIfMissing = true)
      @Import({
      OpenApiDocumentationConfiguration.class,
      SpringDataRestConfiguration.class,
      BeanValidatorPluginsConfiguration.class,
      Swagger2DocumentationConfiguration.class,
      SwaggerUiWebFluxConfiguration.class,
      SwaggerUiWebMvcConfiguration.class
      })
      @AutoConfigureAfter({ WebMvcAutoConfiguration.class, JacksonAutoConfiguration.class,
      HttpMessageConvertersAutoConfiguration.class, RepositoryRestMvcAutoConfiguration.class })
      public class OpenApiAutoConfiguration {

      }
  • 根据 OpenApiAutoConfiguration 上的 @ConditionalOnProperty 条件注解中的定义,可以发现,如果在 application.properties 中设置 springfox.documentation.enabled=false,即关闭了 swagger 功能,此时自动化配置类就不执行了

  • 这个时候可以通过 @EnableOpenApi 注解导入 OpenApiDocumentationConfiguration 配置类。技术上来说逻辑是这样,不过应用中暂未发现这样的需求(即在 application.properties 中关闭 swagger,再通过 @EnableOpenApi 注解开启)。

  • 以前用的 @ApiResponses/@ApiResponse 注解,在 3.0 中名字没变,但是所在的包变了,使用时注意导包问题。

  • 之前用的 @ApiOperation 注解在 3.0 中可以使用 @Operation 代替。

接口示例

  • 接口如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    @Api(tags = "测试接口")
    @RestController
    @RequestMapping("/api")
    public class TestController {

    @ApiOperation(value = "测试接口标题", notes = "测试接口描述")
    @ApiImplicitParams({
    @ApiImplicitParam(name = "param1", value = "参数 1", required = true),
    @ApiImplicitParam(name = "param2", value = "参数 2", required = false)
    })
    @ApiResponses({
    @ApiResponse(code = 400, message = "请求参数没填好"),
    @ApiResponse(code = 404, message = "请求路径没有或页面跳转路径不对")
    })
    @GetMapping("/test")
    public String test() {
    return "ok";
    }
    }
  • 效果

接口的分组

  • 我们在Spring Boot中定义各个接口是以Controller作为第一级维度来进行组织的,Controller与具体接口之间的关系是一对多的关系。
  • 我们可以将同属一个模块的接口定义在一个Controller里。默认情况下,Swagger是以Controller为单位,对接口进行分组管理的。
  • 这个分组的元素在Swagger中称为Tag,但是这里的Tag与接口的关系并不是一对多的,它支持更丰富的多对多关系。

默认分组

  • 首先,我们通过一个简单的例子,来看一下默认情况,Swagger是如何根据Controller来组织Tag与接口关系的。定义两个Controller,分别负责教师管理与学生管理接口,比如下面这样:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    @RestController
    @RequestMapping(value = "/teacher")
    public class TeacherController {

    @GetMapping("/xxx")
    public String xxx() {
    return "xxx";
    }
    }


    @RestController
    @RequestMapping(value = "/student")
    public class StudentController {

    @ApiOperation("获取学生清单")
    @GetMapping("/list")
    public String bbb() {
    return "bbb";
    }

    @ApiOperation("获取教某个学生的老师清单")
    @GetMapping("/his-teachers")
    public String ccc() {
    return "ccc";
    }

    @ApiOperation("创建一个学生")
    @PostMapping("/aaa")
    public String aaa() {
    return "aaa";
    }
    }
  • 启动应用之后,Swagger默认生成的Tag(黑色加粗)与Spring Boot中Controller展示的内容如下:

自定义默认分组的名称

  • 接着,我们可以再试一下,通过@Api注解来自定义Tag,比如这样:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    @Api(tags = "教师管理")
    @RestController
    @RequestMapping(value = "/teacher")
    static class TeacherController {

    // ...

    }

    @Api(tags = "学生管理")
    @RestController
    @RequestMapping(value = "/student")
    static class StudentController {

    // ...

    }
  • 再次启动应用之后,代码中@Api定义的tags内容替代了默认产生的teacher-controllerstudent-controller

合并Controller分组

  • 到这里,都只是使用了TagController一一对应的情况,Swagger中还支持更灵活的分组!

  • @Api注解的属性中,相信聪明的读者一定已经发现tags属性其实是个数组类型:

  • 我们可以通过定义同名的Tag来汇总Controller中的接口,比如我们可以定义一个Tag为“教学管理”,让这个分组同时包含教师管理和学生管理的所有接口

  • 可以这样来实现:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    @Api(tags = {"教师管理", "教学管理"})
    @RestController
    @RequestMapping(value = "/teacher")
    static class TeacherController {

    // ...

    }

    @Api(tags = {"学生管理", "教学管理"})
    @RestController
    @RequestMapping(value = "/student")
    static class StudentController {

    // ...

    }
  • 最终效果如下:

更细粒度的接口分组

  • 通过@Api可以实现将Controller中的接口合并到一个Tag中,但是如果我们希望精确到某个接口的合并呢?

  • 比如这样的需求:“教学管理”包含“教师管理”中所有接口以及“学生管理”管理中的“获取学生清单”接口(不是全部接口)。

  • 那么上面的实现方式就无法满足了。这时候发,我们可以通过使用@ApiOperation注解中的tags属性做更细粒度的接口分类定义,比如上面的需求就可以这样子写:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    @Api(tags = {"教师管理", "教学管理"})
    @RestController
    @RequestMapping(value = "/teacher")
    static class TeacherController {

    @ApiOperation(value = "xxx")
    @GetMapping("/xxx")
    public String xxx() {
    return "xxx";
    }

    }

    @Api(tags = {"学生管理"})
    @RestController
    @RequestMapping(value = "/student")
    static class StudentController {

    @ApiOperation(value = "获取学生清单", tags = "教学管理")
    @GetMapping("/list")
    public String bbb() {
    return "bbb";
    }

    @ApiOperation("获取教某个学生的老师清单")
    @GetMapping("/his-teachers")
    public String ccc() {
    return "ccc";
    }

    @ApiOperation("创建一个学生")
    @PostMapping("/aaa")
    public String aaa() {
    return "aaa";
    }

    }
  • 效果如下:

内容的顺序

  • 在完成了接口分组之后,对于接口内容的展现顺序又是众多用户特别关注的点,其中主要涉及三个方面:分组的排序、接口的排序以及参数的排序,下面我们就来逐个说说如何配置与使用。

分组的排序

  • 为Tag的命名做编号。比如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    @Api(tags = {"2-教师管理", "1-教学管理"})
    @RestController
    @RequestMapping(value = "/teacher")
    static class TeacherController {

    // ...

    }

    @Api(tags = {"3-学生管理"})
    @RestController
    @RequestMapping(value = "/student")
    static class StudentController {

    @ApiOperation(value = "获取学生清单", tags = "1-教学管理")
    @GetMapping("/list")
    public String bbb() {
    return "bbb";
    }

    // ...

    }
  • 显示效果

接口的排序

  • swagger2默认采用二种方式
    • 按照方法定义
    • 按照字母顺序
  • 2.7(不包括)之后的版本需要做另外的处理
    • 由于默认的前端UI包springfox-swagger-ui移除了排序功能,所以即使后端接口数据排过序了,前端照样会乱。

使用第三方提供的前端UI包

  • 添加依赖

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <properties>
    <maven.compiler.source> 8 </maven.compiler.source>
    <maven.compiler.target> 8 </maven.compiler.target>
    <!-- knife4j: swagger ui -->
    <knife4j.version> 2.0.8 </knife4j.version>
    </properties>
    <dependency>
    <groupId> com.github.xiaoymin </groupId>
    <artifactId> knife4j-spring-ui </artifactId>
    <version>${knife4j.version}</version >
    </dependency>
  • 访问 http://localhost:8080/doc.html