• @EnableWebMvc


    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。

    它还启用了如下内容:

    1. Spring 3 风格的类型转换 -- 通过一个ConversionService 实例 配合JavaBean PropertyEditors,用于Data Binding。
    2. 支持@NumberFormat注解通过ConversionService 来格式化Number字段。
    3. 支持使用@DateTimeFormat注解来格式化Date、Calendar、Long、以及Joda Time字段。
    4. 支持使用@Valid校验@Controller input -- 如果classpath中存在一个JSR-303 Provider。
    5. HttpMessageConverter支持@RequestMapping或@ExceptionHandler method的 @RequestBody method parameters和@ResponseBody method 返回值。 -- 比较长,其实就是支持handler (controller)的@RequestBody参数/@ResponseBody返回值。

    下面是<mvc:annotation-driven> 设置的完整的HttpMessageConverter列表:

    1. ByteArrayHttpMessageConverter converts byte arrays.
    2. StringHttpMessageConverter converts strings.
    3. ResourceHttpMessageConverter converts to/from org.springframework.core.io.Resource for all media types.
    4. SourceHttpMessageConverter converts to/from a javax.xml.transform.Source.
    5. FormHttpMessageConverter converts form data to/from a MultiValueMap<String, String>.
    6. Jaxb2RootElementHttpMessageConverter converts Java objects to/from XML — added if JAXB2 is present and Jackson 2 XML extension is not present on the classpath.
    7. MappingJackson2HttpMessageConverter converts to/from JSON — added if Jackson 2 is present on the classpath.
    8. MappingJackson2XmlHttpMessageConverter converts to/from XML — added if Jackson 2 XML extension is present on the classpath.
    9. AtomFeedHttpMessageConverter converts Atom feeds — added if Rome is present on the classpath.
    10. 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:

    1. DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES is disabled.
    2. MapperFeature.DEFAULT_VIEW_INCLUSION is disabled.

    它还自动注册了下列很有名的模块 -- 如果能够在classpath中检测到的话:

    1. jackson-datatype-jdk7: support for Java 7 types like java.nio.file.Path.
    2. jackson-datatype-joda: support for Joda-Time types.
    3. jackson-datatype-jsr310: support for Java 8 Date & Time API types.
    4. 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 来为MappingJackson2HttpMessageConverterMappingJackson2XmlHttpMessageConverter创建一个通用的配置,该配置:支持缩进、自定义的日期格式‘jackson-module-parameter-names的注册(会添加访问parameter names的支持 -- Java 8中的功能)。

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

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

    1. jackson-datatype-money: support for javax.money types (unofficial module)
    2. 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定义。

  • 相关阅读:
    浅谈JS严格模式
    浅谈自记忆函数
    浅谈padding
    JS在if中的强制类型转换
    JS正则表达式从入门到入土(10)—— 字符串对象方法
    JS正则表达式从入门到入土(9)—— test方法以及它的那些坑
    JS正则表达式从入门到入土(8)—— REGEXP对象属性
    从零开始的vue学习笔记(四)
    从零开始的vue学习笔记(三)
    从零开始的vue学习笔记(二)
  • 原文地址:https://www.cnblogs.com/duanxz/p/4875153.html
Copyright © 2020-2023  润新知