继承关系图:
HandlerMapping的作用是根据请求URL找到对应的Handler也就是Controller。
HandlerMapping是一个接口,在接口中定义了一个getHandler方法,通过这个方法可以获得与HTTP请求对应的HandlerExecutionChain,这个HandlerExecutionChain中封装了具体的Controller对象,还设置了一个拦截器链,通过这个拦截器链中的拦截器可以为Handler对象提供功能的增强。
1 | public interface HandlerMapping { |
一、Handler的注册
1.SimpleUrlHandlerMapping
以SimpleUrlHandlerMapping为例,看一下Hanlder的注册过程。
(1)持有了一个urlMap字段,保存URL和Hanlder的映射关系。
(2)Hanlder的注册过程是在initApplicationContext方法中调用的。initApplicationContext方法中先调用了父类AbstractUrlHandlerMapping 的initApplicationContext方法,这个方法中主要是对拦截器相关的设置。然后调用了registerHandlers方法注册handler。
(3)在registerHandlers方法中,调用了父类AbstractUrlHandlerMapping的registerHandler方法对handler进行注册。
1 | public class SimpleUrlHandlerMapping extends AbstractUrlHandlerMapping { |
2.AbstractUrlHandlerMapping
(1)在AbstractUrlHandlerMapping中,同样持有了一个保存URL和Handler映射关系的字段handlerMap。
(2)在registerHandler方法中:
- 首先设置一个变量resolvedHandler,将当前传入的handler赋给它;
- 接着判断是否根据bean名称进行映射,如果是将会直接从容器中获取Handler赋给resolvedHandler;
- 创建变量mappedHandler,表示是从handlerMap根据URL获取的Handler;如果mappedHandler不为空,会与从容器中根据bean获取的Handler对比是否一致,如果不一致将会报错。
- 如果mappedHandler为空,说明Handler还未注册,会判断URL是否是’/‘或者’/*’,并分别设置到ROOT或者DefaultHandler中,如果只是普通的URL,因为还没有注册Handler,就把resolvedHandler注册到handlerMap中。
1 | public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping implements MatchableHandlerMapping { |
二、Handler的查找过程
1.DispatcherServlet
回到DispatcherServlet,对HTTP请求的处理是在doService中完成的,那么就从这个方法入手,看一下DispatcherServlet是如何根据请求获取对应的Handler(Controller)处理HTTP请求的。
(1)在doService方法中会调用doDispatch方法,这里是分发请求的入口。
(2)在doDispatch方法中,调用了自己的getHandler根据请求获取对应的HandlerExecutionChain,在getHandler方法中遍历handlerMappings寻找对应的HandlerExecutionChain,具体的查找过程由子类实现,在子类的getHandler方法中完成。
1 | // 根据请求得到对应的HandlerExecutionChain |
1 |
|
(3)HandlerExecutionChain获取成功后,会调用getHandlerAdapter方法获取HandlerAdapter,最后由HandlerAdapter调用handle方法处理请求。
1 | //获取HandlerAdapter |
整体代码:
1 | public class DispatcherServlet extends FrameworkServlet { |
以SimpleControllerHandlerAdapter为例,看一下Adapter处理请求的方法:
1 | public class SimpleControllerHandlerAdapter implements HandlerAdapter { |
2.AbstractHandlerMapping
在上一步中,getHandler获取HandlerExecutionChain的过程由子类实现的,同样以SimpleUrlHandlerMapping为例,由继承关系图可知AbstractHandlerMapping是SimpleUrlHandlerMapping的父类,getHandler是在父类中实现的,那么就从AbstractHandlerMapping入手看一下AbstractHandlerMapping中是如何获取HandlerExecutionChain的。
(1)在getHandler方法中,首先调用了getHandlerInternal方法,获取Handler,这个方法是在AbstractUrlHandlerMapping中实现的。
(2)Handler获取之后,将Handler封装到了HandlerExecutionChain中并返回,HandlerExecutionChain中包含了Controller的定义和一个拦截器链。
1 | public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport implements HandlerMapping, Ordered { |
HandlerExecutionChain中的成员变量:
1 | public class HandlerExecutionChain { |
3.AbstractUrlHandlerMapping
(1)在AbstractUrlHandlerMapping中的getHandlerInternal方法中调用了lookupHandler方查找当前请求对应的Handler。
(2)查找Handler之后判断是否为空,如果为空,判断当前请求是否是”/“,如果是就使用RootHandler,如果RootHandler也为空,就使用默认的Handler.
1 | public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping implements MatchableHandlerMapping { |
参考:
spring技术内幕:深入解析spring架构与设计原理
SpringMVC工作原理之二:HandlerMapping和HandlerAdapter
Spring版本:5.0.5