美文网首页
Spring Boot - 自动生成接口文档

Spring Boot - 自动生成接口文档

作者: Whyn | 来源:发表于2021-09-25 01:36 被阅读0次

    前言

    在目前主流的前后端分离项目中,桥接前后端的就是接口,因此,一份简洁易懂的接口文档就显得非常重要了。幸运的是,我们不必手动去编写这些接口文档,市面上已有许多成熟的第三方库可以自动为项目生成接口文档,在 Spring Boot 中,最常使用的接口文档自动生成库就是 Swagger。

    本篇博文主要介绍在 Spring Boot 中集成 Swagger 3 的方法。

    几个概念释义

    • OpenAPIOpenAPI规范(以前也被称为Swagger规范)制定了一份标准的对 REST API 接口的描述格式,具体的描述信息包含如下几方面:

      1. 可用终端接口(/user)及其各接口对应的操作(GET /user, POST /user
      2. 每个操作的输入、输出参数描述
      3. 认证方法
      4. 联系方式,许可证,使用条款等其他信息

      API规范 可以使用YAMLJSON格式进行描述,对于人和机器来说都是阅读友好的。

    • SwaggerSwagger是围绕OpenAPI规范构建的一系列开源工具,可以帮助我们设计、构建、记录和使用 REST API。主要的工具包含如下:

      1. Swagger Editor:可以在浏览器上编辑OpenAPI规范。
      2. Swagger UI:将OpenAPI规范渲染成可交互 API 接口文档。
      3. Swagger Codegen:依据OpenAPI规范文件生成服务器存根和客户端库。

    更多详细信息,请参考官网:Specification

    简单来说,OpenAPI就是定义描述 REST API 的规范,而Swagger就是对OpenAPI规范的实现。

    基本使用

    在 Spring Boot 中集成 Swagger 3,步骤如下:

    1. pom.xml中导入依赖

      <dependency>
          <groupId>io.springfox</groupId>
          <artifactId>springfox-boot-starter</artifactId>
          <version>3.0.0</version>
      </dependency>
      
    2. 依赖导入完成后,直接在浏览器输入以下网址:

      http://localhost:8080/swagger-ui/
      

      此时就可以直接看到项目接口文档了。

    3. (可选)Swagger 3 提供了一些注解,可以让我们自定义接口描述信息。相关的注解如下表所示:

      :Swagger 3 提供的注解与 Swagger2 名称不同,下表列举了其对应关系:

      Swagger 2 Swagger 3 (OpenAPI 3) 注解位置
      @Api @Tag(name = "接口类描述") Controller类上
      @ApiOperation @Operation(summary = "接口方法描述") Controller方法上
      @ApiImplicitParams @Parameters Controller方法上
      @ApiImplicitParam @Parameter(description=“参数描述”) @Paramseters内部
      @ApiParam @Parameter(description=“参数描述”) Controller方法参数上
      @ApiIgnore @Parameter(hidden = true)@Operation(hidden = true)@Hidden -
      @ApiModel @Schema DTO 类上
      @ApiModelProperty @Schema DTO 属性上

      一个简单的示例如下所示:

      @RestController
      @RequestMapping("/user")
      @Tag(name = "用户接口")
      public class UserApi {
      
          @PostMapping
          @Operation(summary = "添加用户")
          public String addUser(@RequestBody User user) {
              //...
          }
      
          @GetMapping("/all")
          @Operation(description = "获取所有用户")
          public List<User> getAllUsers() {
              //...
          }
      }
      

    可以看到,Swagger 3 的使用还是非常简单的。

    自定义配置

    如果需要更细致的自定义配置,我们可以自定义一个配置类,然后注入一个Docket数据实例,自定义配置 Swagger。

    以下列举几种常见的配置示例:

    1. 配置文档相关信息:

      @Configuration
      @ConditionalOnProperty(value = "springfox.documentation.enabled", havingValue = "true", matchIfMissing = true)
      public class SwaggerConfig {
          @Bean
          public Docket docket(){
              return new Docket(DocumentationType.OAS_30)
                      // 配置接口相关信息
                      .apiInfo(apiInfo())
                      // 选择哪些接口作为 swagger 的 doc 发布
                      .select()
                      .build();
          }
      
          private ApiInfo apiInfo(){
              return new ApiInfoBuilder()
                      .title("XX项目接口文档")
                      .description("XX项目描述")
                      .contact(new Contact("作者", "作者URL", "作者Email"))
                      .version("1.0")
                      .build();
          }
      }
      
    2. 配置包扫描路径:

      @Bean
      public Docket docket(){
          return new Docket(DocumentationType.OAS_30)
                  .apiInfo(apiInfo())
                  .select()
                  //apis: 添加swagger接口提取范围
                  // 指定扫描包
                  .apis(RequestHandlerSelectors.basePackage("com.yn.controller"))
                  // 指定扫描方法注解
                  // .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                  // 所有路径
                  .paths(PathSelectors.any())
                  .build();
      }
      
    3. Api 分组:默认情况下,Swagger 将扫描到的接口都归属于default组,我们可以通过对每个接口路径(/public/admin)各自配置一个Docket,显式设置其分组:

      @Bean
      public Docket publicApi() {
          return new Docket(DocumentationType.OAS_30)
                  .groupName("api-public")
                  .select()
                  .apis(RequestHandlerSelectors.basePackage("com.yn.controller.open"))
                  // localhost:8080/public
                  .paths(PathSelectors.regex("/public.*"))
                  .build();
      }
      
      @Bean
      public Docket privateApi() {
          return new Docket(DocumentationType.OAS_30)
                  .groupName("api-admin")
                  .select()
                  .apis(RequestHandlerSelectors.basePackage("com.yn.controller.admin"))
                  .paths(PathSelectors.regex("/admin.*"))
                  .build();
      }
      
    4. 请求头添加 token:越来越多的项目采用前后端分离架构,此时经常使用 token 来作为鉴权机制,因此前端每次请求都必须携带上 token,我们可以配置下 Swagger,让其每次请求自动携带我们设置的 token,只需对相应Docket进行配置即可,如下所示:

      @Bean
      public Docket addJwtToken() {
          return new Docket(DocumentationType.OAS_30)
                  .apiInfo(apiInfo())
                  .securitySchemes(Collections.singletonList(HttpAuthenticationScheme.JWT_BEARER_BUILDER
                           // 显示用
                          .name("JWT")
                          .build()))
                  .securityContexts(Collections.singletonList(SecurityContext.builder()
                          .securityReferences(Collections.singletonList(SecurityReference.builder()
                                  .scopes(new AuthorizationScope[0])
                                  .reference("JWT")
                                  .build()))
                          // 声明作用域
                          .operationSelector(o -> o.requestMappingPattern().matches("/.*"))
                          .build()))
                  .select()
                  .apis(RequestHandlerSelectors.any())
                  .paths(PathSelectors.any())
                  .build();
      }
      

      配置完成后,打开该Docker配置对应的页面,就可以看到Authorize的按钮,如下图所示:

      Authorize

      点击该按钮,手动输入 token,最后点击Authorize按钮确认即可,如下图所示:

      Enter Token

    Swagger 更多配置选项,请参考官方文档:springfox

    其他注意事项

    Swagger 在使用过程中,有一些事项可以注意一下,避免出现问题。比如:

    • 区分环境:通常情况下,Swagger 只在开发环境或测试环境下开启,在生产环境下必须进行关闭。可以通过在配置文件application.properties中配置使能或失能 Swagger:

      # 生产环境失能 Swagger
      springfox.documentation.enabled=false
      # 或者
      springfox.documentation.swagger-ui.enabled=false
      

      :在springfox-boot-starter.jar包中,我们可以找到/META-INF/spring.factories配置文件,其内容如下:

      # Auto Configure
      org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
      springfox.boot.starter.autoconfigure.OpenApiAutoConfiguration
      

      可以看到,Swagger 的自动配置文件类为OpenApiAutoConfiguration,其源码如下所示:

      @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 {
          public OpenApiAutoConfiguration() {
          }
      }
      

      这里我们主要关注@ConditionalOnProperty,可以看到,当springfox.documentation.enabled设置为true(缺省默认也为true)时,才会加载OpenApiAutoConfiguration自动配置类。因此,这里也是为什么我们前面自定义配置类SwaggerConfig也带上这个配置,这样可以确保在springfox.documentation.enabled=false时,我们的自定义配置类SwaggerConfig也不会被加载。

      :Spring Boot 多环境配置方法可参考文章:Spring Boot - 多环境配置

    • 安全框架放行:如果项目中使用了 Spring Security 这种权限认证框架,应当注意要把 Swagger 添加到白名单中:

      @Configuration
      public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
      
          @Override
          public void configure(WebSecurity web) throws Exception {
              String[] SWAGGER_WHITELIST = {
                      "/swagger-ui.html",
                      "/swagger-ui/*",
                      "/swagger-resources/**",
                      "/v2/api-docs",
                      "/v3/api-docs",
                      "/webjars/**"
              };
              web.ignoring().antMatchers(SWAGGER_WHITELIST);
          }
      }
      
    • 统一数据下发异常:如果项目中使用了@RestControllerAdvice拦截所有接口请求,那么 Swagger 的内置接口也同样会被拦截修改,导致Unable to infer base url错误,此时,只需为@RestControllerAdvice设置拦截指定包目录即可,如下所示:

      // 只拦截 com.yn.controller 包
      @RestControllerAdvice(basePackages = {"com.yn.controller"})
      public class FormatResponseBodyAdvice implements ResponseBodyAdvice<Object> {...}
      
    • @EnableWebMvc异常:当项目中使用了@EnableWebMvc注解后,会导致 Swagger 无法访问。原因是在 Spring Boot 中,注解在配置类(即@Configuration)类上的@EnableWebMvc会完全掌控 SpringMVC 配置,导致 Spring Boot 对 SpringMVC 的自动配置失效(即不加载自动配置),从而间接影响到了 Swagger。解决该问题的方法有很多,这里列举几种:

      1. 移除@EnableWebMvc:对于 Spring Boot 项目,通常不建议在配置类(@Configuration)上直接使用@EnableWebMvc,很多对 SpringMVC 的配置,可以直接搜索 Spring Boot 对应的配置选项即可,大多数情况下无需直接配置原生 SpringMVC。
      2. 添加视图解析器ViewResolver:使用@EnableWebMvc后,SpringMVC 中,内置的视图解析器无法对 Swagger 的视图进行解析,因此手动为DispatcherServlet添加 Spring 内置的视图解析器即可:
      @Configuration
      @EnableWebMvc
      public class WebConfiguration implements WebMvcConfigurer {
      
          @Override
          public void configureViewResolvers(ViewResolverRegistry registry) {
              registry.viewResolver(new InternalResourceViewResolver());
          }
      }
      

      :可单步调式DispatcherServlet,在DispatcherServlet#resolveViewName方法内就是对视图进行解析的过程,此处可查看到DispatcherServlet具体所使用到的ViewResolver

    参考

    相关文章

      网友评论

          本文标题:Spring Boot - 自动生成接口文档

          本文链接:https://www.haomeiwen.com/subject/zhitnltx.html