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

 

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

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

默认配置

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

@Configuration @EnableWebMvc public class WebAppConfig { }
  • 1
  • 2
  • 3
  • 4
  • 5

若是使用XML配置文件的话,添加下面一行便可。java

<mvc:annotation-driven/>
  • 1

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

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

还会启用如下功能:json

  • 经过一个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使用。bootstrap

自定义配置

上面提供了最基本的配置。若是须要自定义某些配置也能够。若是使用Java配置的话,让配置类实现WebMvcConfigurer接口,更经常使用的办法是继承WebMvcConfigurerAdapter基类,经过重写基类中的方法便可配置相关功能。缓存

@Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { //有不少个方法能够重写,来提供自定义功能 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

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

类型转换和格式化

默认状况下Spring注册了Number(包括全部基本数字类型)和java.util.Date的类型转换和格式化功能。要提供类型的转换和格式化功能,就须要本身注册相应的类型转换器和格式化器。mvc

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

@Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public void addFormatters(FormatterRegistry registry) { // Add formatters and/or converters } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

若是使用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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

验证功能

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 } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

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

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

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

@Controller public class MyController { @InitBinder protected void initBinder(WebDataBinder binder) { binder.addValidators(new FooValidator()); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

配置好验证器以后。当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/*"); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

使用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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

视图控制器

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

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

@Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("index"); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

使用XML配置也很简单。

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

视图解析器

使用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); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

若是使用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>
  • 1
  • 2
  • 3
  • 4
  • 5

资源处理

静态资源处理

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

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

@Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/static/**").addResourceLocations("/resources/static/"); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

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

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

这样映射以后,假如咱们有/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("/static/**") .addResourceLocations("/resources/static/") .resourceChain(true).addResolver( new VersionResourceResolver().addContentVersionStrategy("/**")); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

下面是使用XML配置的例子。

<mvc:resources mapping="/static/**" location="/resources/static/"> <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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

默认Servlet

开启这个选项可让DispatcherServlet处理根路径/下的静态资源请求,说的详细点就是假如静态文件是webapp/css/site.css,那么咱们能够直接经过/css/site.css来访问这个文件。若是不启用这个功能,那么静态文件就只能映射到其余路径下好比/static

这个配置项实际上会配置一个DefaultServletHttpRequestHandler,映射到路径/**,并具备最低的优先级。因为DefaultServletHttpRequestHandler会将全部请求转发到默认Servlet,因此它必须被配置为最后一个处理映射才行。

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

@Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

若是使用XML配置的话,添加如下行。

<mvc:default-servlet-handler/>
  • 1

消息转换

若是咱们须要覆盖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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

高级自定义配置

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

Java配置自定义

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

@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @Import(DelegatingWebMvcConfiguration.class) public @interface EnableWebMvc { }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

所以咱们若是要自定义MVC的话,第一件事就是移除注解@EnableWebMvc。而后继承DelegatingWebMvcConfiguration类并实现它的requestMappingHandlerAdapter()方法。

@Configuration public class WebConfig extends DelegatingWebMvcConfiguration { @Override @Bean public RequestMappingHandlerAdapter requestMappingHandlerAdapter() { // 在这里进行高级配置 } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

在项目中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) { // 在这里自定义属性 } } }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
相关文章
相关标签/搜索