Spring Web MVC框架學(xué)習(xí)之配置Spring Web MVC
這一篇文章講的是Spring Web MVC各部分的配置方法,包括Java代碼配置和XML文件配置以及MVC命名空間的使用方法。
啟用MVC Java配置和XML命名空間
默認(rèn)配置
要啟用MVC Java配置(@Controller等各種注解)和XML命名空間,如果使用的是Java配置,在配置類上再添加@EnableWebMvc注解即可。
@Configuration @EnableWebMvc public class WebAppConfig { }
如果使用XML配置文件的話,添加下面一行即可。
<mvc:annotation-driven/>
不論使用哪種方式,都會在Spring中注冊一些組件來提供最基本的MVC功能。這些功能在文檔中說的很清楚。我簡單翻譯了一下:
上面的配置會注冊一個RequestMappingHandlerMapping,一個RequestMappingHandlerAdapter和一個ExceptionHandlerExceptionResolver來提供注解控制器和注解方法(比如@RequestMapping和@ExceptionHandler等)處理請求的功能。
還會啟用以下功能:
- 通過一個ConversionService實(shí)例,來進(jìn)行Spring 3 方式的類型轉(zhuǎn)換及數(shù)據(jù)綁定支持。
- @NumberFormat格式化數(shù)字字段的支持
- @DateTimeFormat格式化Date、Calendar、Long、JodaTime類型字段的支持。
- 在控制器方法上使用@Valid驗證Bean的支持,如果檢測到JSR-303 Bean驗證的實(shí)現(xiàn)。
- 一組HttpMessageConverter,用于在字符串和所需Java類型之間進(jìn)行類型轉(zhuǎn)換,具體的列表參見Spring文檔 22.16.1. Enabling the MVC Java Config or the MVC XML Namespace。
通過這些默認(rèn)配置,我們即可開始最基本的Spring MVC使用。
自定義配置
上面提供了最基本的配置。如果需要自定義某些配置也可以。如果使用Java配置的話,讓配置類實(shí)現(xiàn)WebMvcConfigurer接口,更常用的辦法是繼承WebMvcConfigurerAdapter基類,通過重寫基類中的方法即可配置相關(guān)功能。
@Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { //有很多個方法可以重寫,來提供自定義功能 }
如果使用XML配置文件,通過IDE的自動補(bǔ)全功能查看一下<mvc:annotation-driven/>有哪些子屬性和子元素。
類型轉(zhuǎn)換和格式化
默認(rèn)情況下Spring注冊了Number(包括所有基本數(shù)字類型)和java.util.Date的類型轉(zhuǎn)換和格式化功能。要提供類型的轉(zhuǎn)換和格式化功能,就需要自己注冊相應(yīng)的類型轉(zhuǎn)換器和格式化器。
如果使用Java配置的話,重寫addFormatters(FormatterRegistry registry)方法并添加相應(yīng)功能即可。
@Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public void addFormatters(FormatterRegistry registry) { // Add formatters and/or converters } }
如果使用XML配置的話,需要注冊一個ConversionService,然后添加到<mvc:annotation-driven>節(jié)點(diǎn)中。
<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進(jìn)行Java對象的驗證,Bean Validation的一個實(shí)現(xiàn)就是Hibernate Validator。
默認(rèn)情況下當(dāng)@EnableWebMvc或<mvc:annotation-driven/>配置之后,如果Spring檢測到Bean Validation,就會自動注冊一個LocalValidatorFactoryBean來提供驗證功能。如果我們希望手動處理驗證過程,可能希望將驗證器實(shí)例注入到控制器中,這時候就不能使用自動注冊的LocalValidatorFactoryBean了。這時候我們可以選擇手動注冊一個LocalValidatorFactoryBeanBean實(shí)例,然后注解@Primary讓自定義LocalValidatorFactoryBean被優(yōu)先使用。
還有一種辦法就是直接覆蓋Spring的默認(rèn)驗證器配置。如果使用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"/>
上面定義的都是全局驗證器,我們也可以在某個控制器中定義一個局部驗證器,然后和全局驗證器結(jié)合起來使用。這時候需要使用@InitBinder注解方法。
@Controller public class MyController { @InitBinder protected void initBinder(WebDataBinder binder) { binder.addValidators(new FooValidator()); } }
配置好驗證器之后。當(dāng)Spring識別到@Valid注解的方法參數(shù)之后,就會執(zhí)行驗證,將驗證結(jié)果綁定到BindingResult上,我們可以在方法中訪問BindingResult來獲取驗證結(jié)果。
攔截器
我們實(shí)現(xiàn)了攔截器之后,就可以將其應(yīng)用到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的簡單方式,當(dāng)該控制器被請求的時候不會執(zhí)行任何邏輯操作,直接轉(zhuǎn)到相應(yīng)視圖。視圖控制器的常見用法是將網(wǎng)站的首頁直接和/請求映射。
使用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視圖。如果需要其它視圖解析器可以參見其相應(yīng)文檔,以及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命名空間簡化配置。除了內(nèi)置的JSP解析器外,其它視圖解析器可能還需要額外的配置,這里不再細(xì)述。
<mvc:view-resolvers> <mvc:jsp prefix="/WEB-INF/jsp/" suffix=".jsp" view-class="org.springframework.web.servlet.view.JstlView"/> </mvc:view-resolvers>
資源處理
靜態(tài)資源處理
這里說的主要是靜態(tài)資源的處理。前面說了很多關(guān)于控制器、視圖的知識,但是如何映射CSS、JS文件,前面沒有說明。配置方法在這里說明。
使用Java配置的話,重寫addResourceHandlers(ResourceHandlerRegistry registry)方法,然后添加相應(yīng)的映射即可。
@Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/static/**").addResourceLocations("/resources/static/"); } }
使用XML配置文件 也同樣簡單。
<mvc:resources mapping="/static/**" location="/resources/static/"/>
這樣映射之后,假如我們有/resources/static/bootstrap.css文件,那么就可以使用/static/bootstrap.css路徑來訪問該文件了。同樣的在視圖文件中也可以如此引用。還可以使用cache-period設(shè)置資源的過期時間,單位是秒。如果需要指定多個資源位置,可以使用逗號分隔。
資源的版本控制
有些頻繁更新的資源可能需要版本控制,強(qiáng)制讓客戶端使用最新的資源。Spring框架也支持資源的版本控制,我們需要定義資源鏈來實(shí)現(xiàn)這個功能。資源鏈由一個ResourceResolver實(shí)例和多個ResourceTransformer實(shí)例組成。內(nèi)建的VersionResourceResolver能滿足我們的大部分需求,它可以定義一些策略來配置版本控制,例如FixedVersionStrategy會依據(jù)日期、版本號或者其他東西作為版本;ContentVersionStrategy會計算資源的MD5值。
ContentVersionStrategy策略是一個不錯的策略,不過由于它會計算MD5,所以開銷比較大, 因此在使用這種策略的時候最好打開緩存來提高性能。
如果使用Java配置的話,和前面的例子差不多,只不過需要多調(diào)用resourceChain(true)等方法并添加相應(yīng)的版本資源解析器和版本策略。
@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("/**")); } }
下面是使用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>
默認(rèn)Servlet
開啟這個選項可以讓DispatcherServlet處理根路徑/下的靜態(tài)資源請求,說的詳細(xì)點(diǎn)就是假如靜態(tài)文件是webapp/css/site.css,那么我們可以直接通過/css/site.css來訪問這個文件。如果不啟用這個功能,那么靜態(tài)文件就只能映射到其他路徑下比如/static。
這個配置項實(shí)際上會配置一個DefaultServletHttpRequestHandler,映射到路徑/**,并具有最低的優(yōu)先級。由于DefaultServletHttpRequestHandler會將所有請求轉(zhuǎn)發(fā)到默認(rèn)Servlet,所以它必須被配置為最后一個處理映射才行。
使用Java配置的話,重寫configureDefaultServletHandling(...)方法并開啟該選項。
@Configuration @EnableWebMvc public class WebConfig extends WebMvcConfigurerAdapter { @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } }
如果使用XML配置的話,添加以下行。
<mvc:default-servlet-handler/>
消息轉(zhuǎn)換
如果我們需要覆蓋Spring默認(rèn)的消息轉(zhuǎn)換器,可以重寫configureMessageConverters(List<HttpMessageConverter<?>> converters)方法,然后向converters參數(shù)添加我們自己的消息轉(zhuǎn)換器。如果僅僅希望增加自己的類型轉(zhuǎn)換器,重寫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提供的簡化類或者M(jìn)VC命名空間,幫助我們快速配置功能。有時候可能需要更高級的功能定制,這樣就需要自己處理這些底層Bean的初始化和屬性設(shè)置。
Java配置自定義
我們先來看一看@EnableWebMvc注解的定義??梢钥吹剿€使用了一個@Import注解,引用了DelegatingWebMvcConfiguration類。當(dāng)我們注解@EnableWebMvc的時候,實(shí)際上初始化和配置的底層類就是DelegatingWebMvcConfiguration。
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented @Import(DelegatingWebMvcConfiguration.class) public @interface EnableWebMvc { }
因此我們?nèi)绻远xMVC的話,第一件事就是移除注解@EnableWebMvc。然后繼承DelegatingWebMvcConfiguration類并實(shí)現(xiàn)它的requestMappingHandlerAdapter()方法。
@Configuration public class WebConfig extends DelegatingWebMvcConfiguration { @Override @Bean public RequestMappingHandlerAdapter requestMappingHandlerAdapter() { // 在這里進(jìn)行高級配置 } }
在項目中DelegatingWebMvcConfiguration子類和@EnableWebMvc注解配置類只能存在一個,因為它們做的事情實(shí)際上是一樣的。而且這里的配置并不影響Spring MVC的其他配置。
自定義MVC命名空間配置
這里的自定義配置更困難,因為Spring沒有提供相應(yīng)的配置機(jī)制。如果實(shí)在需要自定義MVC命名空間配置,可以考慮使用Spring提供的BeanPostProcessor機(jī)制,在檢測到Bean之后修改它的值。
@Component public class MyPostProcessor implements BeanPostProcessor { public Object postProcessBeforeInitialization(Object bean, String name) throws BeansException { if (bean instanceof RequestMappingHandlerAdapter) { // 在這里自定義屬性 } } }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Spring?Boot?3.x?集成?Feign的詳細(xì)過程
本文闡述了如何在SpringBoot3.x中集成Feign,以實(shí)現(xiàn)微服務(wù)之間的調(diào)用,主要步驟包括:搭建chain-common服務(wù),創(chuàng)建chain-starter/chain-feign-starter服務(wù),集成Feign到chain-system和chain-iot-channel服務(wù),配置Feign,感興趣的朋友一起看看吧2024-09-09通過實(shí)例了解JavaBean開發(fā)及使用過程解析
這篇文章主要介紹了通過實(shí)例了解JavaBean開發(fā)及使用過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-08-08解決@PostConstruct注解導(dǎo)致的程序無法啟動(@PostConstruct的執(zhí)行)
這篇文章主要介紹了解決@PostConstruct注解導(dǎo)致的程序無法啟動(@PostConstruct的執(zhí)行)問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01Spring Security permitAll()不允許匿名訪問的操作
這篇文章主要介紹了Spring Security permitAll()不允許匿名訪問的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06Spring Cloud Stream微服務(wù)消息框架原理及實(shí)例解析
這篇文章主要介紹了Spring Cloud Stream微服務(wù)消息框架原理及實(shí)例解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-06-06基于visualvm監(jiān)控類實(shí)現(xiàn)過程詳解
這篇文章主要介紹了基于visualvm監(jiān)控類實(shí)現(xiàn)過程詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-09-09