SpringMVC源码解析-doDispatch方法

Posted 程序员啊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringMVC源码解析-doDispatch方法相关的知识,希望对你有一定的参考价值。

SpringMVC源码解析-doDispatch方法_spring

断点入口

容器启动后,我们根据URL访问接口,我们的DispatcherServlet都做了什么操作呢?

我们可以​​在DispatcherServlet​​类中的​​doDispatch​​方法中打断点来详细查看;

为什么直接在doDispatch方法中打断点?

SpringMVC源码解析-doDispatch方法_post请求_02


由图可知​​DispatcherServlet​​继承自​​HttpServlet​​抽象类,我们的get/post请求分别会请求其​​doGet​​和​​doPost​​方法;

​DispatcherServlet​​的父类​​FrameworkServlet​​中对​​doGet​​和​​doPost​​方法进行了重写,都会执行​​this.processRequest(request, response)​​;

protected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException 
this.processRequest(request, response);


protected final void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
this.processRequest(request, response);

​processRequest​​方法会执行方法:​​this.doService(request, response)​​;而​​FrameworkServlet​​中的​​doService​​是抽象的,具体实现方法是在​​DispatcherServlet​​中;

protected abstract void doService(HttpServletRequest request, HttpServletResponse response) throws Exception;

而​​DispatcherServlet​​中的​​doService​​则执行了关键方法:​​this.doDispatch(request, response)​​。

所以我们执行把断点打在此方法处,看​​DispatcherServlet​​具体都做了什么操作。

doDispatch方法

前言:除了新建一个类使用@Controller注解,还有什么方法能够新建一个Controller呢?

实现Controller接口或者是实现HttpRequestHandler接口也是可以做到的,重写其handleRequest方法,不要忘记使用Component("/URI")注解哦。

执行doDispatch,直接看主要方法 :getHandler

SpringMVC源码解析-doDispatch方法_spring_03


Spring是通过HandlerMapping对象来查找Handler(就是Controller)的,通过不同的HandlerMapping实现来查找不同方式创建的Controller;

SpringMVC源码解析-doDispatch方法_父类_04


SpringMVC源码解析-doDispatch方法_父类_05


通过断点可以看到默认会有两个HandlerMapping的实现:RequestMappingHandlerMapping和BeanNameUrlHandlerMapping;

所有加了@Controller的Controller对象会放在RequestMappingHandlerMapping的父类AbstractHandlerMethodMapping的内部类MappingRegistry的一个Map属性中去,

而所以以BeanName形式定义的Controller对象会放在BeanNameUrlHandlerMapping的父类AbstractUrlHandlerMapping的Map属性中去。

class MappingRegistry 
private final MultiValueMap<String, T> pathLookup = new LinkedMultiValueMap();

public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping implements MatchableHandlerMapping 
private final Map<String, Object> handlerMap = new LinkedHashMap();

通过HandlerMapping .getHandler(request)方法返回一个封装了Handler的HandlerExecutionChain对象并返回;

接着执行getHandlerAdapter方法,通过Handler获取其对应的HandlerAdapter适配器;

HandlerAdapter也同样有多个实现,依据不同的Handler,通过supports方法判断该Handler是哪个类的实现,来返回不同的适配器实现;

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException 
if (this.handlerAdapters != null)
Iterator var2 = this.handlerAdapters.iterator();

while(var2.hasNext())
HandlerAdapter adapter = (HandlerAdapter)var2.next();
if (adapter.supports(handler))
return adapter;



throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");

接着会执行HandlerAdapter.handle方法,将根据适配器调用Controller的具体业务,不同的适配器处理对应的handle处理方式各不相同;

最后返回ModelAndView对象。

流程概览图

SpringMVC源码解析-doDispatch方法_父类_06

以上是关于SpringMVC源码解析-doDispatch方法的主要内容,如果未能解决你的问题,请参考以下文章

SpringMVC源码-执行流程

SpringMVC doDispatch方法的基本思路梳理

SpringMVC doDispatch方法的基本思路梳理

浅谈SpringMVC源码的DispatcherServlet组件执行流程

springmvc的问题,URL分号之后的内容读不到这是为啥呢?

springmvc学习笔记-前端控制器