版权说明: 本文由博主keep丶原创,转载请注明出处。
原文地址: https://blog.csdn.net/qq_38688267/article/details/117260547
文章目录
前言
以前为了解决跨域问题,百度到一个解决方案就是继承org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport
(后文使用WMCS
表示)增加一些跨域配置。但是自从用了WMCS
之后,就陆续出现了很多其他的问题,本文一一给各位列举,避免以后踩到相同的坑。
问题
WebMvcAutoConfiguration
配置类失效
WebMvcAutoConfiguration
类加了注解@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
,因此如果使用了WMCS
,就会导致该配置类失效。
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
// 这里,表示需要满足 不存在指定BEAN时,才生效
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class,
ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
// 省略一堆代码
}
Jackson 日期格式化失效
Spring默认使用Jackson
作为序列化工具,如果没有任何配置,在序列化接口参数时,解析Date
类型参数时就会报错。
没有使用WMCS
的解决方案
在配置文件中加上配置即可:
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
使用WMCS
的问题
WMCS
不会使用Spring维护的序列化类,而是自定义序列化类,这就导致上述配置修改失效(准确的说是配置是生效了,只是那个序列化类没有用)。
部分源码如下:
/**
* Adds a set of default HttpMessageConverter instances to the given list.
* Subclasses can call this method from {@link #configureMessageConverters}.
* @param messageConverters the list to add the default message converters to
*/
protected final void addDefaultHttpMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
// ...省略一堆代码
if (jackson2Present) {
Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json();
if (this.applicationContext != null) {
builder.applicationContext(this.applicationContext);
}
messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build()));
}
// ...省略一堆代码
}
使用WMCS
的解决方案
需要重写WMCS
的configureMessageConverters()
方法
/**
* 实现自定义日期格式化
*/
@Override
protected void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
addDefaultHttpMessageConverters(messageConverters);
for (HttpMessageConverter<?> mc : messageConverters) {
if (mc instanceof MappingJackson2HttpMessageConverter) {
MappingJackson2HttpMessageConverter mc1 = (MappingJackson2HttpMessageConverter) mc;
ObjectMapper objectMapper = mc1.getObjectMapper();
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.setDateFormat(new SimpleDateFormat(IfmConstants.DEFAULT_DATE_FORMAT));
}
converters.add(mc);
}
}
ObjectMapper Bean失效
与Jackson问题一样,WMCS
也不会用Spring维护的ObjectMapper
Bean实例,而是自己创建了一个ObjectMapper
。或者严格点来说,上述问题跟该问题是同一个问题。
源码跟上述问题也一样:
if (jackson2Present) {
Jackson2ObjectMapperBuilder builder = Jackson2ObjectMapperBuilder.json();
if (this.applicationContext != null) {
builder.applicationContext(this.applicationContext);
}
// 这里builder.build()方法就是创建一个ObjectMapper类
messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build()));
}
Bean冲突
WMCS
会自定义一些Bean,包括:
- Validator
- FormattingConversionService
- CompositeUriComponentsContributor
- HandlerFunctionAdapter
- RequestMappingHandlerAdapter
- HandlerMapping
- …
作者就是在自定义Validator
校验器的时候出现了Bean冲突,需要在自定义Validator
时增加@Primary
注解。
导致第三方HTTP拦截器注入失效
作者在集成分布式事务工具SEATA
时,SEATA
需要注册一个HTTP拦截器,但是用了WMCS
会导致其配置失效,SEATA
源码如下:
@ConditionalOnWebApplication
public class SeataHandlerInterceptorConfiguration implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new SeataHandlerInterceptor()).addPathPatterns("/**");
}
}
解决方案
需要重写WMCS的addInterceptors
方法,手动注入相关拦截器
/**
* Override this method to add Spring MVC interceptors for
* pre- and post-processing of controller invocation.
* @see InterceptorRegistry
*/
protected void addInterceptors(InterceptorRegistry registry) {
}
正解:实现WebMvcConfigurer
接口
该接口基本能够实现WMCS
的功能,如增加HTTP拦截器,增加跨域设置,增加Swagger
等资源白名单等。