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
相關文章
相關標籤/搜索