Spring Web MVC框架(八) 配置Spring Web MVC

这一篇文章对应于Spring参考文档 Configuring Spring MVC,讲的是Spring Web MVC各部分的配置方法,包括Java代码配置和XML文件配置以及MVC命名空间的使用方法。

启用MVC Java配置和XML命名空间

默认配置

要启用MVC Java配置(@Controller等各种注解)和XML命名空间,如果使用的是Java配置,在配置类上再添加@EnableWebMvc注解即可。

@Configuration
@EnableWebMvc
public class WebAppConfig {

}

如果使用XML配置文件的话,添加下面一行即可。

<mvc:annotation-driven/>

不论使用哪种方式,都会在Spring中注册一些组件来提供最基本的MVC功能。这些功能在文档中说的很清楚。我简单翻译了一下:

上面的配置会注册一个RequestMappingHandlerMapping,一个RequestMappingHandlerAdapter和一个ExceptionHandlerExceptionResolver来提供注解控制器和注解方法(比如@RequestMapping和@ExceptionHandler等)处理请求的功能。

还会启用以下功能:

  • 通过一个ConversionService实例,来进行Spring 3 方式的类型转换及数据绑定支持。
  • @NumberFormat格式化数字字段的支持
  • @DateTimeFormat格式化DateCalendarLong、JodaTime类型字段的支持。
  • 在控制器方法上使用@Valid验证Bean的支持,如果检测到JSR-303 Bean验证的实现。
  • 一组HttpMessageConverter,用于在字符串和所需Java类型之间进行类型转换,具体的列表参见Spring文档 22.16.1. Enabling the MVC Java Config or the MVC XML Namespace

通过这些默认配置,我们即可开始最基本的Spring MVC使用。

自定义配置

上面提供了最基本的配置。如果需要自定义某些配置也可以。如果使用Java配置的话,让配置类实现WebMvcConfigurer接口,更常用的办法是继承WebMvcConfigurerAdapter基类,通过重写基类中的方法即可配置相关功能。

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

        //有很多个方法可以重写,来提供自定义功能

}

如果使用XML配置文件,通过IDE的自动补全功能查看一下<mvc:annotation-driven/>有哪些子属性和子元素。

类型转换和格式化

默认情况下Spring注册了Number(包括所有基本数字类型)和java.util.Date的类型转换和格式化功能。要提供类型的转换和格式化功能,就需要自己注册相应的类型转换器和格式化器。

如果使用Java配置的话,重写addFormatters(FormatterRegistry registry)方法并添加相应功能即可。

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addFormatters(FormatterRegistry registry) {
        // Add formatters and/or converters
    }

}

如果使用XML配置的话,需要注册一个ConversionService,然后添加到<mvc:annotation-driven>节点中。

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

验证功能

Spring自己提供了一组接口和类提供了一套验证功能。不过更通用的方法是使用Bean Validation进行Java对象的验证,Bean Validation的一个实现就是Hibernate Validator。如果想简单了解一下Hibernate Validator,可以看一下我的文章Hibernate Validator简介。如果需要详细使用方法请查看相关文档博客。

默认情况下当@EnableWebMvc<mvc:annotation-driven/>配置之后,如果Spring检测到Bean Validation,就会自动注册一个LocalValidatorFactoryBean来提供验证功能。如果我们希望手动处理验证过程,可能希望将验证器实例注入到控制器中,这时候就不能使用自动注册的LocalValidatorFactoryBean了。这时候我们可以选择手动注册一个LocalValidatorFactoryBeanBean实例,然后注解@Primary让自定义LocalValidatorFactoryBean被优先使用。

还有一种办法就是直接覆盖Spring的默认验证器配置。如果使用Java配置的话,重写getValidator()方法即可。

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public Validator getValidator() {
        // return "global" validator
    }

}

如果使用XML配置文件,定义一个Validator然后添加到<mvc:annotation-driven>中。

<mvc:annotation-driven validator="globalValidator"/>

上面定义的都是全局验证器,我们也可以在某个控制器中定义一个局部验证器,然后和全局验证器结合起来使用。这时候需要使用@InitBinder注解方法。

@Controller
public class MyController {

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

}

配置好验证器之后。当Spring识别到@Valid注解的方法参数之后,就会执行验证,将验证结果绑定到BindingResult上,我们可以在方法中访问BindingResult来获取验证结果。

拦截器

我们实现了拦截器之后,就可以将其应用到Web程序中。使用Java配置的话,重写addInterceptors(InterceptorRegistry registry)方法,然后在其中添加自己的拦截器即可。如果要配置拦截路径和排除路径也可以在这里配置。

@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命名空间,配置也比较简单。

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

视图控制器

这是一种定义ParameterizableViewController的简单方式,当该控制器被请求的时候不会执行任何逻辑操作,直接转到相应视图。视图控制器的常见用法是将网站的首页直接和/请求映射。

使用Java配置可以这样写,下面的配置将/映射到名为index的视图。

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

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

}

使用XML配置也很简单。

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

视图解析器

使用Java配置,只需要重写configureViewResolvers(ViewResolverRegistry registry)方法即可。下面配置了JSP视图。如果需要其它视图解析器可以参见其相应文档,以及ViewResolverRegistry的JavaDoc。

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.enableContentNegotiation(new MappingJackson2JsonView());
        registry.jsp()
                .prefix("/WEB-INF/jsp/")
                .suffix(".jsp")
                .viewClass(JstlView.class);
    }

}

如果使用XML配置文件可以使用MVC命名空间简化配置。除了内置的JSP解析器外,其它视图解析器可能还需要额外的配置,这里不再细述。

<mvc:view-resolvers>
    <mvc:jsp prefix="/WEB-INF/jsp/"
             suffix=".jsp"
             view-class="org.springframework.web.servlet.view.JstlView"/>
</mvc:view-resolvers>

资源处理

静态资源处理

这里说的主要是静态资源的处理。前面说了很多关于控制器、视图的知识,但是如何映射CSS、JS文件,前面没有说明。配置方法在这里说明。

使用Java配置的话,重写addResourceHandlers(ResourceHandlerRegistry registry)方法,然后添加相应的映射即可。

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

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

}

使用XML配置文件 也同样简单。

<mvc:resources mapping="/resources/static/**" location="/static/"/>

这样映射之后,假如我们有/resources/static/bootstrap.css文件,那么就可以使用/static/bootstrap.css路径来访问该文件了。同样的在视图文件中也可以如此引用。还可以使用cache-period设置资源的过期时间,单位是秒。如果需要指定多个资源位置,可以使用逗号分隔。

资源的版本控制

有些频繁更新的资源可能需要版本控制,强制让客户端使用最新的资源。Spring框架也支持资源的版本控制,我们需要定义资源链来实现这个功能。资源链由一个ResourceResolver实例和多个ResourceTransformer实例组成。内建的VersionResourceResolver能满足我们的大部分需求,它可以定义一些策略来配置版本控制,例如FixedVersionStrategy会依据日期、版本号或者其他东西作为版本;ContentVersionStrategy会计算资源的MD5值。

ContentVersionStrategy策略是一个不错的策略,不过由于它会计算MD5,所以开销比较大, 因此在使用这种策略的时候最好打开缓存来提高性能。

如果使用Java配置的话,和前面的例子差不多,只不过需要多调用resourceChain(true)等方法并添加相应的版本资源解析器和版本策略。

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/static/**")
                .addResourceLocations("/static/")
                .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>

默认Servlet

开启这个选项可以让DispatcherServlet能映射根路径/的同时,允许Servlet容器的默认Servlet处理静态资源请求。这个配置项实际上会配置一个DefaultServletHttpRequestHandler,映射到路径/**,并具有最低的优先级。由于DefaultServletHttpRequestHandler会将所有请求转发到默认Servlet,所以它必须被配置为最后一个处理映射才行。

使用Java配置的话,重写configureDefaultServletHandling(...)方法并开启该选项。

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

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

}

如果使用XML配置的话,添加以下行。

<mvc:default-servlet-handler/>

消息转换

如果我们需要覆盖Spring默认的消息转换器,可以重写configureMessageConverters(List<HttpMessageConverter<?>> converters)方法,然后向converters参数添加我们自己的消息转换器。如果仅仅希望增加自己的类型转换器,重写extendMessageConverters()方法。

使用XML配置文件的话,可以使用MVC命名空间。

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

高级自定义配置

上面的配置使用Spring提供的简化类或者MVC命名空间,帮助我们快速配置功能。有时候可能需要更高级的功能定制,这样就需要自己处理这些底层Bean的初始化和属性设置。

Java配置自定义

我们先来看一看@EnableWebMvc注解的定义。可以看到它还使用了一个@Import注解,引用了DelegatingWebMvcConfiguration类。当我们注解@EnableWebMvc的时候,实际上初始化和配置的底层类就是DelegatingWebMvcConfiguration

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}

因此我们如果要自定义MVC的话,第一件事就是移除注解@EnableWebMvc。然后继承DelegatingWebMvcConfiguration类并实现它的requestMappingHandlerAdapter()方法。

@Configuration
public class WebConfig extends DelegatingWebMvcConfiguration {

    @Override
    @Bean
    public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
        // 在这里进行高级配置
    }

}

在项目中DelegatingWebMvcConfiguration子类和@EnableWebMvc注解配置类只能存在一个,因为它们做的事情实际上是一样的。而且这里的配置并不影响Spring MVC的其他配置。

自定义MVC命名空间配置

这里的自定义配置更困难,因为Spring没有提供相应的配置机制。如果实在需要自定义MVC命名空间配置,可以考虑使用Spring提供的BeanPostProcessor机制,在检测到Bean之后修改它的值。

@Component
public class MyPostProcessor implements BeanPostProcessor {

    public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException {
        if (bean instanceof RequestMappingHandlerAdapter) {
            // 在这里自定义属性
        }
    }

}
时间: 2024-10-14 05:31:10

Spring Web MVC框架(八) 配置Spring Web MVC的相关文章

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

在前面的文档中讲解了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 DispatcherSer

Spring MVC全注解配置 - 无web.xml

Serlvet 3以后,我们可以使用注解来配置Servlet,对于像Spring这类的框架来说是一个很好的适应.Spring也对此特性加入了很多的新功能.本文就将简单的对之前的xml配置转换为java代码的配置.代码配置让程序员们觉得更加具有流程化,不像配置很多代码程序员们都不愿意look into. 接下来,进行替换我们之前的web.xml和spring-mvc.xml的配置.也就是在你的web工程里面看不到这两个配置文件了.(可能有的童鞋会说,这样配置可能对以后的修改不方便,无法达到只修改配

从零开始写C# MVC框架之--- 配置log4日志

在框架中配置日志分2步,一个是在帮助项目Zy.Utilities--Zy.Utility.Core中新建log类,封装写入日志方法,还需要在Zy.Utility.Core添加 log4net 的引用 1.log实现类 1 [assembly: log4net.Config.XmlConfigurator(Watch = true)] 2 namespace Zy.Utility.Core 3 { 4 /// <summary> 5 /// 日志处理类 6 /// </summary>

【ASP.NET Web API2框架揭秘】 初识Web API

Web Api 是什么? MSDN:ASP.NET Web API 是一种框架,用于轻松构建可以访问多种客户端(包括浏览器和移动设备)的 HTTP 服务 百度百科:Web API是网络应用程序接口. 个人理解:Web API 是提供给多种客户端对data做CRUD(增删查改)操作的统一接口 ------------------------------------------- Asp.net Web API 支持多种寄宿方式 1,IIS作为宿主(创建一个Asp.net web应用程序作为Web

Spring学习五、Java配置Spring与代理模式

九.使用Java的方式配置Spring JavaConfig是Spring的一个子项目,在Spring4之后,成为了核心功能 @Configuration public class MyConfig { @Bean public User getUser() { return new User(); } } 纯Java配置,在SpringBoot中随处可见 十.代理模式 代理模式是SpringAOP的底层! 代理模式的分类 静态分类 动态代理 10.1 静态代理 角色分析: 抽象角色:一般会使用

Spring Boot2 系列教程 (八) | 配置日志

前言 如题,今天介绍 springboot 默认日志的配置. 默认日志 Logback 默认情况下,Spring Boot 用 Logback 来记录日志,并用 INFO 级别输出到控制台.如果你在平常项目中用过 Spring Boot,你应该已经注意到很多 INFO 级别的日志了.默认日志长这样: 2019-02-18 22:02:14.907 INFO 23384 --- [ main] org.hibernate.Version : HHH000412: Hibernate Core {5

spring cloud深入学习(八)-----配置中心svn示例和refresh

svn版本 同样先示例server端的代码,基本步骤一样. 1.添加依赖 <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-config-server</artifactId> </dependency> <dependency> <groupId>org

深入理解Spring Redis的使用 (八)、Spring Redis实现 注解 自动缓存

项目中有些业务方法希望在有缓存的时候直接从缓存获取,不再执行方法,来提高吞吐率.而且这种情况有很多.如果为每一个方法都写一段if else的代码,导致耦合非常大,不方便后期的修改. 思来想去,决定使用自动注解+Spring AOP来实现. 直接贴代码. 自定义注解类: package com.ns.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import

IntelliJ IDEA 2017.3-----idea创建java的web项目,详细配置(没有web.xml文件问题)

主要步骤有: 创建jave web工程创建WBE-INF目录创建classes和lib目录创建web.xml文件修改编译输出到classes目录指定jar文件到lib目录tomcat的部署,没有在这里写,前面文章有记录 1.创建javaweb项目,File-->New-->Project: 2. 选择web项目:Java Enterprise-->Web Application 3.创建工程和目录地址: 4.最终得到的项目结构: 现在基本的web项目是创建了,但是目录结构还有很多需要修改

Asp.net mvc 框架揭秘之Asp.net +Mvc简介

1.什么是MVC? 介绍MVC之前说一下自治视图(Autonomous View):将UI界面的呈现.交互动作的捕捉响应.逻辑处理流程.数据存储等糅合在一起(如WebForm),我们将这种设计模式成为自治视图 自治视图的弊端: 视图和逻辑糅合在一起,不利于逻辑的复用 不利于对UI组件的调试 MVC是基于关注点分离的方针的架构模式,它将一个人机交互用户的功能分为Model.View.Controller三部分,它们各自具有自己的职责: Model:是对用于状态和业务功能的封装,是同时包含行为和数据