在前面的文档中讲解了Spring MVC的特殊beans,以及DispatcherServlet使用的默认实现。在本部分,你会学习两种额外的方式来配置Spring MVC。分别是:MVC Java config 和 MVC XML namespace。
原文:
Section 22.2.1, “Special Bean Types In the WebApplicationContext” and Section 22.2.2, “Default DispatcherServlet Configuration” explained about Spring MVC’s special beans and the default implementations used by the
DispatcherServlet
.
MVC Java config 和 MVC namespace,提供了类似的默认配置,都覆盖了DispatcherServlet的默认配置。其目标是①让多数应用免于创建同样的配置,还是②提供更高级的构建来配置Spring MVC,不需要底层配置的相关知识。
你可以按照你的倾向来选择MVC Java config 或 MVC namespace。只是,在后面你会发现,使用MVC Java config,更容易发现底层的配置,从而可以对创建好的Spring MVC beans做出更细化的定制。
现在让我们开始吧。
1、启用MVC Java config 或 MVC XML namespace
想要启用MVC Java config,只需要将@EnableWebMvc添加到你的一个@Configuration class即可。
@Configuration @EnableWebMvc public class WebConfig { }
或者在XML中(注意,这里还是启用MVC Java config),需要在你的DispatcherServlet context (或你的root context -- 如果没有定义DispatcherServlet context的话)内使用 <mvc:annotation-driven> 元素:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <mvc:annotation-driven/> </beans>
上面,已经注册了一个 RequestMappingHandlerMapping、一个RequestMappingHandlerAdapter、以及一个ExceptionHandlerExceptionResolver 以支持使用注解Controller的注解方法(如@RequestMapping、@ExceptionHandler)来处理request。
它还启用了如下内容:
- Spring 3 风格的类型转换 -- 通过一个ConversionService 实例 配合JavaBean PropertyEditors,用于Data Binding。
- 支持@NumberFormat注解通过ConversionService 来格式化Number字段。
- 支持使用@DateTimeFormat注解来格式化Date、Calendar、Long、以及Joda Time字段。
- 支持使用@Valid校验@Controller input -- 如果classpath中存在一个JSR-303 Provider。
- HttpMessageConverter支持@RequestMapping或@ExceptionHandler method的 @RequestBody method parameters和@ResponseBody method 返回值。 -- 比较长,其实就是支持handler (controller)的@RequestBody参数/@ResponseBody返回值。
下面是<mvc:annotation-driven> 设置的完整的HttpMessageConverter列表:
ByteArrayHttpMessageConverter
converts byte arrays.StringHttpMessageConverter
converts strings.ResourceHttpMessageConverter
converts to/fromorg.springframework.core.io.Resource
for all media types.SourceHttpMessageConverter
converts to/from ajavax.xml.transform.Source
.FormHttpMessageConverter
converts form data to/from aMultiValueMap<String, String>
.Jaxb2RootElementHttpMessageConverter
converts Java objects to/from XML?—?added if JAXB2 is present and Jackson 2 XML extension is not present on the classpath.MappingJackson2HttpMessageConverter
converts to/from JSON?—?added if Jackson 2 is present on the classpath.MappingJackson2XmlHttpMessageConverter
converts to/from XML?—?added if Jackson 2 XML extension is present on the classpath.AtomFeedHttpMessageConverter
converts Atom feeds?—?added if Rome is present on the classpath.RssChannelHttpMessageConverter
converts RSS feeds?—?added if Rome is present on the classpath.
See Section 22.16.12, “Message Converters” for more information about how to customize these default converters.
Jackson JSON 和 XML converters是使用Jackson2ObjectMapperBuilder创建的ObjectMapper实例们来创建的,其目的是提供一个更好的默认配置。
该builder定制了Jackson的默认properties:
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES
is disabled.MapperFeature.DEFAULT_VIEW_INCLUSION
is disabled.
它还自动注册了下列很有名的模块 -- 如果能够在classpath中检测到的话:
- jackson-datatype-jdk7: support for Java 7 types like
java.nio.file.Path
. - jackson-datatype-joda: support for Joda-Time types.
- jackson-datatype-jsr310: support for Java 8 Date & Time API types.
- jackson-datatype-jdk8: support for other Java 8 types like
Optional
.
2、修改已提供的配置
想要以Java形式定制默认的配置,你可以简单的实现WebMvcConfigurer接口,或者继承WebMvcConfigurerAdapter并重写需要的方法:
@Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { // Override configuration methods... }
想要定制 <mvc:annotation-driven>的默认配置,需要检查其attributes和其子元素。可以查看Spring MVC XML schema,或者使用IDE的自动完成功能来探索可用的attributes和子元素。
3、类型转换和格式化
默认已注册了Number和Date类型的formatters,支持@NumberFormat和@DateTimeFormat注解。 还注册了对于Joda Time格式化库的完全支持 -- 需要在classpath中有Joda Time。想要注册自定义的formatters和converters,重写addFormatters方法即可:
@Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public void addFormatters(FormatterRegistry registry) { // Add formatters and/or converters } }
在MVC namespace中,<mvc:annotation-driven>会应用同样的默认设置。如果想注册自己的formatters和converters,只需要提供一个ConversionService:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <mvc:annotation-driven conversion-service="conversionService"/> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="converters"> <set> <bean class="org.example.MyConverter"/> </set> </property> <property name="formatters"> <set> <bean class="org.example.MyFormatter"/> <bean class="org.example.MyAnnotationFormatterFactory"/> </set> </property> <property name="formatterRegistrars"> <set> <bean class="org.example.MyFormatterRegistrar"/> </set> </property> </bean> </beans>
See Section 9.6.4, “FormatterRegistrar SPI” and the
FormattingConversionServiceFactoryBean
for more information on when to use FormatterRegistrars.
4、校验
Spring提供了一个Validator接口,可被用于在应用的所有layers上的校验。在Spring MVC中,你可以将其配置成一个全局的Validator实例,用于所有@Valid或@Validated controller method argument的地方,和/或一个Controller内局部的Validator,通过一个@InitBinder方法。 全局的和局部的validator实例们可以组合校验。
Spring还支持 JSR-303/JSR-349 Bean Validation -- 通过LocalValidatorFactoryBean,LocalValidatorFactoryBean会将Spring的Validator接口适配到javax.validation.Validator。 该类可以被插入Spring MVC作为一个全局的validator,下面有讲。
使用@EnableWebMvc或 <mvc:annotation-driven>,会默认地在Spring MVC中自动注册Bean Validation支持 -- 通过LocalValidatorFactoryBean,前提是classpath中有一个Bean Validation Provider,如Hibernate Validator。
有时候,将LocalValidatorFactoryBean注入到controller或其他类中很方便。最简单的方法就是声明你自己的@Bean,并使用@Primary以避免与MVC Java config提供的那个发送冲突。
如果你更喜欢MVC Java config提供的那个,你会需要重写WebMvcConfigurationSupport的mvcValidator(),并声明方法显式地返回LocalValidatorFactory而非Validator。详见 Section 22.16.13, “Advanced Customizations with MVC Java Config”。
或者,你可以配置自己的全局 Validator实例:
@Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public Validator getValidator(); { // return "global" validator } }
在XML中:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <mvc:annotation-driven validator="globalValidator"/> </beans>
官方文档链接:
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-config