Loading

在 SpringBoot 中集成 OpenAPI 文档

概述

OpenAPI 是一个规范(Specification),它定义了一种描述 API 的标准化格式,使得这些 API 更容易被人类阅读和机器解析,便于生成文档、测试、客户端代码等。这个规范以前被称为 Swagger 规范,但后来被捐赠给了 Linux 基金会。Swagger 还一系列遵循这些规则的工具和 UI。

在 SpringBoot 中用于生成 OpenAPI 文档的工具有: springfox、springdoc 和 knife4j 等

准备

<!-- SpringFox 已经停更了 -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-boot-starter</artifactId>
    <version>3.0.0</version>
</dependency>
<!--  SpringDoc 更好的提供了对 OpenAPI3 的支持 -->
<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-ui</artifactId>
    <version>1.5.13</version>
</dependency>
@EnableOpenApi

常用注解

注解 方法 属性
@Api(tags) 标注一个类为 Swagger 资源, 设置资源名称, 默认是类名
@ApiOperation(value) 标注一个请求, 设置该请求的名称, 默认是方法名
@ApiParam (不常用) 仅用于 JAX-RS
@ApiImplicitParam (常用) 功能同 @ApiParame, 可用于 Servlet
@ApiImplicitParams 包裹多个参数描述注解
@ApiModel 标注一个实体类
@ApiModelProperty 标注实体属性, 设置属性的备注信息
@ApiResponse 描述响应码,以及备注信息
@ApiResponses 包裹多个响应描述注解
@ApiIgnore 使swagger忽略某个资源 使swagger忽略某个接口 使swagger忽略某个属性

摘自 springdoc 官网的注解对比:

Swagger注解

SpringFox

配置文档信息

// SpringFox 需要注入一个 Docket 对象配置文档信息, springfox.documentation.spring.web.plugins.Docket 中默认配置了部分属性
// springfox.documentation.spi.service.contexts.Defaults 中配置了一些基本内容
@Configuration
public class SwaggerConfig {

    @Bean
    public Docket docket() {
        return new Docket(DocumentationType.OAS_30)
                .groupName("LearnSwagger")
                .apiInfo(apiInfo())
                .enable(true);
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("测试文档标题")
                .contact(new Contact("xtyuns", "https://github.com/xtyuns", null))
                .description("测试文档描述信息")
                .version("v1.0.0")
                .build();
    }
}

详见 Docket 和 ApiInfo 的源码

文档资源过滤

@Bean
public Docket docket() {
    return new Docket(DocumentationType.OAS_30)
        .groupName("LearnSwagger")
        .select()
        .paths(s -> s.startsWith("/v1"))
        .build();
}

通过 paths 选取时可以使用 PathSelectors, 其中提供了 any()、none()、ant(antPattern)、regex(pathRegex) 方法。

@Bean
public Docket docket() {
    return new Docket(DocumentationType.OAS_30)
        .groupName("LearnSwagger")
        .select()
        .apis(RequestHandlerSelectors.basePackage("com.xtyuns"))
        .apis(requestHandler -> "index-controller".equals(requestHandler.groupName()))
        .build();
}

// 等同于 (使用 and 连结多个选取方法)

@Bean
public Docket docket() {
    return new Docket(DocumentationType.OAS_30)
        .groupName("LearnSwagger")
        .select()
        .apis(
        	RequestHandlerSelectors.basePackage("com.xtyuns")
        	.and(
                requestHandler -> "index-controller".equals(requestHandler.groupName())
            )
    	).build();
}

// 默认的 Selector
public static final ApiSelector DEFAULT
      = new ApiSelector(
          (withClassAnnotation(ApiIgnore.class).negate()).and(
          (withMethodAnnotation(ApiIgnore.class).negate())), PathSelectors.any());

RequestHandlerSelectors 中也提供了 any()、none()、withClassAnnotation(cls)、withMethodAnnotation(cls) 方法。

requestHandler.groupName() 是类名称的中划线表示法,RequestHandler 类中还有一些其他信息可用于进行断言。

文档分组

可以配置多个 Docket Bean, 必须使用 GroupName 进行区分。

配置示例

image

SpringDoc

springdoc 大多数配置都与 springfox 类似,如 Docket 变为了 OpenApi 或 GroupedOpenApi

授权

io.swagger.v3.oas.annotations.security.SecurityScheme

@RestController
@Tag(name = "springdoc & security")
@SecuritySchemes({
        @SecurityScheme(
                name = "byBearer",
                type = SecuritySchemeType.HTTP,
                scheme = "bearer"
        ),
        @SecurityScheme(
                name = "byApiKey",
                type = SecuritySchemeType.APIKEY,
                in = SecuritySchemeIn.HEADER,
                paramName = "customerKey"
        ),
        @SecurityScheme(
                name = "byOAuth2Password",
                type = SecuritySchemeType.OAUTH2,
                flows = @OAuthFlows(
                        authorizationCode = @OAuthFlow(
                                authorizationUrl = "http://example.com/oauth2/authorize",
                                tokenUrl = "http://example.com/oauth2/token"
                        ),
                        password = @OAuthFlow(
                                tokenUrl = "http://example.com/oauth2/token"
                        )
                )

        )
})
public class IndexController {

    @Operation(
            summary = "这是默认请求地址",
            security = {
                    @SecurityRequirement(name = "byBearer")
            },
            responses = {
                @ApiResponse(responseCode = "200", description = "请求成功, 响应: ok"),
                @ApiResponse(responseCode = "500", description = "服务器内部出错了")
            }
    )
    @GetMapping("")
    public ResponseEntity<String> index() {
        return ResponseEntity.ok("ok");
    }
}

通过 OpenApi 定义 SecurityScheme: https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md#securitySchemeObject

相关阅读

swaggere2 和 swagger3: https://blog.csdn.net/qq_35425070/article/details/105347336

springfox 到 springdoc 迁移指南: https://github.com/springfox/springfox/pull/3935

注解总览: https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Annotations#quick-annotation-overview

spring gateway 统一配置 swagger: https://piotrminkowski.com/2020/02/20/microservices-api-documentation-with-springdoc-openapi/

自定义异常处理响应: https://blog.lanweihong.com/posts/1527/

posted @ 2021-12-09 22:11  xtyuns  阅读(731)  评论(0编辑  收藏  举报