SpringMvc配置与默认Swagger的冲突

问题背景

项目使用了Swagger自动生成可视化文档,版本为2.9.2。正常情况下SpringBoot整合Swagger后默认就能访问文档页面。现在在项目中尝试配置SpringMvc拦截器,发现Swagger页面无法访问。

问题复现

在SpringBoot中引入Mvc配置,加入拦截器。有两种形式:

1、@Configuration配置类继承WebMvcConfigurationSupport,该类是Mvc配置的主要类。如:

@Configuration
public class WebConfig extends WebMvcConfigurationSupport {

    @Autowired
    private StatisticsInterceptor statisticsInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(statisticsInterceptor).addPathPatterns("/**");
    }
}

2、@Configuration配置类上加入@EnableWebMvc注解,并实现WebMvcConfigurer,WebMvcConfigurer提供了部分Mvc配置。如

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private StatisticsInterceptor statisticsInterceptor;


    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(statisticsInterceptor).addPathPatterns("/**");
    }
}

加入上述配置后,拦截器生效,但是Swagger页面报404。

原因分析

WebMvcAutoConfiguration自动配置

首先看看没有手动配置SpringMvc之前,SpringBoot自动做了什么?定位到WebMvcAutoConfiguration,代码片段如下:

@ConditionalOnMissingBean(WebMvcConfigurationSupport.class) //注意这里的条件
... //省略无关注解
public class WebMvcAutoConfiguration {

	// Defined as a nested config to ensure WebMvcConfigurer is not read when not
	// on the classpath
	@Import(EnableWebMvcConfiguration.class)
	... //省略无关注解
	public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {

		@Override
		public void addResourceHandlers(ResourceHandlerRegistry registry) {
			if (!this.resourceProperties.isAddMappings()) {
				logger.debug("Default resource handling disabled");
				return;
			}
			Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
			CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
			if (!registry.hasMappingForPattern("/webjars/**")) {
			    // 添加了webjars的路径映射
				customizeResourceHandlerRegistration(registry.addResourceHandler("/webjars/**")
						.addResourceLocations("classpath:/META-INF/resources/webjars/")
						.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
			}
			String staticPathPattern = this.mvcProperties.getStaticPathPattern();
			if (!registry.hasMappingForPattern(staticPathPattern)) {
		        // 添加了 /** 到 "/META-INF/resources/","/resources/", "/static/", "/public/" 的路径映射
				customizeResourceHandlerRegistration(registry.addResourceHandler(staticPathPattern)
				.addResourceLocations(getResourceLocations(this.resourceProperties.getStaticLocations()))
						.setCachePeriod(getSeconds(cachePeriod)).setCacheControl(cacheControl));
			}
		}
	}
	
	/**
	 * Configuration equivalent to {@code @EnableWebMvc}.
	 */
	@Configuration(proxyBeanMethods = false)
	public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {
	...
	}

}

关键类是WebMvcAutoConfigurationAdapterEnableWebMvcConfiguration

可以看到,SpringBoot在不存在WebMvcConfigurationSupport配置类时,会引入WebMvcAutoConfigurationAdapter,这个类是

WebMvcConfigurer的实现类,给Mvc加入了一些默认配置,其中就包括加入了两个资源处理器。

等同于
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/")
registry.addResourceHandler("/**").addResourceLocations("classpath:/META-INF/resources/",
                "classpath:/resources/", "classpath:/static/", "classpath:/public/")

此外WebMvcAutoConfigurationAdapter类上@Import(EnableWebMvcConfiguration.class)引入了下面的EnableWebMvcConfiguration类,这个类继承了DelegatingWebMvcConfiguration,而DelegatingWebMvcConfiguration继承了WebMvcConfigurationSupport

这四个类的关系如下所示:

avatar

DelegatingWebMvcConfiguration内部有WebMvcConfigurer的组合类WebMvcConfigurerCompositeDelegatingWebMvcConfiguration中对Mvc配置的处理,实际上是委托多个WebMvcConfigurer来完成。

至此,我们可以看出,WebMvcAutoConfiguration自动配置的原理和@EnableWebMvc+WebMvcConfigurer效果是一样的@EnableWebMvc注解引入的是DelegatingWebMvcConfiguration类

原因说明

了解了Mvc自动配置的原理后,本文开头出现的问题原因就很明朗了。因为我们手动引入了WebMvcConfigurationSupport对象,因此自动配置不会生效。自动配置时,系统默认设置了两个资源处理器处理静态资源;而上面的手动配置只加入了拦截器,并没有配置资源处理器。

在springfox-swagger-ui-2.9.2.jar中,swagger-ui.html放在META-INF/resources下面,没有配置资源处理器所以无法访问。

解决方法

以@EnableWebMvc+WebMvcConfigurer的方式配置为例,加入资源映射处理器,和自动配置保持一致即可:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private StatisticsInterceptor statisticsInterceptor;


    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(statisticsInterceptor).addPathPatterns("/**");
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        //swagger-2.9.2静态资源不是在webjars目录下,实际验证只需要下面的配置即可
        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
        registry.addResourceHandler("/**").addResourceLocations("classpath:/META-INF/resources/",
                "classpath:/resources/", "classpath:/static/", "classpath:/public/");
    }
}
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值