这一篇文章讲的是Spring Web MVC各部分的配置方法,包括Java代码配置和XML文件配置以及MVC命名空间的使用方法。
启用MVC Java配置和XML命名空间
默认配置
要启用MVC Java配置(@Controller等各种注解)和XML命名空间,如果使用的是Java配置,在配置类上再添加@EnableWebMvc注解即可。
@Configuration @EnableWebMvc public class WebAppConfig { }</div>
如果使用XML配置文件的话,添加下面一行即可。
<mvc:annotation-driven/></div>
不论使用哪种方式,都会在Spring中注册一些组件来提供最基本的MVC功能。这些功能在文档中说的很清楚。我简单翻译了一下:
上面的配置会注册一个RequestMappingHandlerMapping,一个RequestMappingHandlerAdapter和一个ExceptionHandlerExceptionResolver来提供注解控制器和注解方法(比如@RequestMapping和@ExceptionHandler等)处理请求的功能。
还会启用以下功能:
- 通过一个ConversionService实例,来进行Spring 3 方式的类型转换及数据绑定支持。
- @NumberFormat格式化数字字段的支持
- @DateTimeFormat格式化Date、Calendar、Long、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 { //有很多个方法可以重写,来提供自定义功能 }</div>
如果使用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 } }</div>
如果使用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></div>
验证功能
Spring自己提供了一组接口和类提供了一套验证功能。不过更通用的方法是使用Bean Validation进行Java对象的验证,Bean Validation的一个实现就是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 } }</div>
如果使用XML配置文件,定义一个Validator然后添加到<mvc:annotation-driven>中。
<mvc:annotation-driven validator="globalValidator"/></div>
上面定义的都是全局验证器,我们也可以在某个控制器中定义一个局部验证器,然后和全局验证器结合起来使用。这时候需要使用@InitBinder注解方法。
@Controller public class MyController { @InitBinder protected void initBinder(WebDataBinder binder) { binder.addValidators(new FooValidator()); } }</div>
配置好验证器之后。当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/*"); } }</div>
使用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></div>
视图控制器
这是一种定义ParameterizableViewController的简单方式,当该控制器被请求的时候不会执行任何逻辑操作,直接转到相应视图。视图控制器的常见用法是将网站的首页直接和/请求映射。
使用Java配置可以这样写,下面的配置将/映射到名为index的视图。
@Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("index"); } }</div>
使用XML配置也很简单。
<mvc:view-controller path="/" view-name="index"/></div>
视图解析器
使用Java配置,只需要重写configureV