WebMvcConfigurationSupport踩坑经历

版权说明: 本文由博主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的解决方案

   需要重写WMCSconfigureMessageConverters()方法

    /**
     * 实现自定义日期格式化
     */
    @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维护的ObjectMapperBean实例,而是自己创建了一个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等资源白名单等。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值