当前位置: 代码迷 >> VC/MFC >> SpringMVC源码小结(一)HandlerMapping和HandlerAdapter入门
  详细解决方案

SpringMVC源码小结(一)HandlerMapping和HandlerAdapter入门

热度:164   发布时间:2016-05-02 03:17:30.0
SpringMVC源码总结(一)HandlerMapping和HandlerAdapter入门

?

SpringMVC源码总结(一)HandlerMapping和HandlerAdapter入门

?
?
刚接触SpringMVC,对它的xml文件配置一直比较模模糊糊,最近花了一点时间稍微看了下源代码,再加上调试,开始逐渐理解它,网上的类似的内容有很多,写本文主要是自己加深一下理解。本文适合用过SpringMVC的开发者,言归正传,首先搭建一个最简单的工程体验一下。?

该工程是基于maven的,pom配置不再说明,所使用的spring版本4.0.5。?
首先是web.xml文件配置,最简单的配置?

Java代码??收藏代码

  1. <!DOCTYPE?web-app?PUBLIC??

  2. ?"-//Sun?Microsystems,?Inc.//DTD?Web?Application?2.3//EN"??

  3. ?"http://java.sun.com/dtd/web-app_2_3.dtd"?>??

  4. ??

  5. <web-app>??

  6. ??<display-name>Archetype?Created?Web?Application</display-name>??

  7. ??<servlet>??

  8. ????????<servlet-name>mvc</servlet-name>??

  9. ????????<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>??

  10. ????????<load-on-startup>1</load-on-startup>??

  11. ????</servlet>??

  12. ??

  13. ????<servlet-mapping>??

  14. ????????<servlet-name>mvc</servlet-name>??

  15. ????????<url-pattern>/*</url-pattern>??

  16. ????</servlet-mapping>??

  17. </web-app>??


然后是mvc-servlet.xml文件的配置,上面配置DispatcherServlet会默认加载[servlet-name]-servlet.xml文件。对于我的配置,会去加载mvc-servlet.xml文件。?
mvc-servlet.xml文件的内容:
?

Java代码??收藏代码

  1. <?xml?version="1.0"?encoding="UTF-8"??>??

  2. <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"??

  3. ????xsi:schemaLocation="http://www.springframework.org/schema/beans??

  4. ????http://www.springframework.org/schema/beans/spring-beans-3.1.xsd??

  5. ????http://www.springframework.org/schema/mvc??

  6. ????http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd??

  7. ????http://www.springframework.org/schema/util??

  8. ????http://www.springframework.org/schema/util/spring-util-2.0.xsd??

  9. ????http://www.springframework.org/schema/context???

  10. ????http://www.springframework.org/schema/context/spring-context-3.2.xsd">??

  11. ??

  12. ????<bean?name="/index"?class="com.lg.mvc.HomeAction"></bean>??

  13. ????<bean?class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">??

  14. ????????<property?name="templateLoaderPath"?value="/WEB-INF/views"?/>??

  15. ????????<property?name="defaultEncoding"?value="utf-8"?/>??

  16. ????????<property?name="freemarkerSettings">??

  17. ????????????<props>??

  18. ????????????????<prop?key="locale">zh_CN</prop>??

  19. ????????????</props>??

  20. ????????</property>??

  21. ????</bean>??

  22. ????<bean?class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">??

  23. ????????<property?name="suffix"?value=".html"?/>??

  24. ????????<property?name="contentType"?value="text/html;charset=utf-8"?/>??

  25. ????????<property?name="requestContextAttribute"?value="request"?/>??

  26. ????????<property?name="exposeRequestAttributes"?value="true"?/>??

  27. ????????<property?name="exposeSessionAttributes"?value="true"?/>??

  28. ????</bean>??

  29. </beans>??


在该配置中定义了一个HomeAction的Bean。内容为:?

Java代码??收藏代码

  1. package?com.lg.mvc;??

  2. ??

  3. import?javax.servlet.http.HttpServletRequest;??

  4. import?javax.servlet.http.HttpServletResponse;??

  5. ??

  6. import?org.springframework.web.servlet.ModelAndView;??

  7. import?org.springframework.web.servlet.mvc.Controller;??

  8. ??

  9. public?class?HomeAction?implements?Controller{??

  10. ??

  11. [email protected]

  12. ????public?ModelAndView?handleRequest(HttpServletRequest?request,??

  13. ????????????HttpServletResponse?response)?throws?Exception?{??

  14. ????????return?new?ModelAndView("hello");??

  15. ????}??

  16. }??


这是最原始的mvc做法,要继承Controller接口,先从原始的说起,[email protected]@[email protected]??配置有一个关键的属性name="/index"。?
WEB-INF/view目录下有一个简单的hello.html,内容为:
?

Java代码??收藏代码

  1. <html>??

  2. ????<head>??

  3. ??????

  4. ????</head>??

  5. ????<body>??

  6. ????????hello?lg?!??

  7. ????</body>??

  8. </html>??


至此该工程就写完了,部署到tomcat中,项目路径为/,运行一下。?
访问 http://localhost:8080/index?
?
至此整个工程就算搭建成功了。?

下面就要说说原理了。?
用过python Django框架的都知道Django对于访问方式的配置就是,一个url路径和一个函数配对,你访问这个url,就会直接调用这个函数,简单明了。对于java的面向对象来说,就要分两步走。第一步首先要找到是哪个对象,即handler,本工程的handler则是HomeAction对象。第二步要找到访问的函数,即HomeAction的handleRequest方法。所以就出现了两个源码接口 HandlerMapping和HandlerAdapter,前者负责第一步,后者负责第二步。借用网上的SpringMVC架构图。?

HandlerMapping接口的实现(只举了我认识的几个) :?

    • BeanNameUrlHandlerMapping :通过对比url和bean的name找到对应的对象?


    • SimpleUrlHandlerMapping :也是直接配置url和对应bean,比BeanNameUrlHandlerMapping功能更多?


    • DefaultAnnotationHandlerMapping : [email protected],已过时?


    • RequestMappingHandlerMapping :取代了上面一个?



HandlerAdapter 接口实现:?

    • HttpRequestHandlerAdapter : 要求handler实现HttpRequestHandler接口,该接口的方法为????????? void handleRequest(HttpServletRequest request, HttpServletResponse response)也就是? handler必须有一个handleRequest方法?



    • SimpleControllerHandlerAdapter:要求handler实现Controller接口,该接口的方法为ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response),也就是本工程采用的?



    • AnnotationMethodHandlerAdapter :和上面的DefaultAnnotationHandlerMapping配对使用的,也已过时?



    • RequestMappingHandlerAdapter : 和上面的RequestMappingHandlerMapping配对使用,[email protected]



先简单的说下这个工程的流程,访问http://localhost:8080/index首先由DispatcherServlet进行转发,通过BeanNameUrlHandlerMapping(含有 /index->HomeAction的配置),找到了HomeAction,然后再拿HomeAction和每个adapter进行适配,由于HomeAction实现了Controller接口,所以最终会有SimpleControllerHandlerAdapter来完成对HomeAction的handleRequest方法的调度。然后就顺利的执行了我们想要的方法,后面的内容不在本节中说明。?

了解了大概流程,然后就需要看源代码了。?
首先就是SpringMVC的入口类,DispatcherServlet,它实现了Servlet接口,不再详细说DispatcherServlet的细节,不然又是一大堆的内容。每次请求都会调用它的doService->doDispatch,我们关注的重点就在doDispatch方法中。
?

Java代码??收藏代码

  1. protected?void?doDispatch(HttpServletRequest?request,?HttpServletResponse?response)?throws?Exception?{??

  2. ????????HttpServletRequest?processedRequest?=?request;??

  3. ????????HandlerExecutionChain?mappedHandler?=?null;??

  4. ????????boolean?multipartRequestParsed?=?false;??

  5. ??

  6. ????????WebAsyncManager?asyncManager?=?WebAsyncUtils.getAsyncManager(request);??

  7. ??

  8. ????????try?{??

  9. ????????????ModelAndView?mv?=?null;??

  10. ????????????Exception?dispatchException?=?null;??

  11. ??

  12. ????????????try?{??

  13. ????????????????processedRequest?=?checkMultipart(request);??

  14. ????????????????multipartRequestParsed?=?(processedRequest?!=?request);??

  15. ??????????????????????//这个是重点,第一步由HandlerMapping找到对应的handler??

  16. ????????????????//?Determine?handler?for?the?current?request.??

  17. ????????????????mappedHandler?=?getHandler(processedRequest);??

  18. ????????????????if?(mappedHandler?==?null?||?mappedHandler.getHandler()?==?null)?{??

  19. ????????????????????noHandlerFound(processedRequest,?response);??

  20. ????????????????????return;??

  21. ????????????????}??

  22. ??

  23. ????????????????//?Determine?handler?adapter?for?the?current?request.??

  24. ???????????????????????//这是第二步,找到合适的HandlerAdapter,然后由它来调度执行handler的方法??

  25. ????????????????HandlerAdapter?ha?=?getHandlerAdapter(mappedHandler.getHandler());??

  26. ??

  27. ????????????????//?Process?last-modified?header,?if?supported?by?the?handler.??

  28. ????????????????String?method?=?request.getMethod();??

  29. ????????????????boolean?isGet?=?"GET".equals(method);??

  30. ????????????????if?(isGet?||?"HEAD".equals(method))?{??

  31. ????????????????????long?lastModified?=?ha.getLastModified(request,?mappedHandler.getHandler());??

  32. ????????????????????if?(logger.isDebugEnabled())?{??

  33. ????????????????????????logger.debug("Last-Modified?value?for?["?+?getRequestUri(request)?+?"]?is:?"?+?lastModified);??

  34. ????????????????????}??

  35. ????????????????????if?(new?ServletWebRequest(request,?response).checkNotModified(lastModified)?&&?isGet)?{??

  36. ????????????????????????return;??

  37. ????????????????????}??

  38. ????????????????}??

  39. ??

  40. ????????????????if?(!mappedHandler.applyPreHandle(processedRequest,?response))?{??

  41. ????????????????????return;??

  42. ????????????????}??

  43. ??

  44. ????????????????try?{??

  45. ????????????????????//?Actually?invoke?the?handler.??

  46. ????????????????????mv?=?ha.handle(processedRequest,?response,?mappedHandler.getHandler());??

  47. ????????????????}??

  48. ????????????????finally?{??

  49. ????????????????????if?(asyncManager.isConcurrentHandlingStarted())?{??

  50. ????????????????????????return;??

  51. ????????????????????}??

  52. ????????????????}??

  53. ??

  54. ????????????????applyDefaultViewName(request,?mv);??

  55. ????????????????mappedHandler.applyPostHandle(processedRequest,?response,?mv);??

  56. ????????????}??

  57. ????????????catch?(Exception?ex)?{??

  58. ????????????????dispatchException?=?ex;??

  59. ????????????}??

  60. ????????????processDispatchResult(processedRequest,?response,?mappedHandler,?mv,?dispatchException);??

  61. ????????}??

  62. ????????catch?(Exception?ex)?{??

  63. ????????????triggerAfterCompletion(processedRequest,?response,?mappedHandler,?ex);??

  64. ????????}??

  65. ????????catch?(Error?err)?{??

  66. ????????????triggerAfterCompletionWithError(processedRequest,?response,?mappedHandler,?err);??

  67. ????????}??

  68. ????????finally?{??

  69. ????????????if?(asyncManager.isConcurrentHandlingStarted())?{??

  70. ????????????????//?Instead?of?postHandle?and?afterCompletion??

  71. ????????????????mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest,?response);

  72. ????????????????return;??

  73. ????????????}??

  74. ????????????//?Clean?up?any?resources?used?by?a?multipart?request.??

  75. ????????????if?(multipartRequestParsed)?{??

  76. ????????????????cleanupMultipart(processedRequest);??

  77. ????????????}??

  78. ????????}??

  79. ????}??


第一步详细查看:?

Java代码??收藏代码

  1. protected?HandlerExecutionChain?getHandler(HttpServletRequest?request)?throws?Exception?{?

  2. ????????for?(HandlerMapping?hm?:?this.handlerMappings)?{??

  3. ????????????if?(logger.isTraceEnabled())?{??

  4. ????????????????logger.trace(??

  5. ????????????????????????"Testing?handler?map?["?+?hm?+?"]?in?DispatcherServlet?with?name?'"?+?getServletName()?+?"'");??

  6. ????????????}??

  7. ????????????HandlerExecutionChain?handler?=?hm.getHandler(request);??

  8. ????????????if?(handler?!=?null)?{??

  9. ????????????????return?handler;??

  10. ????????????}??

  11. ????????}??

  12. ????????return?null;??

  13. ????}??


可以看到就是通过遍历所有已注册的HandlerMapping来找到对应的handler,然后构建出一个HandlerExecutionChain,它包含了handler和HandlerMapping本身的一些拦截器,如下?

Java代码??收藏代码

  1. public?class?HandlerExecutionChain?{??

  2. ??

  3. ????private?final?Object?handler;??

  4. ??

  5. ????private?HandlerInterceptor[]?interceptors;??

  6. ??

  7. ????private?List<HandlerInterceptor>?interceptorList;??

  8. ??????????

  9. ????????//其他代码省略??

  10. }??


其中HandlerMapping的getHandler实现:?

Java代码??收藏代码

  1. public?final?HandlerExecutionChain?getHandler(HttpServletRequest?request)?throws?Exception?{??

  2. ????????Object?handler?=?getHandlerInternal(request);??

  3. ????????if?(handler?==?null)?{??

  4. ????????????handler?=?getDefaultHandler();??

  5. ????????}??

  6. ????????if?(handler?==?null)?{??

  7. ????????????return?null;??

  8. ????????}??

  9. ????????//?Bean?name?or?resolved?handler???

  10. ????????if?(handler?instanceof?String)?{??

  11. ????????????String?handlerName?=?(String)?handler;??

  12. ????????????handler?=?getApplicationContext().getBean(handlerName);??

  13. ????????}??

  14. ????????return?getHandlerExecutionChain(handler,?request);??

  15. ????}??


这里的getHandlerInternal(request)是个抽象方法,由具体的HandlerMapping来实现,获取到的handler如果为空,则获取默认配置的handler,如果handler为String类型,则表示这个则会去Spring容器里面去找这样名字的bean。?
再看下BeanNameUrlHandlerMapping的getHandlerInternal(request)的具体实现(通过一系列的接口设计,之后再好好看看这个设计,到BeanNameUrlHandlerMapping这只用实现该方法中的一部分),如下
?

Java代码??收藏代码

  1. public?class?BeanNameUrlHandlerMapping?extends?AbstractDetectingUrlHandlerMapping?{??

  2. ??

  3. ????/**?

  4. ?????*?Checks?name?and?aliases?of?the?given?bean?for?URLs,?starting?with?"/".?

  5. ?????*/??

  6. [email protected]

  7. ????protected?String[]?determineUrlsForHandler(String?beanName)?{??

  8. ????????List<String>?urls?=?new?ArrayList<String>();??

  9. ????????if?(beanName.startsWith("/"))?{??

  10. ????????????urls.add(beanName);??

  11. ????????}??

  12. ????????String[]?aliases?=?getApplicationContext().getAliases(beanName);??

  13. ????????for?(String?alias?:?aliases)?{??

  14. ????????????if?(alias.startsWith("/"))?{??

  15. ????????????????urls.add(alias);??

  16. ????????????}??

  17. ????????}??

  18. ????????return?StringUtils.toStringArray(urls);??

  19. ????}??

  20. ??

  21. }??


这里面注释说,bean的name必须以/开头,它才处理,将信息存储在Map<String, Object> handlerMap中,对于本工程来说就是{'/index':HomeAction对象}。?
至此这里完成了第一步,下面开始第二步,即方法HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());的具体实现:
?

Java代码??收藏代码

  1. protected?HandlerAdapter?getHandlerAdapter(Object?handler)?throws?ServletException?{??

  2. ????????for?(HandlerAdapter?ha?:?this.handlerAdapters)?{??

  3. ????????????if?(logger.isTraceEnabled())?{??

  4. ????????????????logger.trace("Testing?handler?adapter?["?+?ha?+?"]");??

  5. ????????????}??

  6. ????????????if?(ha.supports(handler))?{??

  7. ????????????????return?ha;??

  8. ????????????}??

  9. ????????}??

  10. ????????throw?new?ServletException("No?adapter?for?handler?["?+?handler?+??

  11. ????????????????"]:?The?DispatcherServlet?configuration?needs?to?include?a?HandlerAdapter?that?supports?this?handler");??

  12. ????}??


遍历所有的HandlerAdapter,判断他们是否支持这个handler。?
我们来看下HttpRequestHandlerAdapter的supports(handler)方法:
?

Java代码??收藏代码

  1. public?class?HttpRequestHandlerAdapter?implements?HandlerAdapter?{??

  2. ??

  3. [email protected]

  4. ????public?boolean?supports(Object?handler)?{??

  5. ??????????//就是判断handler是否实现了HttpRequestHandler接口??

  6. ????????return?(handler?instanceof?HttpRequestHandler);??

  7. ????}??

  8. ??

  9. [email protected]

  10. ????public?ModelAndView?handle(HttpServletRequest?request,?HttpServletResponse?response,?Object?handler)??

  11. ????????????throws?Exception?{??

  12. ???????????//若handler实现了HttpRequestHandler接口,则调用该接口的方法,执行我们在该方法中写的业务逻辑??

  13. ????????((HttpRequestHandler)?handler).handleRequest(request,?response);??

  14. ????????return?null;??

  15. ????}??

  16. ??

  17. [email protected]

  18. ????public?long?getLastModified(HttpServletRequest?request,?Object?handler)?{??

  19. ????????if?(handler?instanceof?LastModified)?{??

  20. ????????????return?((LastModified)?handler).getLastModified(request);??

  21. ????????}??

  22. ????????return?-1L;??

  23. ????}??

  24. ??

  25. }??


同理SimpleControllerHandlerAdapter也是这样类似的逻辑?

Java代码??收藏代码

  1. public?class?SimpleControllerHandlerAdapter?implements?HandlerAdapter?{??

  2. ??

  3. [email protected]

  4. ????public?boolean?supports(Object?handler)?{??

  5. ????????return?(handler?instanceof?Controller);??

  6. ????}??

  7. ??

  8. [email protected]

  9. ????public?ModelAndView?handle(HttpServletRequest?request,?HttpServletResponse?response,?Object?handler)??

  10. ????????????throws?Exception?{??

  11. ??

  12. ????????return?((Controller)?handler).handleRequest(request,?response);??

  13. ????}??

  14. ??

  15. [email protected]

  16. ????public?long?getLastModified(HttpServletRequest?request,?Object?handler)?{??

  17. ????????if?(handler?instanceof?LastModified)?{??

  18. ????????????return?((LastModified)?handler).getLastModified(request);??

  19. ????????}??

  20. ????????return?-1L;??

  21. ????}??

  22. ??

  23. }??


剩余两个AnnotationMethodHandlerAdapter和RequestMappingHandlerAdapter就比较复杂,我也没看。?
按照本工程的配置,则SimpleControllerHandlerAdapter是支持HomeAction的,然后就会执行SimpleControllerHandlerAdapter的handle(processedRequest, response, mappedHandler.getHandler())方法。本质上就会调用HomeAction实现Controller接口的方法。至此就分析完了。?
了解过程了之后,然后就是最重要的也是经常配置出问题的地方。DispatcherServlet的handlerMappings和handlerAdapters的来源问题。?

DispatcherServlet初始化的时候,会调用一个方法如下:?

Java代码??收藏代码

  1. protected?void?initStrategies(ApplicationContext?context)?{??

  2. ????????initMultipartResolver(context);??

  3. ????????initLocaleResolver(context);??

  4. ????????initThemeResolver(context);??

  5. //初始化一些HandlerMapping??

  6. ????????initHandlerMappings(context);??

  7. //初始化一些HandlerAdapter??

  8. ????????initHandlerAdapters(context);??

  9. ????????initHandlerExceptionResolvers(context);??

  10. ????????initRequestToViewNameTranslator(context);??

  11. ????????initViewResolvers(context);??

  12. ????????initFlashMapManager(context);??

  13. ????}??


这里可以看到,它会初始化一些HandlerMapping和HandlerAdapter,这两个方法非常重要,理解了这两个方法你就会知道,配置不对问题出在哪里,下面具体看下这两个方法:?

Java代码??收藏代码

  1. private?void?initHandlerMappings(ApplicationContext?context)?{??

  2. ????????this.handlerMappings?=?null;??

  3. ??

  4. ????????if?(this.detectAllHandlerMappings)?{??

  5. ????????????//?Find?all?HandlerMappings?in?the?ApplicationContext,?including?ancestor?contexts.??

  6. ????????????Map<String,?HandlerMapping>?matchingBeans?=??

  7. ????????????????????BeanFactoryUtils.beansOfTypeIncludingAncestors(context,?HandlerMapping.class,?true,?false);??

  8. ????????????if?(!matchingBeans.isEmpty())?{??

  9. ????????????????this.handlerMappings?=?new?ArrayList<HandlerMapping>(matchingBeans.values());??

  10. ????????????????//?We?keep?HandlerMappings?in?sorted?order.??

  11. ????????????????OrderComparator.sort(this.handlerMappings);??

  12. ????????????}??

  13. ????????}??

  14. ????????else?{??

  15. ????????????try?{??

  16. ????????????????HandlerMapping?hm?=?context.getBean(HANDLER_MAPPING_BEAN_NAME,?HandlerMapping.class);??

  17. ????????????????this.handlerMappings?=?Collections.singletonList(hm);??

  18. ????????????}??

  19. ????????????catch?(NoSuchBeanDefinitionException?ex)?{??

  20. ????????????????//?Ignore,?we'll?add?a?default?HandlerMapping?later.??

  21. ????????????}??

  22. ????????}??

  23. ??

  24. ????????//?Ensure?we?have?at?least?one?HandlerMapping,?by?registering??

  25. ????????//?a?default?HandlerMapping?if?no?other?mappings?are?found.??

  26. ????????if?(this.handlerMappings?==?null)?{??

  27. ????????????this.handlerMappings?=?getDefaultStrategies(context,?HandlerMapping.class);??

  28. ????????????if?(logger.isDebugEnabled())?{??

  29. ????????????????logger.debug("No?HandlerMappings?found?in?servlet?'"?+?getServletName()?+?"':?using?default");??

  30. ????????????}??

  31. ????????}??

  32. ????}??


detectAllHandlerMappings是DispatcherServlet的一个属性,你是可以在web.xml中配置的,默认是true,如果为true,则会去从本工程mvc-servlet.xml文件中去探测所有实现了HandlerMapping的bean,如果有,则加入DispatcherServlet的handlerMappings中。如果detectAllHandlerMappings为false,则直接去容器中找id="handlerMapping"且实现了HandlerMapping的bean.如果以上都没找到,则会去加载默认的HandlerMapping。?

Java代码??收藏代码

  1. /**?Detect?all?HandlerMappings?or?just?expect?"handlerMapping"?bean??*/??

  2. ????private?boolean?detectAllHandlerMappings?=?true;??


本工程由于没有配置HandlerMapping,所以它会去加载默认的,下面看看默认的配置是什么?

Java代码??收藏代码

  1. protected?<T>?List<T>?getDefaultStrategies(ApplicationContext?context,?Class<T>?strategyInterface)?{??

  2. ????????String?key?=?strategyInterface.getName();??

  3. //defaultStrategies存储了默认的配置??

  4. ????????String?value?=?defaultStrategies.getProperty(key);??

  5. ????????if?(value?!=?null)?{??

  6. ????????????String[]?classNames?=?StringUtils.commaDelimitedListToStringArray(value);??

  7. ????????????List<T>?strategies?=?new?ArrayList<T>(classNames.length);??

  8. ????????????for?(String?className?:?classNames)?{??

  9. ????????????????try?{??

  10. ????????????????????Class<?>?clazz?=?ClassUtils.forName(className,?DispatcherServlet.class.getClassLoader());??

  11. ????????????????????Object?strategy?=?createDefaultStrategy(context,?clazz);??

  12. ????????????????????strategies.add((T)?strategy);??

  13. ????????????????}??

  14. ????????????????catch?(ClassNotFoundException?ex)?{??

  15. ????????????????????throw?new?BeanInitializationException(??

  16. ????????????????????????????"Could?not?find?DispatcherServlet's?default?strategy?class?["?+?className?+??

  17. ????????????????????????????????????"]?for?interface?["?+?key?+?"]",?ex);??

  18. ????????????????}??

  19. ????????????????catch?(LinkageError?err)?{??

  20. ????????????????????throw?new?BeanInitializationException(??

  21. ????????????????????????????"Error?loading?DispatcherServlet's?default?strategy?class?["?+?className?+??

  22. ????????????????????????????????????"]?for?interface?["?+?key?+?"]:?problem?with?class?file?or?dependent?class",?err);??

  23. ????????????????}??

  24. ????????????}??

  25. ????????????return?strategies;??

  26. ????????}??

  27. ????????else?{??

  28. ????????????return?new?LinkedList<T>();??

  29. ????????}??

  30. ????}??


继续看看defaultStrategies是如何初始化的:?

Java代码??收藏代码

  1. private?static?final?Properties?defaultStrategies;??

  2. ??

  3. ????static?{??

  4. ????????//?Load?default?strategy?implementations?from?properties?file.??

  5. ????????//?This?is?currently?strictly?internal?and?not?meant?to?be?customized??

  6. ????????//?by?application?developers.??

  7. ????????try?{??

  8. //这里的DEFAULT_STRATEGIES_PATH就是DispatcherServlet.properties??

  9. ????????????ClassPathResource?resource?=?new?ClassPathResource(DEFAULT_STRATEGIES_PATH,?DispatcherServlet.class);??

  10. ????????????defaultStrategies?=?PropertiesLoaderUtils.loadProperties(resource);??

  11. ????????}??

  12. ????????catch?(IOException?ex)?{??

  13. ????????????throw?new?IllegalStateException("Could?not?load?'DispatcherServlet.properties':?"?+?ex.getMessage());??

  14. ????????}??

  15. ????}??


这里使用静态代码块来加载配置文件DispatcherServlet.properties,它所在位置就是和DispatcherServlet同一目录下面的,如下图所示:?


该默认的配置文件的内容如下:?

Java代码??收藏代码

  1. #?Default?implementation?classes?for?DispatcherServlet's?strategy?interfaces.??

  2. #?Used?as?fallback?when?no?matching?beans?are?found?in?the?DispatcherServlet?context.??

  3. #?Not?meant?to?be?customized?by?application?developers.??

  4. ??

  5. org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver??

  6. ??

  7. org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver??

  8. ??

  9. #这里就是默认的HandlerMapping的配置??

  10. org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\??

  11. ????org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping??

  12. #这里就是默认的HandlerAdapter的配置??

  13. org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\??

  14. ????org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\??

  15. ????org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter??

  16. ??

  17. org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerExceptionResolver,\??

  18. ????org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\??

  19. ????org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver??

  20. ??

  21. org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator??

  22. ??

  23. org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver??

  24. ??

  25. org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager??


也就是说,当你什么都没有配置时,默认会加载以上的配置。正是由于有了上述默认配置的BeanNameUrlHandlerMapping(它要求name必须是以/开头的),它才会存储我们在mvc-servlet.xml中配置的<bean name="/index" class="com.lg.mvc.HomeAction"></bean>,同样正是由于有了SimpleControllerHandlerAdapter(由于handler实现了Controller接口,所以它的support方法支持我们的handler),才会调度执行HomeAction的handleRequest方法
  相关解决方案