spring设计好美:WebMvcConfigurer

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010399009/article/details/84958141

从WebMvcConfigurer了解spring设计的美味

说明

本篇文章主要是讲WebMvcConfigurer设计的巧妙之处。
目的之一:弄清WebMvcConfigurer是什么。
目的之二:WebMvcConfigurer设计中的优点

WebMvcConfigurer是什么

如何使用WebMvcConfigurer

@EnableWebMvc
@Configuration
public class WebConfiguration implements WebMvcConfigurer {

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {

    }
}

这是一个简单的实现:
spring4.0以前我们是要WebMvcConfigurerAdapter,但是5.0不需要了。
Java8接口新特性:
1.default默认实现。
2.static默认实现。

也就是我们被default标志了的,不需要必须实现了。
WebMvcConfigurerAdapter这个就是把WebMvcConfigurer接口覆盖成了保护类型,我们实现WebMvcConfigurerAdapter不需要把所有的接口方法都实现。

WebMvcConfigurer是什么?我们简单理解就是以前我们以前用xml配置时候的,spring-web.xml。就是我们可以配置很多web方面的组件,比如说消息转化,拦截器,视图转化器,跨域配置,资源控制器等等。我们只需要看接口的注释说明。

我们看spring源码的时候看到注解,只需要点进去,都会有相应的处理方法。
@EnableWebMvc
发现Import(DelegatingWebMvcConfiguration.class)
也就是导入DelegatingWebMvcConfiguration该配置

public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport
public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware 

DelegatingWebMvcConfiguration:
主要是用来检测Spring容器中有多少WebMvcConfigurer,然后把它加入进来。并且有很多方法这些方法我们可以理解为代理方法。
WebMvcConfigurationSupport就是来做我们web组件的初始化用的,比如HandlerMapping,RequestMappingHandlerAdapter,RequestMappingHandlerMapping

从这里我们知道了如何使用了WebMvcConfigurer

WebMvcConfigurer设计中的优点

设想:如果让你自己设计,例如我要自己扩展消息转化器,现在我们知道了RequestMappingHandlerAdapter.getDefaultArgumentResolvers中

resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice));
		resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice));
	public List<HttpMessageConverter<?>> getMessageConverters() {
		return this.messageConverters;
	}

。我们知道了RequestMappingHandlerAdapter.getMessageConverters获得消息转化器,我们现在只需要想办法,将它扩展到messageConverters中即可。

设计思想:
1.开放关闭原则。
2.针对接口编程。

1.我们需要写一个接口,这个接口有一个默认的方法setMessageConverters,
2.扩展这个接口,做成一个配置A。
3.在实例化RequestMappingHandlerAdapter是,setMessageConverters的时候,调用一个模板方法,或者将所有A配置收集起来,放入messageConverters即可。
这里我们还需要考虑的几个问题:
1.默认的消息转化器怎么办?
2.如果没有这些配置怎么处理?

我们来看看spring是怎么做的。

@Configuration
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {

	private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();


	@Autowired(required = false)
	public void setConfigurers(List<WebMvcConfigurer> configurers) {
		if (!CollectionUtils.isEmpty(configurers)) {
			this.configurers.addWebMvcConfigurers(configurers);
		}
	}


	@Override
	protected void configurePathMatch(PathMatchConfigurer configurer) {
		this.configurers.configurePathMatch(configurer);
	}

	@Override
	protected void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
		this.configurers.configureContentNegotiation(configurer);
	}

	@Override
	protected void configureAsyncSupport(AsyncSupportConfigurer configurer) {
		this.configurers.configureAsyncSupport(configurer);
	}

	@Override
	protected void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
		this.configurers.configureDefaultServletHandling(configurer);
	}

WebMvcConfigurerComposite是什么呢?

class WebMvcConfigurerComposite implements WebMvcConfigurer {

	private final List<WebMvcConfigurer> delegates = new ArrayList<>();


	public void addWebMvcConfigurers(List<WebMvcConfigurer> configurers) {
		if (!CollectionUtils.isEmpty(configurers)) {
			this.delegates.addAll(configurers);
		}
	}


	@Override
	public void configurePathMatch(PathMatchConfigurer configurer) {
		for (WebMvcConfigurer delegate : this.delegates) {
			delegate.configurePathMatch(configurer);
		}
	}

从字面理解是一个WebMvcConfigurer代理
我们配置的WebMvcConfigurer均会被添加到WebMvcConfigurerComposite中

而DelegatingWebMvcConfiguration中的其他配置方法都是WebMvcConfigurationSupport的模板方法。

来看
RequestMappingHandlerAdapter如何加载消息转化器的:

	protected final List<HttpMessageConverter<?>> getMessageConverters() {
		if (this.messageConverters == null) {
			this.messageConverters = new ArrayList<>();
			configureMessageConverters(this.messageConverters);
			if (this.messageConverters.isEmpty()) {
				addDefaultHttpMessageConverters(this.messageConverters);
			}
			extendMessageConverters(this.messageConverters);
		}
		return this.messageConverters;
	}
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
	}

先去看看有没有配置消息转化器,没有配置就加载默认的,再看看有没有扩展的消息转化器,这里的都是模板方法,都是在DelegatingWebMvcConfiguration中做的。

我当时在想一个问题,DelegatingWebMvcConfiguration不就可以实现吗,为什么还要WebMvcConfigurerComposite?
DelegatingWebMvcConfiguration不用WebMvcConfigurerComposite直接使用List 干嘛这样做呢?

我思考可能是这样的,spring任务,WebMvcConfigurerComposite中添加消息转化器这个功能其实是一个固定的,不会怎么变的,如果我们写成配置的话,就不好了,因为配置会改变,如果日后需要扩展的话又会去动固定的功能。

当然如果我设计的话,我可能就不用WebMvcConfigurerComposite了。

总结

1.WebMvcConfigurer就是我们来配置web请求过程中的一些组建。
2.java8接口可以用default,也可以用static方法。
3.针对接口编程,模板方法。

猜你喜欢

转载自blog.csdn.net/u010399009/article/details/84958141