您的位置:首页 > 编程语言 > Java开发

Spring 4 官方文档学习(十一)Web MVC 框架之配置Spring MVC

2016-12-11 22:01 1016 查看
内容列表:

启用MVC Java config 或 MVC XML namespace

修改已提供的配置

类型转换和格式化

校验

拦截器

内容协商

View Controllers

View Resolvers

服务于资源

回滚到默认的Servlet

Path Matching - 路径匹配

Message Converters - 消息转换器

MVC Java config中的高级定制

MVC namespace中的高级定制

在前面的文档中讲解了Spring MVC的特殊beans,以及DispatcherServlet使用的默认实现。在本部分,你会学习两种额外的方式来配置Spring MVC。分别是:MVC Java configMVC 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中,需要在你的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/from
org.springframework.core.io.Resource
for all media types.

SourceHttpMessageConverter
converts to/from a
javax.xml.transform.Source
.

FormHttpMessageConverter
converts form data to/from a
MultiValueMap<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>


想要联合全局的和局部的validation,只需要简单地添加一个或多个local validator(s):

@Controller
public class MyController {

@InitBinder
protected void initBinder(WebDataBinder binder) {
binder.addValidators(new FooValidator());
}

}


使用这种最小化的配置,任何时间只要@Valid或@Validated method argument遇到了,就会被配置好的validators校验。任何校验都会自动的被暴露成BindingResult中的errors,可被方法参数访问,在Spring MVC HTML views中也是可渲染的。 -- 其实都是废话,就是说 method(..@Valid T t, BindingResult br)。

5、拦截器

HandlerInterceptor 或 WebRequestInterceptor,可被用于所有incoming requests 或 特定的URL path patterns。

Java形式注册拦截器:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LocaleInterceptor());
registry.addInterceptor(new ThemeInterceptor()).addPathPatterns("/**").excludePathPatterns("/admin/**");
registry.addInterceptor(new SecurityInterceptor()).addPathPatterns("/secure/*");
}

}


在XML中使用 <MVC:Interceptors> 元素:

<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"/>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/admin/**"/>
<bean class="org.springframework.web.servlet.theme.ThemeChangeInterceptor"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/secure/*"/>
<bean class="org.example.SecurityInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>


6、内容协商

你可以配置Spring MVC如何判断request中的请求媒体类型。可用的选项是:①检查URL路径中的文件扩展名,②检查Accept header,③特定的query parameter,④或回滚到默认的内容类型 -- 当什么都不请求时。 默认,先检查request URI中的扩展名,再检查Accept header。

MVC Java config和 MVC namespace 默认会注册 json、xml、rss、atom,前提是classpath中有相应的依赖。可以显式地注册额外的path extension-to-media类型映射。

下面是通过MVC Java config定制内容协商选项的例子:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.mediaType("json", MediaType.APPLICATION_JSON);
}
}


中MVC namespace中,<mvc:annotation-driven>元素有个 content-negotiation-manager attribute,它预期的是一个ContentNegotiationManager-- 可以使用ContentNegotiationManagerFactoryBean:

<mvc:annotation-driven content-negotiation-manager="contentNegotiationManager"/>

<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="mediaTypes">
<value>
json=application/json
xml=application/xml
</value>
</property>
</bean>


如果不使用MVC Java config 或 MVC namespace,你会需要创建一个ContentNegotiationManager实例,并用它来配置RequestMappingHandlerMapping -- 用于request mapping目的,以及配置RequestMappingHandlerAdapter 和 ExceptionHandlerExceptionResolver -- 用于内容协商目的。

注意,ContentNegotiatingViewResolver 现在也可以使用一个ContentNegotiationManager来配置,所以你可以使用一个共享的实例。

更多的情况下,配置多个ContentNegotiationManager实例(可能包含定制的ContentNegotiationStrategy实现)可能很有用。例如,你可以使用一个ContentNegotiationManager来配置ExceptionHandlerExceptionResolver,然后总是将请求的媒体类型处理成”application/json”。或者,你可能想插入一个定制的策略,如果没有内容类型被请求时,使用一些逻辑来选择默认的内容类型--如XML或JSON。

7、View Controllers

有一种简便的方式来定义一个ParameterizableViewController --当调用时会立即转发到一个view。一般用于静态案例。

例如,以Java形式将对”/”的请求转发至”home” view:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("home");
}

}


在XML中,可以使用<mvc:view-controller> 元素:

<mvc:view-controller path="/" view-name="home"/>


8、View Resolvers

MVC config 简化了view resolvers的注册。

下面是一个Java config示例,配置了内容协商视图解决方案使用FreeMarker HTML 模板,还配置了Jackson作为默认JSON View:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.enableContentNegotiation(new MappingJackson2JsonView());
registry.jsp();
}

}


在XML中:

<mvc:view-resolvers>
<mvc:content-negotiation>
<mvc:default-views>
<bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>
</mvc:default-views>
</mvc:content-negotiation>
<mvc:jsp/>
</mvc:view-resolvers>


注意:FreeMarker、Velocity、Tiles、Groovy Markup和脚本模板,同样要求配置底层的view 技术。

MVC namespace提供了专用的元素。 例如,针对FreeMarker:

<mvc:view-resolvers>
<mvc:content-negotiation>
<mvc:default-views>
<bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>
</mvc:default-views>
</mvc:content-negotiation>
<mvc:freemarker cache="false"/>
</mvc:view-resolvers>

<mvc:freemarker-configurer>
<mvc:template-loader-path location="/freemarker"/>
</mvc:freemarker-configurer>


在Java config中,只需要简单的添加相应的Configurer bean即可:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.enableContentNegotiation(new MappingJackson2JsonView());
registry.freeMarker().cache(false);
}

@Bean
public FreeMarkerConfigurer freeMarkerConfigurer() {
FreeMarkerConfigurer configurer = new FreeMarkerConfigurer();
configurer.setTemplateLoaderPath("/WEB-INF/");
return configurer;
}

}


9、服务于资源

该选项允许静态资源请求按照特定的URL pattern,由ResourceHttpRequestHandler来服务 -- 从Resource locations列表中的任意一个。这提供了一种便捷的方式来服务静态资源,不只是web app root的位置,还包括classpath (牛掰大了)。其cache-period property可以被用来设置失效headers (对于Page Speed and YSlow等工具来说,推荐设为1年),这样它们会被client更有效的使用。handler还会正确的evaluate Last-Modified header (如果有) -- 并在恰当的时候返回 304 status code,这样会避免不必要的重复资源获取。例如,想要使用 /resources/** 形式的URL pattern来请求 web root 下public-resources 文件夹中内容,你可以这样做:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/public-resources/");
}

}


或者在XML中:

<mvc:resources mapping="/resources/**" location="/public-resources/"/>


设定 1年有效期:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/public-resources/").setCachePeriod(31556926);
}

}


XML中:

<mvc:resources mapping="/resources/**" location="/public-resources/" cache-period="31556926"/>


更多详见 Spring 4 官方文档学习(十一)Web MVC 框架之HTTP caching support

注意:mapping attribute 必须是一个Ant 模式的,这样才能被SimpleUrlHandlerMapping使用;location attribute 必须指定一个或多个有效的资源目录。 多个资源位置可以使用逗号间隔。指定的位置会按照指定的顺序被检查。例如,想要同时支持 web root 和classpath中任何jar中的 /META-INF/public-web-resources/ 路径,可以这样:

@EnableWebMvc
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/", "classpath:/META-INF/public-web-resources/");
}

}


在XML中:

<mvc:resources mapping="/resources/**" location="/, classpath:/META-INF/public-web-resources/"/>


当资源可能随着新版本的部署而发生改变时,建议在请求资源的mapping pattern中加入一个版本字符串,这样你可以强制客户端请求新部署版本的资源。 框架天然支持带版本的URLs,且可以通过配置resource handler的resource chain来启用。该chain由一个或多个ResourceResolver实例(伴有一个或多个ResourceTransformer实例)组成。它们一起可以为资源提供任意的resolution和transformation。

内置的VersionResourceResolver,可以被配置不同的策略。例如,一个FixedVersionStrategy可以使用一个property、一个date,或其他作为版本。一个ContentVersionStrategy 使用根据资源内容计算的MD5 hash(也被叫做fingerprinting URLs)作为版本。 注意,VersionResourceResolver会自动使用resolved version strings作为 HTTP ETag header的值。

ContentVersionStrategy是一个很好的默认选择,除非不能使用 (例如,当使用JavaScript 模块加载器时)。 你可以配置不同的版本策略。务必记住,基于内容计算的版本是很耗费系统资源的,因此,在生产模型中应该启用resource chain 缓存。

Java config 例子:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/public-resources/")
.resourceChain(true).addResolver(
new VersionResourceResolver().addContentVersionStrategy("/**"));
}

}


XML例子:

<mvc:resources mapping="/resources/**" location="/public-resources/">
<mvc:resource-chain>
<mvc:resource-cache/>
<mvc:resolvers>
<mvc:version-resolver>
<mvc:content-version-strategy patterns="/**"/>
</mvc:version-resolver>
</mvc:resolvers>
</mvc:resource-chain>
</mvc:resources>


为了让上面的内容正常工作,应用必须在URLs中带有版本。 最简单的方式就是配置一个ResourceUrlEncodingFilter,它封装了response,并重写了其encodeURL method。在JSPs、FreeMarker、Velocity、和任何调用response encodeURL method的其他view技术中,都可以工作。或者,一个应用也可以注入和直接使用 ResourceUrlProvider bean,MVC Java config 和 MVC namespace会自动声明它。

Webjars are also supported with
WebJarsResourceResolver
, which is automatically registered when the
"org.webjars:webjars-locator"
library is on classpath. This resolver allows the resource chain to resolve version agnostic libraries from HTTP GET requests
"GET /jquery/jquery.min.js"
will return resource
"/jquery/1.2.0/jquery.min.js"
. It also works by rewriting resource URLs in templates
<script src="/jquery/jquery.min.js"/> → <script src="/jquery/1.2.0/jquery.min.js"/>
.

10、回滚到默认的Servlet

这允许将 DispatcherServlet 映射到 “/”(因此,覆盖了容器的default Servlet的映射),同时,仍然允许容器的default Servlet来处理静态资源请求。它配置了一个DefaultServletHttpRequestHandler,并映射到 “/**”,该映射具有最低的优先级。

该Handler 会将所有请求转发给default Servlet。因此,它在所有其他URL HandlerMappings中排名最后很重要(就是必须放在最后的意思)。当你使用<mvc:annotation-driven> 或 当你在设置你自己定制的HandlerMapping实例时,其order property的值应比DefaultServletHttpRequestHandler的值小,嗯嗯,后者是
Integer.MAX_VALUE


To enable the feature using the default setup use:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}

}


或者,在XML中:

<mvc:default-servlet-handler/>


针对覆盖 “/” Servlet mapping的警告是:default Servlet 的 RequestDispatcher 必须通过name来获取,而非通过path。DefaultServletHttpRequestHandler 会在Servlet容器启动时试图自动探测其default Servlet -- 使用一个包含大多数已知Servlet容器的name列表(包括Tomcat、Jetty、GlassFish、JBoss、Resin、WebLogic、WebSphere) 。 如果default Servlet已经被配置了不同的name,或者如果使用了一个不同的Servlet容器(不知其default Servlet name),那么必须按照如下方式来提供default Servlet name:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable("myCustomDefaultServlet");
}

}


或者在XML中:

<mvc:default-servlet-handler default-servlet-name="myCustomDefaultServlet"/>


11、Path Matching - 路径匹配

这里允许针对URL mapping和path matching 自定义不同的设置。 针对每个选项的详细信息,请检查PathMatchConfigurer API。

下面是一个Java config例子:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer
.setUseSuffixPatternMatch(true)
.setUseTrailingSlashMatch(false)
.setUseRegisteredSuffixPatternMatch(true)
.setPathMatcher(antPathMatcher())
.setUrlPathHelper(urlPathHelper());
}

@Bean
public UrlPathHelper urlPathHelper() {
//...
}

@Bean
public PathMatcher antPathMatcher() {
//...
}

}


或在XML中使用<mvc:path-matching> 元素:

<mvc:annotation-driven>
<mvc:path-matching
suffix-pattern="true"
trailing-slash="false"
registered-suffixes-only="true"
path-helper="pathHelper"
path-matcher="pathMatcher"/>
</mvc:annotation-driven>

<bean id="pathHelper" class="org.example.app.MyPathHelper"/>
<bean id="pathMatcher" class="org.example.app.MyPathMatcher"/>


12、Message Converters - 消息转换器

针对HttpMessageConverter的定制,可以通过重写configureMessageConverters() 或重写extendMessageConverters()来实现,二者不同之处在于:前者会取代Spring MVC创建的默认转换器,后者则是添加额外的转换器。(个人推荐后者)

下面是一个取代默认设置的例子:

@Configuration
@EnableWebMvc
public class WebConfiguration extends WebMvcConfigurerAdapter {

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder()
.indentOutput(true)
.dateFormat(new SimpleDateFormat("yyyy-MM-dd"))
.modulesToInstall(new ParameterNamesModule());
converters.add(new MappingJackson2HttpMessageConverter(builder.build()));
converters.add(new MappingJackson2XmlHttpMessageConverter(builder.xml().build()));
}

}


在该例子中,使用
Jackson2ObjectMapperBuilder
来为
MappingJackson2HttpMessageConverter
MappingJackson2XmlHttpMessageConverter
创建一个通用的配置,该配置:支持缩进、自定义的日期格式‘jackson-module-parameter-names的注册(会添加访问parameter names的支持 -- Java 8中的功能)。


启用Jackson XML的缩进支持,需要jaskson-dataformat-xml 还有 woodstox-core-asl 依赖。


其他有趣的可用Jackson模块包括:

jackson-datatype-money: support for
javax.money
types (unofficial module)

jackson-datatype-hibernate: support for Hibernate specific types and properties (including lazy-loading aspects)

在XML中:

<mvc:annotation-driven>
<mvc:message-converters>
<bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="objectMapper"/>
</bean>
<bean class="org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter">
<property name="objectMapper" ref="xmlMapper"/>
</bean>
</mvc:message-converters>
</mvc:annotation-driven>

<bean id="objectMapper" class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean"
p:indentOutput="true"
p:simpleDateFormat="yyyy-MM-dd"
p:modulesToInstall="com.fasterxml.jackson.module.paramnames.ParameterNamesModule"/>

<bean id="xmlMapper" parent="objectMapper" p:createXmlMapper="true"/>


13、MVC Java config中的高级定制

如果你在前面的例子中看到的一样,MVC Java config 和 MVC namespace 都提供了高级别的指令 -- 不需要高深的底层知识。相反,它会帮助你将精力放在应用上面。然而,某些时候你的确可能需要更细化的控制,或者你只是简单地想理解底层的配置。

迈向更细化的控制的第一步,就是查看底层的beans。在MVC Java config 中你可以看到javadocs 和 WebMvcConfigurationSupport中的@Bean methods。 通过@EnableWebMvc注解,可以自动导入该类中的配置。 事实上,你点开@EnableWebMvc 就可以看到 @Import语句。

第二步就是自定义下WebMvcConfigurationSupport创建的某个bean的一个property,或者,干脆提供你自己的实例。这需要两件事情:移除@EnableWebMvc注解,以阻止导入,然后继承DelegatingWebMvcConfiguration -- 它是WebMvcConfigurationSupport的一个子类。 见下面的例子:

@Configuration
public class WebConfig extends DelegatingWebMvcConfiguration {

@Override
public void addInterceptors(InterceptorRegistry registry){
// ...
}

@Override
@Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
// Create or let "super" create the adapter
// Then customize one of its properties
}

}



一个应用应该只有一个继承自DelegatingWebMVCConfiguration的配置 或 单一的@EnableWebMvc class, 因为它们会注册相同的底层beans。

以这种方式修改beans,不会阻止你使用任何更高级别的方式 -- 就是前面讲述的那些方式。WebMvcConfigurerAdapter的子类们和WebMvcConfigurer实现们 仍然被使用。



14、MVC namespace中的高级定制

好吧,MVC namespace中更细化的控制有点麻烦。

建议配置一个 BeanPostProcessor,用它来侦探你想定制的bean,然后修改器properties即可。例如:

@Component
public class MyPostProcessor implements BeanPostProcessor {

public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
if (bean instanceof RequestMappingHandlerAdapter) {
// Modify properties of the adapter
}
}

}


这里要注意,MyPostProcessor 需要被包含在一个 <component scan/>中,这样能够自动被侦测到。或者,如果你喜欢,也可以将其显式地声明为一个XML bean定义。

官方文档链接:

http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-config
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: