1 Spring Web MVC
本文将介绍Spring Web MVC的几种配置方法。
2 @EnableWebMvc
在上一篇文章中,我们已经使用过@EnableWebMvc
注解进行Spring Web MVC的配置。@EnableWebMvc
注解启用Spring Web MVC自动配置的特性,用于初始化Spring Web MVC框架。那么,自动配置到底配置了什么呢?
前面的文章中介绍过Web应用,抽象来讲就是一个处理HTTP请求并返回HTTP响应的程序。这个程序的处理过程大致可以描述成:
-
将HTTP请求反序列化成一个
ServletRequest
对象 -
根据
ServletRequest
的信息,找到能正确处理该请求的某个@RequestMapping
方法 -
将
ServletRequest
对象的信息解析成@RequestMapping
方法的各种类型的入参 -
调用
@RequestMapping
方法,得到类型为ModelAndView
的结果 -
根据
ModelAndView
的内容,填充ServletResponse
对象 -
将
ServletResponse
对象序列化成HTTP响应返回给浏览器
在Spring Web MVC中,对上述的过程进行了设计和抽象。比如:通过request信息查找handler方法的HandlerMapping
;根据ModelAndView
对象组装HTTP响应的ViewResolver
;从request解析出各种方法入参的HttpMessageConverter
……
上述过程涉及的概念,Spring Web MVC均提供了默认的实现。@EnableWebMvc
注解则是告诉Spring Web MVC使用这些默认实现完成应用的初始化。当然,用户也可以对当中的一些或者全部做个性化的设置。这就是@EnableWebMvc
注解的自动配置功能。
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}
上面是@EnableWebMvc
的源代码,通过使用@Import(DelegatingWebMvcConfiguration.class)
注入了DelegatingWebMvcConfiguration
类。
DelegatingWebMvcConfiguration
继承自WebMvcConfigurationSupport
。WebMvcConfigurationSupport
是实现Spring Web MVC自动配置的核心类,它包含了很多方法,但大部分方法的处理方式都很类似。
WebMvcConfigurationSupport
通过定义@Bean
方法向WebApplicationContext
容器中注入Bean对象。这些@Bean
方法会优先提供一套默认的配置,然后调用DelegatingWebMvcConfiguration
中的具体方法进行个性化设置。这样的模式既保证了Spring Web MVC框架可以提供一套默认的标准配置,也同时支持开发人员根据框架约定进行个性化设置。下面是一个简化版本的示例:
public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware
...
@Bean
public ViewResolver mvcViewResolver(@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager) {
// 提供默认的一套配置
ViewResolverRegistry registry = new ViewResolverRegistry(contentNegotiationManager, this.applicationContext);
// 调用子类方法,进行个性化设置
configureViewResolvers(registry);
...
return composite;
}
...
}
DelegatingWebMvcConfiguration
中引用了一个类型为WebMvcConfigurerComposite
的对象。WebMvcConfigurerComposite
既是WebMvcConfigurer
的代理类,也是WebMvcConfigurer
的一个具体实现。
DelegatingWebMvcConfiguration
通过setConfigurers(...)
方法将IoC容器中的所有WebMvcConfigurer
类型的Bean对象注入到了WebMvcConfigurerComposite
中。真正处理个性化设置的其实是WebMvcConfigurerComposite
类。
@Configuration(proxyBeanMethods = false)
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);
}
}
}
总结一下,Spring Web MVC框架中,个性化设置全部是通过代理类WebMvcConfigurerComposite
调用IoC容器中所有WebMvcConfigurer
类型的Bean对象实现的。开发人员可以设计多个实现了WebMvcConfigurer
接口的@Configuration
对象,用于对Spring Web MVC启动过程进行个性化设置。开发人员不需要关心这些对象如何被调起,该过程将由Spring Web MVC框架自动处理。
3 WebMvcConfigurer
到这里,我们便可以修改上一篇文章中的配置方法,让AppConfig
类实现WebMvcConfigurer
接口,这样我们就可以通过实现WebMvcConfigurer
接口中定义的特定方法来对Web应用进行个性化。
package org.example.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "org.example.controller")
public class AppConfig implements WebMvcConfigurer {
}
4 另一种配置方法
根据前面介绍,WebMvcConfigurer
会被WebMvcConfigurerComposite
加载,WebMvcConfigurerComposite
则会被DelegatingWebMvcConfiguration
调用,所以调用入口在DelegatingWebMvcConfiguration
类上。也就是说,WebMvcConfigurer
中的所有操作都可以通过改变DelegatingWebMvcConfiguration
相关方法来实现。因此,DelegatingWebMvcConfiguration
比WebMvcConfigurer
更灵活。
我们可以使@Configuration
对象直接继承DelegatingWebMvcConfiguration
来达到更灵活的配置功能。这时,在@Configuration
上就不能再使用@EnableWebMvc
了,否则DelegatingWebMvcConfiguration
相关的代码会被框架调用两次,产生错误。
package org.example.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration;
@Configuration
@ComponentScan(basePackages = "org.example.controller")
public class AppConfig extends DelegatingWebMvcConfiguration {
}
5 结论
好了,Spring Web MVC框架启动配置的所有方法都介绍完了。整个系列主要介绍了四种启动配置方式:
-
通过传统的web.xml文件进行Spring Web MVC应用的配置。
-
通过使用
WebApplicationInitializer
+@EnableWebMvc
进行Spring Web MVC应用的配置。 -
通过使用
WebApplicationInitializer
+@EnableWebMvc
+WebMvcConfigurer
进行Spring Web MVC应用的配置。 -
通过使用
WebApplicationInitializer
+DelegatingWebMvcConfiguration
进行Spring Web MVC应用的配置。