SpringBoot(八):整合Swagger

郎家岭伯爵 2023年07月18日 291次浏览

前言

SpringBoot 整合 Swagger

实现

理论

Swagger 的作用?

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

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

什么是 Swagger-UI

Swagger-UI 是一套 HTML/CSS/JS 框架,用于渲染 Swagger 文档,以便提供美观的 API 文档界面。

也就是说,Swagger-UI 是 Swagger 提供的一套可视化渲染组件,支持在线导入描述文件和本地部署 UI 项目。

SpringBoot

创建一个 SpringBoot 项目。

pom.xml

pom.xml 中导入以下依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</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-starterspringfox 针对 SpringBoot 项目提供的一个 starter,简化 Swagger 依赖的导入,否则我们就需要在 pom.xml 文件中添加 springfox-swaggerspringfox-swagger-ui 等多个依赖。

application.properties

application.properties 配置文件中添加如下配置项:

spring.mvc.pathmatch.matching-strategy=ant_path_matcher

Swagger配置类

创建如下 SwaggerConfig.java 配置类:

package com.langjialing.swaggerdemo.config;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
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;
import springfox.documentation.spring.web.plugins.WebFluxRequestHandlerProvider;
import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider;

import java.lang.reflect.Field;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 郎家岭伯爵
 * @time 2023/7/18 9:37
 */
@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("com.langjialing.swaggerdemo.controller"))
                .paths(PathSelectors.any())
                .build();

        return docket;
    }

    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                .title("郎家岭伯爵的Swagger文档")
                .description("郎家岭伯爵的Swagger Demo项目文档")
                .contact(new Contact("郎家岭伯爵", "https://langjialing.com","1830879596@qq.com"))
                .version("v1.0")
                .build();
    }

    @Bean
    public static BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {
        return new BeanPostProcessor() {

            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {
                    customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
                }
                return bean;
            }

            private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {
                List<T> copy = mappings.stream()
                        .filter(mapping -> mapping.getPatternParser() == null)
                        .collect(Collectors.toList());
                mappings.clear();
                mappings.addAll(copy);
            }

            @SuppressWarnings("unchecked")
            private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {
                try {
                    Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
                    field.setAccessible(true);
                    return (List<RequestMappingInfoHandlerMapping>) field.get(bean);
                } catch (IllegalArgumentException | IllegalAccessException e) {
                    throw new IllegalStateException(e);
                }
            }
        };
    }

}
  • @Configuration 注解通常用来声明一个 Java 配置类,取代了以往的 xml 配置文件,让配置变得更加的简单和直接。

  • @EnableOpenApi 注解表明开启 Swagger。

  • SwaggerConfig 类中包含了一个 @Bean 注解声明的方法 docket(),该方法会被 Spring 的 AnnotationConfigApplicationContextAnnotationConfigWebApplicationContext 类进行扫描,然后添加到 Spring 容器当中。

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
  ctx.register(AppConfig.class);
  ctx.refresh();
  MyBean myBean = ctx.getBean(MyBean.class);

简单描述一下 Swagger 的配置内容:

  • new Docket(DocumentationType.OAS_30),使用 3.0 版本的 Swagger API。OAS 是 OpenAPI Specification 的简称,翻译成中文就是 OpenAPI 说明书,Swagger 遵循的就是这套规范。
  • apiInfo(apiInfo()),配置 API 文档基本信息,标题、描述、作者、版本等。
  • apis(RequestHandlerSelectors.basePackage("top.codingmore.controller")) 指定 API 的接口范围为 controller 控制器。
  • paths(PathSelectors.any()) 指定匹配所有的 URL。

controller层接口

创建如下 controller 接口,测试 Swagger 文档:

package com.langjialing.swaggerdemo.controller;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author 郎家岭伯爵
 * @time 2023/7/18 10:01
 */
@Api(tags = "测试 Swagger")
@RestController
@RequestMapping("/swagger")
public class SwaggerController {

    @ApiOperation("测试")
    @RequestMapping("/test")
    public String test() {
        return "testSwagger";
    }
}
  1. @Api 注解,用在类上,该注解将控制器标注为一个 Swagger 资源。该注解有 3 个属性:

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

    • value 操作的简单说明,长度为120个字母,60个汉字。
    • notes 对操作的详细说明。
    • httpMethod HTTP请求的动作名,可选值有:“GET”, “HEAD”, “POST”, “PUT”, “DELETE”, “OPTIONS” 和 “PATCH”。
    • code 默认为200,有效值必须符合标准的 HTTP Status Code Definitions
  3. @RestController 注解,用在类上,是 @ResponseBody@Controller 的组合注解。如果方法要返回 JSON 的话,可省去 @ResponseBody 注解。

  4. @RequestMapping 注解,可用在类(父路径)和方法(子路径)上,主要用来定义 API 的请求路径和请求类型。该注解有 6 个属性:

    • value,指定请求的实际地址
    • method,指定请求的 method 类型, GET、POST、PUT、DELETE等
    • consumes,指定处理请求的提交内容类型(Content-Type),例如 application/json, text/html
    • produces,指定返回的内容类型,仅当 request 请求头中的(Accept)类型中包含该指定类型才返回
    • params,指定 request 中必须包含某些参数值
    • headers,指定request中必须包含某些指定的 header 值

访问Swagger文档

启动项目后,在浏览器中输入如下地址可访问 Swagger 文档:

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

Swagger文档

调试接口

总结

SpringBoot 整合 Swagger。但 Swagger-UI 的界面实在是有点不太优雅,下一篇我们将介绍更好用的 Knife4j

捐赠页面示例