前面对springMV处理请求的过程做了整体的描述,以及对它的理解,但对于寻找Handler的细节,还是有必要在仔细研究一下,加深记忆!
总体步骤
遍历所有的HandlerMapping
在遍历过程中,通过每个HandlerMapping的getHandler方法寻找Handler对象
在getHandler方法中,调用geHandlertInternal方法实际的寻找Handler对象,该方法会根据不同的方式来寻找不同类型的Handler。
问题
首先要遍历HandlerMapping,那HandlerMapping是怎么来的?先上代码
这个方法是在著名的DispatcherServlet里面,该方法由initStrategies方法的调用,而initStrategies又由onRefresh来调用,onRefresh方法是重写父类的方法,DispatherServlet的父类FrameworkServlet在初始化WebApplicationContext时,调用这个钩子方法,由子类来实现,即现在的DispatherServlet。记住这点,后面学习ApplicationContext的时候就有例子可以参考了。
在初始化的开始,对是否加载所有的HandlerMapping做了判断,如果不加载全部的HandlerMapping,就会加载一个名为“handlerMapping”的Bean作为一个单例的mapping,如果这个Bean也没有找到,则会加载默认的handlerMapping。
加载所有HandlerMapping的方式,就是利用反射来加载所有实现了HandlerMapping接口的类。
另外,对于WebApplicationContext有些思考:其实WebApplicationContext充当了一个适配器的角色,它一方面集成了Spring的ApplicationContext,也就意味着和Spring做了集成;另外一方面它又包含了ServletContext,这就意味着又集成了Servlet容器的上下文,最后就是我们的Servlet容器和web 应用拥有了强大的spring的能力。
默认的HandlerMapping有哪些?
所谓默认的HandlerMapping,我指的时spring自带的HandlerMapping。上图:
从上图看,总共有七个HandlerMapping,现在来归纳一下:
AbstractHandlerMapping是最高层的抽象类,是积累它本身不能算是一种HandlerMapping。
AbstractUrlHandlerMapping是一种HandlerMapping,所谓一种,指的的是通过请求匹配Bean的方式,看类名就知道这是通过url来找匹配的Bean作为Handler;其中SimpleUrlHandlerMapping就是它的实现类。
AbstractDetectingUrlHandlerMapping虽然也是AbstractUrlHandlerMapping的实现类,但它是一种新的寻找HandlerBean的方式,所以我认为它是一种HandlerMapping,其中BeanNameUrlHandlerMapping就是它的实现类,BeanNameUrlHandlerMapping的匹配Bean的方式就是通过将url作为beanName,来加载Bean。
AbstractHandlerMethodMapping是一种新的Mapping方式,mapping过程是先通过url寻找Handler对象,然后再通过url匹配处理请求的方法,并将该方法封装成HandlerMethod对象,来具体处理请求。
最后的MatchableHandlerMapping,其实并不是一个新的mapping方式,只是增加了一个请求匹配的内部功能。
总上来看,springMvc中一共提供了3种寻找Handler的方式,一是通过url匹配Handler对象,二是通过url匹配HandlerMethod对象,三是通过将url作为beanName来匹配Handler对象。