当前位置:   article > 正文

Swagger 整合 springboot 2.6.8 + swagger3 springboot 2.x + swagger2

Swagger 整合 springboot 2.6.8 + swagger3 springboot 2.x + swagger2

拓展阅读

Devops-01-devops 是什么?

Devops-02-Jpom 简而轻的低侵入式在线构建、自动部署、日常运维、项目监控软件

代码质量管理 SonarQube-01-入门介绍

项目管理平台-01-jira 入门介绍 缺陷跟踪管理系统,为针对缺陷管理、任务追踪和项目管理的商业性应用软件

项目管理平台-01-Phabricator 入门介绍 一套集成的强大工具,帮助公司构建更高质量的软件

持续集成平台 01 jenkins 入门介绍

Swagger 整合 springmvc

Swagger 整合 springboot 2.6.8 + swagger3 springboot 2.x + swagger2

Swagger 文档工具 设计、构建、文档化和使用您的 RESTful API

springboot 2.x + swagger2

maven

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

编写配置类

@Configuration
@EnableSwagger2 // 开启Swagger2自动配置
public class Swagger2Config {

    @Bean
    public Docket UserApiConfig(){
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("UserApi") // 分组
                .apiInfo(UserApiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("cn.ken.login.controller"))
                .paths(PathSelectors.ant("/user/**"))
                .build();
    }

    @Bean
    public Docket BlogApiConfig(){
        return new Docket(DocumentationType.SWAGGER_2)
                .groupName("BlogApi") // 分组
                .apiInfo(BlogApiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("cn.ken.login.controller"))
                .paths(PathSelectors.ant("/blog/**"))
                .build();
    }

    // 配置用户文档信息
    private ApiInfo UserApiInfo(){
        return new ApiInfoBuilder()
                .title("我的API文档") // 标题
                .description("本文档描述了用户相关的接口定义") // 描述
                .version("1.0") // 版本
                .contact(new Contact("联系人名字", "联系人访问链接", "联系人邮箱")) // 联系人信息
                .build();
    }

    // 配置博客文档信息
    private ApiInfo BlogApiInfo(){
        return new ApiInfoBuilder()
                .title("我的API文档") // 标题
                .description("本文档描述了博客相关的接口定义") // 描述
                .version("1.0") // 版本
                .contact(new Contact("联系人名字", "联系人访问链接", "联系人邮箱")) // 联系人信息
                .build();
    }

}
  • 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

访问

使用注解对接口进行描述(也可以省略)

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

启动报错

1. NPE

Caused by: java.lang.NullPointerException: null
    at springfox.documentation.spi.service.contexts.Orderings$8.compare(Orderings.java:112) ~[springfox-spi-2.9.2.jar:null]
    at springfox.documentation.spi.service.contexts.Orderings$8.compare(Orderings.java:109) ~[springfox-spi-2.9.2.jar:null]
    at com.google.common.collect.ComparatorOrdering.compare(ComparatorOrdering.java:37) ~[guava-20.0.jar:na]
    at java.util.TimSort.countRunAndMakeAscending(TimSort.java:351) ~[na:1.8.0_05]
    at java.util.TimSort.sort(TimSort.java:216) ~[na:1.8.0_05]
    at java.util.Arrays.sort(Arrays.java:1435) ~[na:1.8.0_05]
    at com.google.common.collect.Ordering.sortedCopy(Ordering.java:855) ~[guava-20.0.jar:na]
    at springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider.requestHandlers(WebMvcRequestHandlerProvider.java:57) ~[springfox-spring-web-2.9.2.jar:null]
    at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper$2.apply(DocumentationPluginsBootstrapper.java:138) ~[springfox-spring-web-2.9.2.jar:null]
    at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper$2.apply(DocumentationPluginsBootstrapper.java:135) ~[springfox-spring-web-2.9.2.jar:null]
    at com.google.common.collect.Iterators$7.transform(Iterators.java:750) ~[guava-20.0.jar:na]
    at com.google.common.collect.TransformedIterator.next(TransformedIterator.java:47) ~[guava-20.0.jar:na]
    at com.google.common.collect.TransformedIterator.next(TransformedIterator.java:47) ~[guava-20.0.jar:na]
    at com.google.common.collect.MultitransformedIterator.hasNext(MultitransformedIterator.java:52) ~[guava-20.0.jar:na]
    at com.google.common.collect.MultitransformedIterator.hasNext(MultitransformedIterator.java:50) ~[guava-20.0.jar:na]
    at com.google.common.collect.ImmutableList.copyOf(ImmutableList.java:249) ~[guava-20.0.jar:na]
    at com.google.common.collect.ImmutableList.copyOf(ImmutableList.java:209) ~[guava-20.0.jar:na]
    at com.google.common.collect.FluentIterable.toList(FluentIterable.java:614) ~[guava-20.0.jar:na]
    at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.defaultContextBuilder(DocumentationPluginsBootstrapper.java:111) ~[springfox-spring-web-2.9.2.jar:null]
    at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.buildContext(DocumentationPluginsBootstrapper.java:96) ~[springfox-spring-web-2.9.2.jar:null]
    at springfox.documentation.spring.web.plugins.DocumentationPluginsBootstrapper.start(DocumentationPluginsBootstrapper.java:167) ~[springfox-spring-web-2.9.2.jar:null]
    at org.springframework.context.support.DefaultLifecycleProcessor.doStart(DefaultLifecycleProcessor.java:178) ~[spring-context-5.3.16.jar:5.3.16]
    ... 15 common frames omitted
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

原因:

Spring Boot 2.6及 更高版本使用的是PathPatternMatcher,而Springfox使用的路径匹配是基于AntPathMatcher的,所以更改配置如下:

spring:
  mvc:
    pathmatch:
      matching-strategy: ANT_PATH_MATCHER
  • 1
  • 2
  • 3

2. 访问页面 404

@EnableWebMvc 注解的问题,加了这个注解以后会导致静态资源路径无法访问。

继承了WebMvcConfigurationSupport,配置文件在中配置的相关内容会失效,需要重新指定静态资源

@EnableWebMvc注解(相当于继承WebMvcConfigurationSupport)和extends WebMvcConfigurationSupport导致404的原因都是因为同时有多个配置类实现了WebMvcConfigurer或继承了WebMvcConfigurationSupport的话,只会有一个生效,即以上两种情况导致了默认的WebMvcAutoConfiguration自动配置失效,故找不到静态资源。

解决办法是,保持一个配置类,将配置都在一个类中设置。

解决方法:

在一个统一的WebConfig中实现WebMvcConfigurer,并重写其中的public void addResourceHandlers(ResourceHandlerRegistry registry)方法,重新指定swagger静态资源,如下:

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

3、页面被拦截器拦截

放行该页面,如下:

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new JWTInterceptor())
                .excludePathPatterns("user/login")
                .excludePathPatterns("user/register")
                .excludePathPatterns("/swagger-resources/**")
                .excludePathPatterns("/swagger-ui.html/**")
                .excludePathPatterns("/webjars/**");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

快速开始

maven

<dependency>
  <groupId>io.springfox</groupId>
  <artifactId>springfox-boot-starter</artifactId>
  <version>3.0.0</version>
</dependency>
  • 1
  • 2
  • 3
  • 4

配置类

@Configuration  //注解为配置类,向spring容器注入bean对象
@EnableOpenApi
public class SwaggerConfig {
    @Bean  //把方法的返回值对象,注入容器
    public Docket docket(){
        return new Docket(DocumentationType.OAS_30)//选择swagger3.0版本号
                .apiInfo(apiInfo()).enable(true) //获取版权声明
                .select()
                //确定swagger能够访问到的请求接口范围,指定控制器包路径
                .apis(RequestHandlerSelectors.basePackage("org.example.controller"))
                .paths(PathSelectors.any())
                .build();  //构建对象
    }
    //撰写项目的版本声明
    private ApiInfo apiInfo(){
        return new ApiInfoBuilder()
                .title("医院预约挂号系统") //项目的名称
                .description("这是一个预约系统") //项目功能说明
                .contact(new Contact("自己的名字","自己的博客网址","12141579@qq.com"))
                .version("1.0")
                .build();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

访问路径

运行成功后的访问路径:

http://localhost:8080/swagger-ui/index.html

踩坑版本

maven

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-boot-starter</artifactId>
    <version>3.0.0</version>
</dependency>
  • 1
  • 2
  • 3
  • 4

配置类

package com.posinda.system.infrastructure.swagger;


import io.swagger.annotations.ApiOperation;
import io.swagger.models.auth.In;
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.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
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.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName : Swagger3Config
 * @Description :
 * @Author : felix
 * @Date: 2022-06-07 13:57
 */
@EnableOpenApi
@Configuration
public class Swagger3Config {

   /**
    * 创建API
    */
   @Bean
   public Docket createRestApi()
   {
      return new Docket(DocumentationType.OAS_30)
            // 是否启用Swagger
            .enable(true)
            // 用来创建该API的基本信息,展示在文档的页面中(自定义展示的信息)
            .apiInfo(apiInfo())
            // 设置哪些接口暴露给Swagger展示
            .select()
            // 扫描所有有注解的api,用这种方式更灵活
            .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
            // 扫描指定包中的swagger注解
//           .apis(RequestHandlerSelectors.basePackage("com.posinda.admin.peopleService.controller"))
            // 扫描所有
//           .apis(RequestHandlerSelectors.any())
//          .paths(PathSelectors.any())
            .build()
            /* 设置安全模式,swagger可以设置访问token */
//          .securitySchemes(securitySchemes())
//          .securityContexts(securityContexts())
//          .pathMapping(pathMapping)
            ;
   }

   /**
    * 添加摘要信息
    */
   private ApiInfo apiInfo()
   {
      // 用ApiInfoBuilder进行定制
      return new ApiInfoBuilder()
            // 设置标题
            .title("标题:若依管理系统_接口文档")
            // 描述
            .description("描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...")
            // 作者信息
            .contact(new Contact("felix", null, null))
            // 版本
            .version("版本号:" + "1.0")
            .build();
   }


   /**
    * 安全模式,这里指定token通过Authorization头请求头传递
    */
   private List<SecurityScheme> securitySchemes()
   {
      List<SecurityScheme> apiKeyList = new ArrayList<SecurityScheme>();
      apiKeyList.add(new ApiKey("Authorization", "Authorization", In.HEADER.toValue()));
      return apiKeyList;
   }

   /**
    * 安全上下文
    */
   private List<SecurityContext> securityContexts()
   {
      List<SecurityContext> securityContexts = new ArrayList<>();
      securityContexts.add(
            SecurityContext.builder()
                  .securityReferences(defaultAuth())
                  .operationSelector(o -> o.requestMappingPattern().matches("/.*"))
                  .build());
      return securityContexts;
   }

   /**
    * 默认的安全上引用
    */
   private List<SecurityReference> defaultAuth()
   {
      AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
      AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
      authorizationScopes[0] = authorizationScope;
      List<SecurityReference> securityReferences = new ArrayList<>();
      securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
      return securityReferences;
   }

   /**
    * 解决springboot2.6 和springfox不兼容问题  Failed to start bean ‘ documentationPluginsBootstrapper ‘ ; nested exception…
    * @return
    */
   @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);
            }
         }
      };
   }


}
  • 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
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159

一些问题

Failed to start bean ‘ documentationPluginsBootstrapper ‘ ; nested exception…

1) 不兼容解决办法

/**
    * 解决springboot2.6 和springfox不兼容问题  Failed to start bean ‘ documentationPluginsBootstrapper ‘ ; nested exception…
    * @return
    */
   @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);
            }
         }
      };
   }
  • 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

2) yml 配置文件

spring:
  mvc:
    pathmatch:
      matching-strategy: ant_path_matcher #swagger3 需配置,不然展示不了列表
  • 1
  • 2
  • 3

或者指定下面的注解:

@EnableMvc

    参考资料

    Springboot集成Swagger

    https://blog.csdn.net/yao22yao/article/details/125207679

    https://blog.csdn.net/qq_25046827/article/details/124086625

    声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/342244
    推荐阅读
    相关标签
      

    闽ICP备14008679号