SpringMVC(18) - 配置SpringMVC

参考:https://docs.spring.io/spring/docs/4.3.20.RELEASE/spring-framework-reference/htmlsingle/#mvc-config

本节中了解配置Spring MVC的另外两种方法:MVC Java配置和MVC XML命名空间。

MVC Java配置和MVC命名空间提供类似的默认配置,它会覆盖DispatcherServlet的默认值。目标是使大多数应用程序不必创建相同的配置,并提供更高级别的构造,用于配置Spring MVC,作为一个简单的起点,并且需要很少或根本不需要基础配置的知识。

可以根据自己的喜好选择MVC Java配置或MVC命名空间。另外,正如将在下面看到的,使用MVC Java配置,更容易看到底层配置,以及直接对创建的Spring MVC bean进行细粒度的自定义。

1. 启用MVC Java Config或MVC XML命名空间
要启用MVC Java配置,请将注解@EnableWebMvc添加到@Configuration类之一:

@Configuration
@EnableWebMvc
public class WebConfig {
}

要在XML中实现相同的功能,请在DispatcherServlet上下文中使用<mvc:annotation-driven>元素(如果未定义DispatcherServlet上下文,则在根上下文中使用):

<?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(以及其他),以支持使用带注释的控制器方法处理请求,例如@RequestMapping,@ ExceptionHandler等注解。

它还可以实现以下功能:

  1. 除了用于数据绑定的JavaBeans PropertyEditors之外,还通过ConversionService实例进行Spring 3样式类型转换。
  2. 支持通过ConversionService使用@NumberFormat注解格式化数字字段。
  3. 支持使用@DateTimeFormat注解格式化Date、Calendar、Long和Joda-Time字段。
  4. 如果类路径中存在JSR-303实现,则支持使用@Valid验证@Controller输入。
  5. HttpMessageConverter支持@RequestBody方法参数和@RequestMapping或@ExceptionHandler方法上@ResponseBody注释的方法的返回值。

由mvc:annotation-driven设置的HttpMessageConverters的完整列表:

  • a. ByteArrayHttpMessageConverter:转换字节数组。
  • b. StringHttpMessageConverter:转换字符串。
  • c. ResourceHttpMessageConverter:为所有媒体类型从org.springframework.core.io.Resource转换或转换为org.springframework.core.io.Resource。
  • d. SourceHttpMessageConverter:从javax.xml.transform.Source转换或转换为javax.xml.transform.Source
  • e. FormHttpMessageConverter:将表单数据从MultiValueMap<String, String>转换或转换为MultiValueMap<String, String>。
  • f. Jaxb2RootElementHttpMessageConverter:将Java对象转换为XML或从XML转换 - 如果存在JAXB2且类路径中不存在Jackson 2 XML扩展,则添加。
  • g. MappingJackson2HttpMessageConverter:转换为JSON转换或从JSON转换 - 如果类路径中存在Jackson 2,则添加。
  • h. MappingJackson2XmlHttpMessageConverter:转换为XML或从XML转换 - 如果类路径中存在Jackson 2 XML扩展,则添加。
  • i. AtomFeedHttpMessageConverter:转换Atom提要 - 如果类路径中存在Rome,则添加。
  • j. RssChannelHttpMessageConverter:转换RSS提要 - 如果类路径中存在Rome,则添加RSS提要。

注:

Jackson JSON和XML转换器是使用Jackson2ObjectMapperBuilder创建的ObjectMapper实例创建的,以便提供更好的默认配置。

此构建器使用以下方法自定义Jackson的默认属性:

  • DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES:已禁用。
  • MapperFeature.DEFAULT_VIEW_INCLUSION:已禁用。

如果在类路径中检测到它们,它还会自动注册以下模块:

  • jackson-datatype-jdk7:支持Java 7类型,如java.nio.file.Path。
  • jackson-datatype-joda:支持Joda-Time类型。
  • jackson-datatype-jsr310:支持Java 8 Date&Time API类型。
  • jackson-datatype-jdk8:支持其他Java 8类型,如Optional。

2. 自定义提供的配置
要在Java中自定义默认配置,只需实现WebMvcConfigurer接口,或者更可能扩展WebMvcConfigurerAdapter类并覆盖需要的方法:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

    // 覆盖配置方法...
}

要自定义<mvc:annotation-driven />的默认配置,请检查它支持的属性和子元素。 可以查看Spring MVC XML架构或使用IDE的代码完成功能来发现可用的属性和子元素。

3. 转换和格式化
默认情况下,会安装Number和Date类型的格式化程序,包括对@NumberFormat和@DateTimeFormat注解的支持。 如果类路径中存在Joda-Time,则还会安装对Joda-Time格式库的完全支持。 要注册自定义格式化程序和转换器,请覆盖addFormatters方法:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addFormatters(FormatterRegistry registry) {
        // ...
    }
}

在MVC命名空间中,添加<mvc:annotation-driven>时会应用相同的默认值。 要注册自定义格式化程序和转换器,只需提供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>

4. 校验
Spring提供了一个Validator接口,可用于在应用程序的所有层中进行验证。在Spring MVC中,可以将其配置为用作全局Validator实例,在遇到@Valid或@Validated控制器方法参数时使用,或通过@InitBinder方法在控制器中作为本地Validator使用。可以组合全局和本地验证器实例以提供复合验证。

Spring还通过LocalValidatorFactoryBean支持JSR-303/JSR-349 Bean验证,它使Spring org.springframework.validation.Validator接口适应Bean Validation javax.validation.Validator契约。如下所述,此类可以作为全局验证器插入Spring MVC。

默认情况下,当在类路径上检测到Bean验证提供程序(如Hibernate Validator)时,使用@EnableWebMvc或<mvc:annotation-driven>会自动在Spring MVC中通过LocalValidatorFactoryBean注册Bean Validation支持。

注:
有时将LocalValidatorFactoryBean注入控制器或其他类是很方便的。最简单的方法是声明自己的@Bean并使用@Primary标记它,以避免与MVC Java配置提供的冲突。

如果更喜欢使用MVC Java配置中的那个,则需要从WebMvcConfigurationSupport覆盖mvcValidator方法,并声明该方法显式返回LocalValidatorFactory而不是Validator。

或者,可以配置自己的全局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>

要将全局校验与本地校验相结合,只需添加一个或多个本地校验器:

@Controller
public class MyController {

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

}

使用此最小配置,只要遇到@Valid或@Validated方法参数,它将由配置的验证器进行验证。 任何验证违规都将自动暴露为BindingResult中的错误,可作为方法参数访问,也可在Spring MVC HTML视图中呈现。

5. 拦截器
可以配置HandlerInterceptors或WebRequestInterceptors,然后将它们应用到所有传入的请求或限制为特定URL路径模式。

在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如何根据请求确定所请求的媒体类型。 可用选项是检查URL路径获取文件扩展名,检查“Accept”头,特定查询参数,或在没有请求任何内容时回退到默认内容类型。 默认情况下,首先检查请求URI中的路径扩展,然后检查“Accept”头。

如果相应的依赖项在类路径上,则MVC Java配置和MVC命名空间默认注册json,xml,rss,atom。 还可以明确地注册附加的路径媒体扩展到类型映射,并且还具有将它们列为白名单以将其作为用于RFD攻击检测的安全扩展的效果。

以下是通过MVC Java配置自定义内容协商选项的示例:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

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

在MVC命名空间中,<mvc:annotation-driven>元素具有content-negotiation-manager属性,该属性需要ContentNegotiationManager,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配置或MVC命名空间,则需要创建ContentNegotiationManager的实例并使用它来配置RequestMappingHandlerMapping以进行请求映射,并使用RequestMappingHandlerAdapter和ExceptionHandlerExceptionResolver进行内容协商。

提示:ContentNegotiatingViewResolver也可以使用ContentNegotiationManager进行配置,因此可以在Spring MVC中使用一个共享实例。

在更高级的情况下,配置多个ContentNegotiationManager实例可能会很有用,而这些实例又可能包含自定义ContentNegotiationStrategy实现。例如,可以使用ContentNegotiationManager配置ExceptionHandlerExceptionResolver,它始终将请求的媒体类型解析为“application/json”。或者,如果没有请求内容类型,可能希望插入具有某种逻辑的自定义策略来选择默认内容类型(例如XML或JSON)。

7. 视图控制器
这是定义ParameterizableViewController的快捷方式,该方法在调用时立即转发到视图。在视图生成响应之前,如果没有要执行的Java控制器逻辑,请在静态情况下使用它。

将对“/”的请求转发到Java中名为“home”的视图的示例:

@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. 视图解析器
MVC配置简化了视图解析器的注册。

以下是使用FreeMarker HTML模板配置内容协商视图解析的Java配置示例,以及Jackson作为JSON渲染的默认视图:

@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和script 模板也需要配置底层视图技术。

MVC名称空间提供专用元素。 例如使用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配置中,只需添加相应的“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. 资源服务
此选项允许ResourceHttpRequestHandler从任何资源位置列表中为特定URL模式的静态资源请求提供服务。 这提供了一种方便的方法来从Web应用程序根目录以外的位置提供静态资源,包括类路径上的位置。 cache-period属性可用于设置头部到期时间(Page Speed和YSlow等优化工具推荐1年),以便客户端更有效地使用它们。 处理器还正确地评估Last-Modified头(如果存在),以便适当地返回304状态代码,从而避免对于客户端已缓存的资源的不必要开销。 例如,要从Web应用程序根目录中的公共资源目录提供URL模式为/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/"/>

要在一年到期时提供这些资源,以确保最大限度地使用浏览器缓存并减少浏览器发出的HTTP请求:

@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"/>

有关更多详细信息,请参阅静态资源的HTTP缓存支持。

  • mapping属性必须是SimpleUrlHandlerMapping可以使用的Ant模式,
  • location属性必须指定一个或多个有效的资源目录位置。 可以使用逗号分隔的值列表指定多个资源位置。 将按指定的顺序检查指定的位置是否存在任何给定请求的资源。 例如,要启用来自Web应用程序根目录和来自类路径上任何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/"/>

在提供可能在部署新版本的应用程序时更改的资源时,建议将版本字符串合并到用于请求资源的映射模式中,以便可以强制客户端请求新部署的应用程序资源版本。对版本化URL的支持已经内置于框架中,可以通过在资源处理器上配置资源链来启用。该链包含一个ResourceResolver实例,后跟一个或多个ResourceTransformer实例。它们可以一起提供任意解析和资源转换。

可以使用不同的策略配置内置的VersionResourceResolver。例如,FixedVersionStrategy可以使用属性,日期或其他作为版本。 ContentVersionStrategy使用根据资源内容计算的MD5哈希值(称为“指纹识别”URL)。请注意,VersionResourceResolver在提供资源时会自动将已解析的版本字符串用作HTTP ETag头值。

ContentVersionStrategy是一个很好的默认选择,除非它无法使用(例如使用JavaScript模块加载器)。可以针对不同的模式配置不同的版本策略,如下所示。还要记住,基于计算内容的版本很昂贵,因此应该在生产中启用资源链缓存。

Java配置示例;

@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>

为了使上述工作正常,应用程序还必须使用版本展示URL。最简单的方法是配置ResourceUrlEncodingFilter,它包装响应并覆盖其encodeURL方法。这将适用于JSP,FreeMarker,Velocity以及调用响应encodeURL方法的任何其他视图技术。或者,应用程序也可以直接注入和使用ResourceUrlProvider bean,它使用MVC Java配置和MVC命名空间自动声明。

WebJarsResourceResolver也支持Webjars,当"org.webjars:webjars-locator"库在classpath上时会自动注册。此解析器允许资源链从HTTP GET请求解析版本无关的库“GET /jquery/jquery.min.js”将返回资源“/jquery/1.2.0/jquery.min.js”。它还可以通过在模板中重写资源URL<script src="/jquery/jquery.min.js"/> -> <script src="/jquery/1.2.0/jquery.min.js”/>来工作。

10. 默认Servlet
这允许将DispatcherServlet映射到"/"(从而覆盖容器的默认Servlet的映射),同时仍允许容器的默认Servlet处理静态资源请求。它配置DefaultServletHttpRequestHandler,其URL映射为“/**”,并且相对于其他URL映射具有最低优先级。

此处理器将所有请求转发到默认Servlet。因此,重要的是它在所有URL HandlerMapping中顺序保持最后。如果使用<mvc:annotation-driven>,或者如果要设置自己的自定义HandlerMapping实例,请确保将其order属性设置为低于DefaultServletHttpRequestHandler(Integer.MAX_VALUE)的值。

要使用默认设置启用该功能,请使用:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

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

或者用XML:

<mvc:default-servlet-handler/>

覆盖"/"Servlet映射需要注意的是,必须通过名称而不是路径来检索默认Servlet的RequestDispatcher。 DefaultServletHttpRequestHandler将尝试使用大多数主要Servlet容器(包括Tomcat,Jetty,GlassFish,JBoss,Resin,WebLogic和WebSphere)的已知名称列表,在启动时自动检测容器的默认Servlet。 如果使用不同的名称自定义配置了默认Servlet,或者在默认Servlet名称未知的情况下使用了不同的Servlet容器,则必须显式提供默认的Servlet名称,如下例所示:

@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. 路径匹配
这允许自定义与URL映射和路径匹配相关的各种设置。 有关各个选项的详细信息,请查看PathMatchConfigurer API。

以下是Java配置中的示例:

@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. 消息转换器
如果想要替换Spring MVC创建的默认转换器,或者如果只想自定义它们或者将其他转换器添加到默认转换器中,则可以通过覆盖configureMessageConverters()来实现HttpMessageConverter的自定义。

下面是一个示例,它使用自定义的ObjectMapper而不是默认的ObjectMapper添加Jackson JSON和XML转换器:

@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-parameters-names的注册,增加了对访问参数名称的支持(Java 8中添加的功能)。
注:使用Jackson XML支持启用缩进除了jackson-dataformat-xml之外还需要woodstox-core-asl依赖。

其他可用的Jackson模块:

  • jackson-datatype-money:支持javax.money类型(非官方模块)
  • jackson-datatype-hibernate:支持Hibernate特定的类型和属性(包括延迟加载方面)

也可以在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配置进行高级自定义
从上面的示例中可以看出,MVC Java配置和MVC命名空间提供了更高级别的构造,这些构造不需要深入了解创建的底层bean。相反,它可以帮助我们专注于应用程序需求。但是,在某些时候可能需要更细粒度的控制,或者可能只是希望了解底层配置。

实现更细粒度控制的第一步是查看创建的基础bean。在MVC Java配置中,可以在WebMvcConfigurationSupport中看到javadoc和@Bean方法。此类中的配置将通过@EnableWebMvc注解自动导入。实际上,如果打开@EnableWebMvc,可以看到@Import语句。

更精细控制的下一步是在WebMvcConfigurationSupport中创建的bean之一上自定义属性,或者提供自己的实例。这需要两件事:

  • 删除@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注释类,因为它们都注册相同的底层bean。

以这种方式修改bean不会阻止您使用本节前面所示的任何更高级别的构造。 WebMvcConfigurerAdapter子类和WebMvcConfigurer实现仍在使用中。

14. 使用MVC命名空间进行高级自定义
使用MVC命名空间对创建的配置进行细粒度控制会有点困难。

如果确实需要这样做,而不是复制它提供的配置,请考虑配置BeanPostProcessor,以检测要按类型自定义的bean,然后根据需要修改其属性。 例如:

@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声明显式声明它。

猜你喜欢

转载自blog.csdn.net/mytt_10566/article/details/84205681