SpringBoot配置Swagger2接口未显示分析

0.背景

  • 项目A继承自项目B, SpringBoot1.5.16.RELEASE

        B
        com.****
        ****-SNAPSHOT

1.配置信息

  • 项目A中配置的 Swagger2版本

            io.springfox
            springfox-swagger2
            2.9.2

                    io.swagger
                    swagger-models

                    com.google.guava
                    guava

            io.swagger
            swagger-models
            1.5.21

            io.springfox
            springfox-swagger-ui
            2.9.2

                    com.google.guava
                    guava

  • 项目A的 Swagger2Config.class
@EnableSwagger2
@Configuration
@EnableWebMvc
public class Swagger2Config extends WebMvcConfigurerAdapter {

    /**
     * 添加对swagger资源的放行
     *
     * @param registry
     */
    @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/");
    }

    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2).groupName("myDocket")
                .apiInfo(apiInfo())
                .pathMapping("/")
                .enable(true)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.****.controller"))
                .apis(RequestHandlerSelectors.withClassAnnotation(ApiOperation.class))
                .paths(PathSelectors.any())
                .build();
    }

    //构建 api文档的详细信息函数
    private ApiInfo apiInfo() {
        return new ApiInfoBuilder()
                //页面标题
                .title("Spring Boot Swagger2 构建RESTful API")
                //条款地址
                .description("*** Web Service Api Document")
                .version("1.0.0")
                .license("Apache 2.0")
                .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0")
                //描述
                .build();
    }
}

3.定位

配置如上信息的时候后启动端口进行调试:

SpringBoot配置Swagger2接口未显示分析

正常的显示是没问题,但是所有的接口信息都不能展示,加了 Swagger的的注解,未生效,报 No operations defined in spec!

这种原因大部分是因为 package没有被扫到,即上面的 .apis(RequestHandlerSelectors.basePackage("com.****.controller")),这段一开始,在 debug过程中,也确实走了这段代码,但是未生效

之后试了下另外一个完全新搭建的项目(这个项目是从老项目中整体中剥离出来的,所以才有了继承父pom的写法),同样配置是完全OK的,正常显示的。

4.解决

上图中的1,2两个标志指向了一个一个邮箱地址,但在项目A中没找到此邮箱地址,去B项目搜了下,发现是这个 SwaggerConfig.class影响到了

@Configuration
@Profile("!prod")
@EnableSwagger2
public class SwaggerConfig extends ApolloAware{
    private static final String BASE_CONTROLLER_LEAF_NAME = "web";

    @Value("${spring.application.name}")
    private String appName;

    protected ApplicationContext applicationContext;
    public SwaggerConfig(@Autowired ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @Bean
    public Docket api() {
        Object app = apolloApp(applicationContext);
        ApolloApplication apollo = app.getClass().getAnnotation(ApolloApplication.class);
        String defaultBasePackage = app.getClass().getPackage().getName() + "." + BASE_CONTROLLER_LEAF_NAME;
        String scanPackage = apollo.swaggerBasePackage().trim().isEmpty() ? defaultBasePackage : apollo.swaggerBasePackage();
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(getApiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage(scanPackage))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo getApiInfo() {
        Contact contact = new Contact("****.cloud", "http://*****", "****.cloud@****.com");
        return new ApiInfoBuilder()
                .title(appName)
                .description("Web Service Api Document")
                .version("1.0.0")
                .license("Apache 2.0")
                .licenseUrl("http://www.apache.org/licenses/LICENSE-2.0")
                .contact(contact)
                .build();
    }

这其实也能解释在A项目中,一开始没有单独命名 groupName("myDocket")会提示 docket重复冲突的错误,在B项目的 SwaggerConfig.class中,`groupName是默认的,也能发现这个里面有一个写法是默认的package

    String defaultBasePackage = app.getClass().getPackage().getName() + "." + BASE_CONTROLLER_LEAF_NAME;

重新审视了A项目的注解,主要是启动类上的注解,发现了采用了复合注解的写法,下面的扩展内容会说到

@ApolloApplication
@ServletComponentScan
public class XXXApplication {
    public static void main(String[] args) {
        SpringApplication.run(XXXApplication.class, args);
    }
}

@ApolloApplication注解是复合注解,源码是这样的:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
        @ComponentScan.Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
        @ComponentScan.Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface ApolloApplication {
    @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "exclude")
    Class[] exclude() default {};

    @AliasFor(annotation = EnableAutoConfiguration.class, attribute = "excludeName")
    String[] excludeName() default {};

    @AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
    String[] scanBasePackages() default {"com.******"};

    @AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
    Class[] scanBasePackageClasses() default {};

    String swaggerBasePackage() default "";
}

此注解集成了 @SpringBootConfiguration, @EnableAutoConfiguration@ComponentScan等注解,其中的一个参数 swaggerBasePackage,指的是不指定包扫描的路径,所以调整下启动类的注解

@ApolloApplication(swaggerBasePackage = "com.****.controller")
@ServletComponentScan
public class XXXApplication {
    public static void main(String[] args) {
        SpringApplication.run(XXXApplication.class, args);
    }
}

接口信息顺利加载出来

SpringBoot配置Swagger2接口未显示分析

注解扩展

@EnableAutoConfiguration

@EnableAutoConfiguration的作用是启动自动配置,意思是Spring Boot会根据你添加的jar包来配置你项目的默认设置,比如你添加了Spring Boot提供的spring-boot-starter-web依赖,其中包含了Tomcat和Spring MVC,这个注释就会假设你正在开发一个Web应用程序,自动地帮你添加Web项目中所需要的Spring配置。

@ComponentScan

@ComponentScan的作用是扫描当前包及其子包下被@Component注解标记的类并纳入到Spring容器中进行管理。是Spring传统XML配置的的替代。

@Controller,@Service,@Repository是@Component的子注解,所以也会被@ComponentScan扫描并做和@Component相同的处理。

@ComponentScan提供了basePackage参数定义要扫描的包,如果不设置,默认会扫描包的所有类,即默认扫描*/.class路径,建议加上该参数以减少加载的时间。

@SpringBootApplication提供的参数

exclude

exlude参数继承自@EnableAutoConfiguration注解的同名参数,根据class来排除特定的类加入Spring容器,传入参数的value类型是class类型数组。

@SpringBootApplication(exclude = {Good.class, Bad.class})

excludeName

exludeName参数继承自@EnableAutoConfiguration注解的同名参数,根据className来排除特定的类加入Spring容器,传入参数的value类型是class的全类名字符串数组。

@SpringBootApplication(excludeName = {"com.yanggb.xxx.Good", "com.yanggb.yyy.Bad"})

exclude和excludeName可以用来关闭指定的自动配置,比如关闭数据源相关的自动配置。

scanBasePackages

scanBasePackages参数继承自@ComponentScan注解的basePackages参数,指定要扫描的包,传入参数的value类型是包名的字符串数组。

@SpringBootApplication(scanBasePackages = {"com.yanggb.xxx", "com.yanggb.yyy"})

scanBasePackageClasses

scanBasePackageClasses参数继承自@ComponentScan注解的basePackageClasses参数,指定要扫描的包,传入参数的value类型是包名的字符串数组。

@SpringBootApplication(scanBasePackageClasses = {Good.class, Bad.class}

Reference

  1. springboot注解@SpringBootApplication分析

Original: https://www.cnblogs.com/wat1r/p/13653554.html
Author: 阿飞算法
Title: SpringBoot配置Swagger2接口未显示分析

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/570091/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 一文总结高并发大数据量下MySQL开发规范【军规】

    在互联网公司中,MySQL是使用最多的数据库,那么在并发量大、数据量大的互联网业务中,如果高效的使用MySQL才能保证服务的稳定呢?根据本人多年运维管理经验的总结,梳理了一些核心的…

    Java 2023年6月16日
    0104
  • Java:常用反射获取类信息

    Constructor getConstructor(Class… parameterTypes):返回单个公共构造方法 Constructor getDeclared…

    Java 2023年6月7日
    075
  • Idea2019.3 :一直卡在Resolving Maven dependencies

    maven仓库是阿里的 问题 如图,下载jar包挺快,一直卡在解析那一步。。。。导致写注解老是爆红 解决 修改maven Importing的jvm参数, 默认为700多, 直接修…

    Java 2023年6月7日
    079
  • Spring boot 2.0 之优雅停机

    spring boot 框架在生产环境使用的有一段时间了,它”约定大于配置”的特性,体现了优雅流畅的开发过程,它的部署启动方式( java -jar xxx…

    Java 2023年5月30日
    073
  • websocket2.0 适用于发送的数据体很大

    当websocket发送的数据体积很大,需要的传输时间很长,并且传输频率较高的情况下使用 pom配置 一、创建内部的缓存对象 二、创建websocket对象 三、创建定时任务进行状…

    Java 2023年6月16日
    073
  • logback的使用

    一、logback的介绍 Logback是由log4j创始人设计的另一个开源日志组件,官方网站: http://logback.qos.ch。 常用处理java的日志组件:slf4…

    Java 2023年6月5日
    071
  • java poi生成数据透视表

    /** * 导出EXCEL—poi */ @Override public void pivot(HttpServletResponse response) throws Ex…

    Java 2023年6月16日
    095
  • 浅聊Mybatis是怎么扫描并且注入到spring容器中的(源码向)

    源码很枯燥,但是能学到很多东西,废话不多说直接进入正题: @MapperScan 扫描注入 spring beanDefinition 的流程 在使用注解确认扫包范围的时候 注解里…

    Java 2023年6月8日
    092
  • 美团动态线程池实践思路,开源了

    大家好,今天我们来聊一个比较实用的话题,动态可监控的线程池实践,全新开源项目(DynamicTp)地址在文章末尾,欢迎交流学习。 写在前面 稍微有些Java编程经验的小伙伴都知道,…

    Java 2023年6月14日
    075
  • javacv 图片合成

    java;gutter:false; /*<em> * 图片组合 </em>/ @Slf4j public class ComposeImageUtil {…

    Java 2023年5月29日
    072
  • 给IDEA道个歉,这不是它的BUG,而是反编译插件的BUG。

    你好呀,我是歪歪。 主要描述了在 IDEA 里面反编译后的 class 文件中有这样的代码片段: 很明显,这玩意就是一个语法错误。 但是当我用其他的编译器打开之后,显示又是正常的。…

    Java 2023年6月5日
    074
  • 五,手写SpringMVC框架,过滤器的使用

    过滤器 8.1 编写字符过滤器 C har acterEncodingFilter 复制项目mymvc4 ,新建项目mymvc5 package com.hy.filter; im…

    Java 2023年6月16日
    078
  • 链表

    链表 1 链表 链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的。 2 单链表 商品结点类 package com.acti.lin…

    Java 2023年6月14日
    0115
  • Java开发笔记(一百五十三)时间戳的获取和转换

    日期时间是Java一个重要的数据类型,常见的日期时间格式通常为”yyyy-MM-dd HH:mm:ss”,但是计算机中存储的日期时间并非字符串形式,而是长整…

    Java 2023年6月6日
    075
  • IntelliJ IDEA正版一年多少钱?

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Java 2023年5月29日
    085
  • github学生认证——申请学生开发包

    写在前面 申请学生认证的好处: GitHub学生的免费AWS Educate入门帐户,价值100美元。 专业的桌面IDE:IntelliJ IDEA,PyCharm等。学生的免费订…

    Java 2023年6月9日
    0101
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球