? | 上一篇文章让我们了解HandlerMapping和HandlerAdapter以及默认采取的策略,这篇文章就要讲述mvc:annotation-driven对默认策略的改变。它背后到底注册了哪些HandlerMapping和HandlerAdapter。?
首先可以在DispatcherServlet的initStrategies方法中的initHandlerMappings和initHandlerAdapters中打上断点,来查看注册了哪些HandlerMapping和HandlerAdapter?
Java代码?? protected?void?initStrategies(ApplicationContext?context)?{?? ????????initMultipartResolver(context);?? ????????initLocaleResolver(context);?? ????????initThemeResolver(context);?? ????????initHandlerMappings(context);?? ????????initHandlerAdapters(context);?? ????????initHandlerExceptionResolvers(context);?? ????????initRequestToViewNameTranslator(context);?? ????????initViewResolvers(context);?? ????????initFlashMapManager(context);?? ????}??
目前我的spring版本是4.0.5。我查看的结果:? HandlerMapping:注册了 RequestMappingHandlerMapping和BeanNameUrlHandlerMapping? HandlerAdapter:注册了 RequestMappingHandlerAdapter、HttpRequestHandlerAdapter和SimpleControllerHandlerAdapter? 这几个HandlerMapping和HandlerAdapter上文都提到过。? 下面就要查看下具体的注册过程:? 在xml文件中配置mvc:annotation-driven,肯定有一个专门的类来解析处理这个东西。? 会有这样的一个接口BeanDefinitionParser,它只有一个方法:?
Java代码?? public?interface?BeanDefinitionParser?{?? ?? ????/**? [email protected]}?and?register?the?resulting? [email protected](s)}?with?the? [email protected]Context#getRegistry()?BeanDefinitionRegistry}? [email protected]}.? ?????*?<p>[email protected]on}?that?results? ?????*?from?the?parse?if?they?will?ever?be?used?in?a?nested?fashion?(for?example?as? [email protected]<property/>}?tag).?Implementations?may?return? [email protected]}?if?they?will?<strong>not</strong>?be?used?in?a?nested?fashion.? [email protected][email protected] BeanDefinitions}? [email protected]he?current?state?of?the?parsing?process;? [email protected].beans.factory.support.BeanDefinitionRegistry}? [email protected][email protected]}? ?????*/?? ????BeanDefinition?parse(Element?element,?ParserContext?parserContext);?? ?? }??
它是用来专门处理<beans></beans>里面的配置元素。然后我们会找到这样的一个实现类AnnotationDrivenBeanDefinitionParser,它的文档介绍如下:?
Java代码?? /**? ?*?这里清清楚楚写着该类是专门处理?<mvc:annotation-driven/>标签的? [email protected]}?that?provides?the?configuration?for?the? [email protected]<annotation-driven/>}?MVC?namespace??element.? ?*? ?*?这里说明了注册的HandlerMapping? ?*?<p>[email protected]}s:</p>? ?*?<ul>? ?*??<li>[email protected]}? ?*??ordered?at?0?for?mapping?requests?to?annotated?controller?methods.? ?*??<li>[email protected]}? ?*??ordered?at?2?to?map?URL?paths?to?controller?bean?names.? ?*?</ul>? ?*? ?*?<p><strong>Note:</strong>?Additional?HandlerMappings?may?be?registered? [email protected]<view-controller>}?or?the? [email protected]<resources>}?MVC?namespace?elements.? ?*? ?*?这里说明了注册的HandlerAdapter? ?*?<p>[email protected]}s:? ?*?<ul>? ?*??<li>[email protected]}? ?*??for?processing?requests?with?annotated?controller?methods.? ?*??<li>[email protected]}? [email protected]r}s.? ?*??<li>[email protected]}? [email protected]Controller}s.? ?*?</ul>? ?*? ?*?<p>[email protected]esolver}s:? ?*?<ul>? ?*??<li>[email protected]}?for?handling?exceptions? ?*??through?@[email protected]}?methods.? ?*??<li>[email protected]}?for?exceptions?annotated? ?*??with?@[email protected]}.? ?*??<li>[email protected]}?for?resolving?known?Spring? ?*??exception?types? ?*?</ul>? ?*? ?*?<p>[email protected]}?and?the? [email protected]}?are?configured?with?instances?of? ?*?the?following?by?default:? ?*?<ul>? ?*??<li>[email protected]}? ?*??<li>[email protected]}? ?*??<li>[email protected]idatorFactoryBean}? ?*??if?a?JSR-303?implementation?is?available?on?the?classpath? ?*??<li>[email protected]}s?depending?on?what?3rd?party? ?*??libraries?are?available?on?the?classpath.? ?*?</ul>? ?*? [email protected] [email protected] [email protected] [email protected] [email protected] [email protected] ?*/?? class?AnnotationDrivenBeanDefinitionParser?implements?BeanDefinitionParser?{?? ??????????//先省略,请详细看下它的文档介绍?? }??
上面的文档对mvc:annotation-driven注册的东西都有详细的说明。? 具体看解析过程的代码的内容:?
Java代码?? @Override?? ????public?BeanDefinition?parse(Element?element,?ParserContext?parserContext)?{?? ????????Object?source?=?parserContext.extractSource(element);?? ?? ????????//省略?? ????????RootBeanDefinition?handlerMappingDef?=?new?RootBeanDefinition(RequestMappingHandlerMapping.class);?? ?????????? ????????RootBeanDefinition?handlerAdapterDef?=?new?RootBeanDefinition(RequestMappingHandlerAdapter.class);?? ?????????? ????????????//省略,?? ????????//?Ensure?BeanNameUrlHandlerMapping?(SPR-8289)?and?default?HandlerAdapters?are?not "turned?off"?? ????????MvcNamespaceUtils.registerDefaultComponents(parserContext,?source);?? ?? ????????parserContext.popAndRegisterContainingComponent();?? ?? ????????return?null;?? ????}??
MvcNamespaceUtils.registerDefaultComponents的内容如下:?
Java代码?? public?static?void?registerDefaultComponents(ParserContext?parserContext,?Object?source)?{?? ????????registerBeanNameUrlHandlerMapping(parserContext,?source);?? ????????registerHttpRequestHandlerAdapter(parserContext,?source);?? ????????registerSimpleControllerHandlerAdapter(parserContext,?source);?? ????}??
至此所注册的HandlerMapping和HandlerAdapter我们都找到了。? 然后我们就可以体验下RequestMappingHandlerMapping和BeanNameUrlHandlerMapping,这两个HandlerMapping。由于上一篇文章已经体验过了BeanNameUrlHandlerMapping,接下来就要体验下RequestMappingHandlerMapping,然后你会发觉又有一系列的新名词走进我们的视野,需要我们去弄清楚。? 先体验下:?
首先还是web.xml的配置:?
Java代码?? <!DOCTYPE?web-app?PUBLIC?? ?"-//Sun?Microsystems,?Inc.//DTD?Web?Application?2.3//EN"?? ?"http://java.sun.com/dtd/web-app_2_3.dtd"?>?? ?? <web-app>?? ??<display-name>Archetype?Created?Web?Application</display-name>?? ??<servlet>?? ????????<servlet-name>mvc</servlet-name>?? ????????<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>?? ????????<load-on-startup>1</load-on-startup>?? ????</servlet>?? ?? ????<servlet-mapping>?? ????????<servlet-name>mvc</servlet-name>?? ????????<url-pattern>/*</url-pattern>?? ????</servlet-mapping>?? </web-app>??
最简单的配置,然后是[servlet-name]-servlet.xml,本工程即mvc-servlet.xml:?
Java代码?? <?xml?version="1.0"?encoding="UTF-8"??>?? <beans?xmlns="http://www.springframework.org/schema/beans"?xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"?xmlns:mvc="http://www.springframework.org/schema/mvc"?xmlns:util="http://www.springframework.org/schema/util"?xmlns:context="http://www.springframework.org/schema/context"?? ????xsi:schemaLocation="http://www.springframework.org/schema/beans?? ????http://www.springframework.org/schema/beans/spring-beans-3.1.xsd?? ????http://www.springframework.org/schema/mvc?? ????http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd?? ????http://www.springframework.org/schema/util?? ????http://www.springframework.org/schema/util/spring-util-2.0.xsd?? ????http://www.springframework.org/schema/context??? ????http://www.springframework.org/schema/context/spring-context-3.2.xsd">?? ?????? ?????? ????<mvc:annotation-driven/>?? ?????? ????<bean?class="com.lg.mvc.StringAction"/>?? ????<bean?name="/index"?class="com.lg.mvc.HomeAction"></bean>?? ?????? ?????? ????<bean?class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">?? ????????<property?name="templateLoaderPath"?value="/WEB-INF/views"?/>?? ????????<property?name="defaultEncoding"?value="utf-8"?/>?? ????????<property?name="freemarkerSettings">?? ????????????<props>?? ????????????????<prop?key="locale">zh_CN</prop>?? ????????????</props>?? ????????</property>?? ????</bean>?? ????<bean?class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">?? ????????<property?name="suffix"?value=".html"?/>?? ????????<property?name="contentType"?value="text/html;charset=utf-8"?/>?? ????????<property?name="requestContextAttribute"?value="request"?/>?? ????????<property?name="exposeRequestAttributes"?value="true"?/>?? ????????<property?name="exposeSessionAttributes"?value="true"?/>?? ????</bean>?? </beans>??
开启了<mvc:annotation-driven/>,同时注册了两个bean。有RequestMappingHandlerMapping和RequestMappingHandlerAdapter作为后盾支持,[email protected]@[email protected]@RequestMapping无关的,[email protected],[email protected]ng也是挺重要的,但不是必须的。这里简单说明下:[email protected][email protected],如果有其一则会将该bean纳入作为它的处理对象,[email protected]?[email protected]?(作为基础地址),也可以配置在方法上,[email protected],有时候又不会,[email protected]@RequestMapping,RequestMappingHandlerMapping都会将他们纳入自己的handler[email protected]?是不被处理的,[email protected]@Controller,[email protected],你可以试验下,稍后会做源代码说明。下面继续,[email protected]@RequestMapping注解的StringAction类?
Java代码?? package?com.lg.mvc;?? ?? import?java.io.UnsupportedEncodingException;?? ?? import?org.springframework.stereotype.Controller;?? import?org.springframework.web.bind.annotation.RequestMapping;?? import?org.springframework.web.bind.annotation.RequestMethod;?? import?org.springframework.web.bind.annotation.ResponseBody;?? ?? @Controller?? public?class?StringAction?{?? ?????? [email protected] [email protected](value="/string",method=RequestMethod.GET)?? ????public?String?testMessageConverter(String?name)?throws?UnsupportedEncodingException{?? ????????System.out.println(name);?? ????????return?name;?? ????}?? }??
然后就可以运行一下,体验一下,先不要管乱码问题,这个问题引出了下一篇文章spring框架中的乱码问题。? 运行结果如下:?
? 证明整个流程跑通了。? [email protected]ingHandlerMapping管理,RequestMappingHandlerMapping会将这个handler和handler中的每[email protected]ethod对象,该类的构造函数为HandlerMethod(Object bean, Method method),经过这样的包装之后将构造的HandlerMethod对象作为新的handler,然后进行选择适配器,进行方法调用,当RequestMappingHandlerAdapter判断是否support一个类时,就是依据当前的handlelr是否是HandlerMethod类型。若是则由RequestMappingHandlerAdapter来调度执行该handler(handler为HandlerMethod类型)的中的method方法。以上就是整个大体的流程。下面就要用代码来事实说话:? 第一步要弄清RequestMappingHandlerMapping在初始化时是如何寻找它所管辖的bean。说说我找代码的具体流程:? RequestMappingHandlerMapping的父类AbstractHandlerMethodMapping在初始化时,会调用到这样的一个方法initHandlerMethods,在该方法中,[email protected]?[email protected]:?
Java代码?? /**? ?????*?Scan?beans?in?the?ApplicationContext,?detect?and?register?handler?methods.? [email protected]#isHandler(Class)? [email protected]#getMappingForMethod(Method,?Class)? [email protected]#handlerMethodsInitialized(Map)? ?????*/?? ????protected?void?initHandlerMethods()?{?? ????????if?(logger.isDebugEnabled())?{?? ????????????logger.debug("Looking?for?request?mappings?in?application?context:?"?+?getApplicationContext());?? ????????}?? ?? ????????String[]?beanNames?=?(this.detectHandlerMethodsInAncestorContexts???? ????????????????BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(),?Object.class)?:?? ????????????????getApplicationContext().getBeanNamesForType(Object.class));?? ?? ????????for?(String?beanName?:?beanNames)?{?? ????????????if?(!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)?&&?? ????????????????????isHandler(getApplicationContext().getType(beanName))){?? ????????????????detectHandlerMethods(beanName);?? ????????????}?? ????????}?? ????????handlerMethodsInitialized(getHandlerMethods());?? ????}??
其中的isHandler的判断方法代码如下:?
Java代码?? /**? [email protected]}? ?????*?Expects?a?handler?to?have?a?type-level?@[email protected]}?annotation.? ?????*/?? [email protected] ????protected?boolean?isHandler(Class<?>?beanType)?{?? ????????return?((AnnotationUtils.findAnnotation(beanType,?Controller.class)?!=?null)?||?? ????????????????(AnnotationUtils.findAnnotation(beanType,?RequestMapping.class)?!=?null));?? ????}??
如果handler含有了上述注解的其中之一,[email protected]??方法:?
Java代码?? /**? ?????*?Look?for?handler?methods?in?a?handler.? [email protected]?a?handler?instance? ?????*/?? ????protected?void?detectHandlerMethods(final?Object?handler)?{?? ????????Class<?>?handlerType?=?? ????????????????(handler?instanceof?String???getApplicationContext().getType((String)?handler)?:?handler.getClass());?? ?? ????????//?Avoid?repeated?calls?to?getMappingForMethod?which?would?rebuild?RequestMappingInfo?instances?? ????????final?Map<Method,?T>?mappings?=?new?IdentityHashMap<Method,?T>();?? ????????final?Class<?>?userType?=?ClassUtils.getUserClass(handlerType);?? ?? ????????Set<Method>?methods?=?HandlerMethodSelector.selectMethods(userType,?new?MethodFilter()?{?? [email protected] ????????????public?boolean?matches(Method?method)?{?? ????????????????T?mapping?=?getMappingForMethod(method,?userType);?? ????????????????if?(mapping?!=?null)?{?? ????????????????????mappings.put(method,?mapping);?? ????????????????????return?true;?? ????????????????}?? ????????????????else?{?? ????????????????????return?false;?? ????????????????}?? ????????????}?? ????????});?? ?? ????????for?(Method?method?:?methods)?{?? ????????????registerHandlerMethod(handler,?method,?mappings.get(method));?? ????????}?? ????}??
遍历这个handler类的所有方法,过滤条件就是这个内部类MethodFilter,其中的getMappingForMethod方法内容为:?
Java代码?? /**? ?????*?Uses?method?and?type-level?@[email protected]}?annotations?to?create? ?????*?the?RequestMappingInfo.? [email protected],[email protected]}?if?the?method? [email protected]@RequestMapping}?annotation.? [email protected]#getCustomMethodCondition(Method)? [email protected]#getCustomTypeCondition(Class)? ?????*/?? [email protected] ????protected?RequestMappingInfo?getMappingForMethod(Method?method,?Class<?>?handlerType)?{?? ????????RequestMappingInfo?info?=?null;?? ????????RequestMapping?methodAnnotation?=?AnnotationUtils.findAnnotation(method,?RequestMapping.class);?? ????????if?(methodAnnotation?!=?null)?{?? ????????????RequestCondition<?>?methodCondition?=?getCustomMethodCondition(method);?? ????????????info?=?createRequestMappingInfo(methodAnnotation,?methodCondition);?? ????????????RequestMapping?typeAnnotation?=?AnnotationUtils.findAnnotation(handlerType,?RequestMapping.class);?? ????????????if?(typeAnnotation?!=?null)?{?? ????????????????RequestCondition<?>?typeCondition?=?getCustomTypeCondition(handlerType);?? ????????????????info?=?createRequestMappingInfo(typeAnnotation,?typeCondition).combine(info);?? ????????????}?? ????????}?? ????????return?info;?? ????}??
如找到了含有RequestMapping注释的方法,则由这个注释的内容构建一个RequestMappingInfo对象:?
Java代码?? /**? ?????*?Created?a?RequestMappingInfo?from?a?RequestMapping?annotation.? ?????*/?? ????protected?RequestMappingInfo?createRequestMappingInfo(RequestMapping?annotation,?RequestCondition<?>?customCondition)?{?? ????????String[]?patterns?=?resolveEmbeddedValuesInPatterns(annotation.value());?? ????????return?new?RequestMappingInfo(?? ????????????????new?PatternsRequestCondition(patterns,?getUrlPathHelper(),?getPathMatcher(),?? ????????????????????????this.useSuffixPatternMatch,?this.useTrailingSlashMatch,?this.fileExtensions),?? ????????????????new?RequestMethodsRequestCondition(annotation.method()),?? ????????????????new?ParamsRequestCondition(annotation.params()),?? ????????????????new?HeadersRequestCondition(annotation.headers()),?? ????????????????new?ConsumesRequestCondition(annotation.consumes(),?annotation.headers()),?? ????????????????new?ProducesRequestCondition(annotation.produces(),?annotation.headers(),?this.contentNegotiationManager),?? ????????????????customCondition);?? ????}??
就是拿RequestMapping注释的内容进一步封装进RequestMappingInfo对象中。对handler的所有方法过滤完成之后,就要遍历这些方法,以一定的方式存储起来。?
Java代码?? /**? ?????*?Register?a?handler?method?and?its?unique?mapping.? [email protected]or?the?handler?instance? [email protected] [email protected]d?with?the?handler?method? [email protected]?was?already?registered? ?????*?under?the?same?mapping? ?????*/?? ????protected?void?registerHandlerMethod(Object?handler,?Method?method,?T?mapping)?{?? ????????HandlerMethod?newHandlerMethod?=?createHandlerMethod(handler,?method);?? ????????HandlerMethod?oldHandlerMethod?=?this.handlerMethods.get(mapping);?? ????????if?(oldHandlerMethod?!=?null?&&?!oldHandlerMethod.equals(newHandlerMethod))?{?? ????????????throw?new?IllegalStateException("Ambiguous?mapping?found.?Cannot?map?'"?+?newHandlerMethod.getBean()?+?? ????????????????????"'?bean?method?\n"?+?newHandlerMethod?+?"\nto?"?+?mapping?+?":?There?is?already?'"?+?? ????????????????????oldHandlerMethod.getBean()?+?"'?bean?method\n"?+?oldHandlerMethod?+?"?mapped.");?? ????????}?? ?? ????????this.handlerMethods.put(mapping,?newHandlerMethod);?? ????????if?(logger.isInfoEnabled())?{?? ????????????logger.info("Mapped?\""?+?mapping?+?"\"?onto?"?+?newHandlerMethod);?? ????????}?? ?? ????????Set<String>?patterns?=?getMappingPathPatterns(mapping);?? ????????for?(String?pattern?:?patterns)?{?? ????????????if?(!getPathMatcher().isPattern(pattern))?{?? ????????????????this.urlMap.add(pattern,?mapping);?? ????????????}?? ????????}?? ????}??
这里的this.handlerMethods就包含了所有管辖的bean,key为RequestMappingInfo对象,[email protected]d构建的HandlerMethod。? 如下所示:?
Java代码?? /**? ?????*?Create?the?HandlerMethod?instance.? [email protected]al?handler?instance? [email protected] [email protected] ?????*/?? ????protected?HandlerMethod?createHandlerMethod(Object?handler,?Method?method)?{?? ????????HandlerMethod?handlerMethod;?? ????????if?(handler?instanceof?String)?{?? ????????????String?beanName?=?(String)?handler;?? ????????????handlerMethod?=?new?HandlerMethod(beanName,?getApplicationContext(),?method);?? ????????}?? ????????else?{?? ????????????handlerMethod?=?new?HandlerMethod(handler,?method);?? ????????}?? ????????return?handlerMethod;?? ????}??
至此,RequestMappingHandlerMapping的初始化注册工作就完成了。然后就是等待请求,访问? http://localhost:8080/string?name=aa,RequestMappingHandlerMapping会匹配到由StringAction对象和它的包含注释的方法testMessageConverter构建的HandlerMethod对象,该对象将作为handler,然后再遍历HandlerAdapter判断它们是否支持这个handler,RequestMappingHandlerAdapter的判断依据为是否是HandlerMethod 类型(在AbstractHandlerMethodAdapter类中):?
Java代码?? public?final?boolean?supports(Object?handler)?{?? ????????return?handler?instanceof?HandlerMethod?&&?supportsInternal((HandlerMethod)?handler);?? ????}?? ?
|
|
|