mvc:annotation-driven/
轉(zhuǎn)自:?Spring MVC 解讀——<mvc:annotation-driven/>
摘自:使用@Controller注解為什么要配置<mvc:annotation-driven />
?
?
摘要: <mvc:annotation-driven/>是做什么的?它做了什么?它與<context:component-scan/>有什么區(qū)別?
Spring MVC 解讀——<mvc:annotation-driven/>
一、AnnotationDrivenBeanDefinitionParser
????通常如果我們希望通過注解的方式來進(jìn)行Spring MVC開發(fā),我們都會(huì)在***-servlet.xml中加入<mvc:annotation-driven/>標(biāo)簽來告訴Spring我們的目的。但是我們?yōu)槭裁催@么做呢?這個(gè)標(biāo)簽是什么意思呢?它做了什么呢?
????同樣為了弄清楚這些問題, 像<context:component-scan/>標(biāo)簽一樣,我們先找到它的解析類。第一篇文章中說過了,所有的自定義命名空間(像mvc,context等)下的標(biāo)簽解析都是由BeanDefinitionParser接口的子類來完成的。參看第一篇文章中的圖片
?
我們看到有多個(gè)AnnotationDrivenBeanDefinitionParser,他們是用來處理不同命名空間下的<annotation-driven/>標(biāo)簽的,我們今天研究的是<mvc:annotation-driven/>標(biāo)簽,所以我們找到對(duì)應(yīng)的實(shí)現(xiàn)類是org.springframework.web.servlet.config.AnnotationDrivenBeanDefinitionParser。
????通過閱讀類注釋文檔,我們發(fā)現(xiàn)這個(gè)類主要是用來向工廠中注冊了
-
RequestMappingHandlerMapping?
-
BeanNameUrlHandlerMapping
-
RequestMappingHandlerAdapter
-
HttpRequestHandlerAdapter
-
SimpleControllerHandlerAdapter
-
ExceptionHandlerExceptionResolver?
-
ResponseStatusExceptionResolver?
-
DefaultHandlerExceptionResolver?
上面幾個(gè)Bean實(shí)例。這幾個(gè)類都是用來做什么的呢?
????前兩個(gè)是HandlerMapping接口的實(shí)現(xiàn)類,用來處理請(qǐng)求映射的。其中第一個(gè)是處理@RequestMapping注解的。第二個(gè)會(huì)將controller類的名字映射為請(qǐng)求url。
????中間三個(gè)是用來處理請(qǐng)求的。具體點(diǎn)說就是確定調(diào)用哪個(gè)controller的哪個(gè)方法來處理當(dāng)前請(qǐng)求。第一個(gè)處理@Controller注解的處理器,支持自定義方法參數(shù)和返回值(很酷)。第二個(gè)是處理繼承HttpRequestHandler的處理器。第三個(gè)處理繼承自Controller接口的處理器。
????后面三個(gè)是用來處理異常的解析器。
二、實(shí)現(xiàn)
????光說無憑據(jù),我們直接看代碼:
public BeanDefinition parse(Element element, ParserContext parserContext) {Object source = parserContext.extractSource(element);CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), source);parserContext.pushContainingComponent(compDefinition);RuntimeBeanReference contentNegotiationManager = getContentNegotiationManager(element, source, parserContext);//第一個(gè)在這 RequestMappingHandlerMappingRootBeanDefinition handlerMappingDef = new RootBeanDefinition(RequestMappingHandlerMapping.class);handlerMappingDef.setSource(source);handlerMappingDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);handlerMappingDef.getPropertyValues().add("order", 0);handlerMappingDef.getPropertyValues().add("removeSemicolonContent", false);handlerMappingDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);String methodMappingName = parserContext.getReaderContext().registerWithGeneratedName(handlerMappingDef);//第二個(gè)在這 RequestMappingHandlerAdapterRootBeanDefinition handlerAdapterDef = new RootBeanDefinition(RequestMappingHandlerAdapter.class);handlerAdapterDef.setSource(source);handlerAdapterDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);handlerAdapterDef.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);handlerAdapterDef.getPropertyValues().add("webBindingInitializer", bindingDef);handlerAdapterDef.getPropertyValues().add("messageConverters", messageConverters);if (element.hasAttribute("ignoreDefaultModelOnRedirect")) {Boolean ignoreDefaultModel = Boolean.valueOf(element.getAttribute("ignoreDefaultModelOnRedirect"));handlerAdapterDef.getPropertyValues().add("ignoreDefaultModelOnRedirect", ignoreDefaultModel);}if (argumentResolvers != null) {handlerAdapterDef.getPropertyValues().add("customArgumentResolvers", argumentResolvers);}if (returnValueHandlers != null) {handlerAdapterDef.getPropertyValues().add("customReturnValueHandlers", returnValueHandlers);}if (asyncTimeout != null) {handlerAdapterDef.getPropertyValues().add("asyncRequestTimeout", asyncTimeout);}if (asyncExecutor != null) {handlerAdapterDef.getPropertyValues().add("taskExecutor", asyncExecutor);}handlerAdapterDef.getPropertyValues().add("callableInterceptors", callableInterceptors);handlerAdapterDef.getPropertyValues().add("deferredResultInterceptors", deferredResultInterceptors);String handlerAdapterName = parserContext.getReaderContext().registerWithGeneratedName(handlerAdapterDef);//異常處理解析器RootBeanDefinition exceptionHandlerExceptionResolver = new RootBeanDefinition(ExceptionHandlerExceptionResolver.class);exceptionHandlerExceptionResolver.setSource(source);exceptionHandlerExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);exceptionHandlerExceptionResolver.getPropertyValues().add("contentNegotiationManager", contentNegotiationManager);exceptionHandlerExceptionResolver.getPropertyValues().add("messageConverters", messageConverters);exceptionHandlerExceptionResolver.getPropertyValues().add("order", 0);String methodExceptionResolverName =parserContext.getReaderContext().registerWithGeneratedName(exceptionHandlerExceptionResolver);//異常處理解析器RootBeanDefinition responseStatusExceptionResolver = new RootBeanDefinition(ResponseStatusExceptionResolver.class);responseStatusExceptionResolver.setSource(source);responseStatusExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);responseStatusExceptionResolver.getPropertyValues().add("order", 1);String responseStatusExceptionResolverName =parserContext.getReaderContext().registerWithGeneratedName(responseStatusExceptionResolver);//異常處理解析器RootBeanDefinition defaultExceptionResolver = new RootBeanDefinition(DefaultHandlerExceptionResolver.class);defaultExceptionResolver.setSource(source);defaultExceptionResolver.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);defaultExceptionResolver.getPropertyValues().add("order", 2);String defaultExceptionResolverName =parserContext.getReaderContext().registerWithGeneratedName(defaultExceptionResolver);parserContext.registerComponent(new BeanComponentDefinition(handlerMappingDef, methodMappingName));parserContext.registerComponent(new BeanComponentDefinition(handlerAdapterDef, handlerAdapterName));parserContext.registerComponent(new BeanComponentDefinition(exceptionHandlerExceptionResolver, methodExceptionResolverName));parserContext.registerComponent(new BeanComponentDefinition(responseStatusExceptionResolver, responseStatusExceptionResolverName));parserContext.registerComponent(new BeanComponentDefinition(defaultExceptionResolver, defaultExceptionResolverName));parserContext.registerComponent(new BeanComponentDefinition(mappedCsInterceptorDef, mappedInterceptorName));//這里注冊了BeanNameUrlHandlerMapping,SimpleControllerHandlerAdapter等// Ensure BeanNameUrlHandlerMapping (SPR-8289) and default HandlerAdapters are not "turned off" MvcNamespaceUtils.registerDefaultComponents(parserContext, source);parserContext.popAndRegisterContainingComponent();return null;} //在這啊。 public static void registerDefaultComponents(ParserContext parserContext, Object source) {registerBeanNameUrlHandlerMapping(parserContext, source);registerHttpRequestHandlerAdapter(parserContext, source);registerSimpleControllerHandlerAdapter(parserContext, source);}略長,但很容易看明白的代碼。看注釋我們發(fā)現(xiàn),它的確注冊了上面說的那幾個(gè)類。
三、總結(jié)
????我們知道了它們自動(dòng)為我們注冊了這么多的Bean,那這些Bean是做什么的呢?
????我們主要說明里面的兩個(gè),RequestMappingHandlerMapping和RequestMappingHandlerAdapter。
????第一個(gè)是HandlerMapping的實(shí)現(xiàn)類,它會(huì)處理@RequestMapping 注解,并將其注冊到請(qǐng)求映射表中。(下片文章我們會(huì)詳細(xì)介紹的)
????第二個(gè)是HandlerAdapter的實(shí)現(xiàn)類,它是處理請(qǐng)求的適配器,說白了,就是確定調(diào)用哪個(gè)類的哪個(gè)方法,并且構(gòu)造方法參數(shù),返回值。(后面文章也會(huì)陸續(xù)詳細(xì)介紹的)
????那么它跟<context:component-scan/>有什么區(qū)別呢?其實(shí)想上篇文章中介紹的,<context:component-scan/>標(biāo)簽是告訴Spring 來掃描指定包下的類,并注冊被@Component,@Controller,@Service,@Repository等注解標(biāo)記的組件。
????而<mvc:annotation-scan/>是告知Spring,我們啟用注解驅(qū)動(dòng)。然后Spring會(huì)自動(dòng)為我們注冊上面說到的幾個(gè)Bean到工廠中,來處理我們的請(qǐng)求。
?
?
------------------------------------------------
?
This tag registers the DefaultAnnotationHandlerMapping and AnnotationMethodHandlerAdapter beans that are required for spring MVC to dispatch requests to Controllers.?
這個(gè)標(biāo)簽注冊了Spring MVC分發(fā)請(qǐng)求到控制器所必須的DefaultAnnotationHandlerMapping和AnnotationMethodHandlerAdapter實(shí)例
The tag configures those two beans with sensible defaults based on what is present in your classpath.?
標(biāo)簽配置的這2個(gè)實(shí)例可以根據(jù)classpath中的內(nèi)容默認(rèn)提供以下功能:
The defaults are:
1. Support for Spring 3's Type ConversionService in addition to JavaBeans PropertyEditors during Data Binding.?
A ConversionService instance produced by the org.springframework.format.support.FormattingConversionServiceFactoryBean is used by default.?
This can be overriden by setting the conversion-service attribute.
支持spring3的javaBeans屬性編輯器數(shù)據(jù)綁定時(shí)的類型轉(zhuǎn)換服務(wù)。
類型轉(zhuǎn)換服務(wù)實(shí)例默認(rèn)為org.springframework.format.support.FormattingConversionServiceFactoryBean。
可以覆蓋conversion-service屬性來指定類型轉(zhuǎn)換服務(wù)實(shí)例類。
2. Support for formatting Number fields using the @NumberFormat annotation
支持@NumberFormat 注解格式化數(shù)字類型字段。
3. Support for formatting Date, Calendar, Long, and Joda Time fields using the @DateTimeFormat annotation, if Joda Time 1.3 or higher is present on the classpath.
@DateTimeFormat注解格式化 Date, Calendar, Long和 Joda Time(如classpath下存在Joda Time 1.3或更高版本)字段
4. Support for validating @Controller inputs with @Valid, if a JSR-303 Provider is present on the classpath.?
The validation system can be explicitly configured by setting the validator attribute.
支持@Valid注解驗(yàn)證控制器數(shù)據(jù),classpath中需JSR-303的**。
可以使用setting明確的配置
5. Support for reading and writing XML, if JAXB is present on the classpath.
支持讀寫xml,classpath中需JAXB 。
6. Support for reading and writing JSON, if Jackson is present on the classpath.
支持讀寫json,classpath中需Jackson 。
A typical usage is shown below:
下邊是用法:
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/drizzlewithwind/p/6064021.html
總結(jié)
以上是生活随笔為你收集整理的mvc:annotation-driven/的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python3-字典中的一些常用方法
- 下一篇: win7提示Xshell5提示缺少msv