DispatcherServlet的doDispatch方法解析

先看下整个方法:

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    HttpServletRequest processedRequest = request;
    HandlerExecutionChain mappedHandler = null;
    boolean multipartRequestParsed = false;
    WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

    try {
        try {
            ModelAndView mv = null;
            Object dispatchException = null;

            try {
                processedRequest = this.checkMultipart(request);
                multipartRequestParsed = processedRequest != request;
                mappedHandler = this.getHandler(processedRequest);
                if (mappedHandler == null) {
                    this.noHandlerFound(processedRequest, response);
                    return;
                }

                HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
                String method = request.getMethod();
                boolean isGet = "GET".equals(method);
                if (isGet || "HEAD".equals(method)) {
                    long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                    if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
                        return;
                    }
                }

                if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                    return;
                }

                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                if (asyncManager.isConcurrentHandlingStarted()) {
                    return;
                }

                this.applyDefaultViewName(processedRequest, mv);
                mappedHandler.applyPostHandle(processedRequest, response, mv);
            } catch (Exception var20) {
                dispatchException = var20;
            } catch (Throwable var21) {
                dispatchException = new NestedServletException("Handler dispatch failed", var21);
            }

            this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
        } catch (Exception var22) {
            this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
        } catch (Throwable var23) {
            this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
        }

    } finally {
        if (asyncManager.isConcurrentHandlingStarted()) {
            if (mappedHandler != null) {
                mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
            }
        } else if (multipartRequestParsed) {
            this.cleanupMultipart(processedRequest);
        }

    }
}

首先是:

HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
boolean multipartRequestParsed = false;
WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

看下HandlerExecutionChain的成员变量:

   

 

handler 即对应的处理器,interceptors即对应的拦截器,interceptorList即集合化的拦截器。multipartRequestParsed判断这个请求是不是文件流的请求,即multipartFile。

asyncManager,异步管理器:

if (asyncManager.isConcurrentHandlingStarted()) {
    return;
}

这个地方还未具体研究。

 

二、然后是:

processedRequest = this.checkMultipart(request);
multipartRequestParsed = processedRequest != request;
mappedHandler = this.getHandler(processedRequest);
if (mappedHandler == null) {
    this.noHandlerFound(processedRequest, response);
    return;
}

判断是不是文件流请求,以及获取处理器映射器:

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    if (this.handlerMappings != null) {
        Iterator var2 = this.handlerMappings.iterator();

        while(var2.hasNext()) {
            HandlerMapping mapping = (HandlerMapping)var2.next();
            HandlerExecutionChain handler = mapping.getHandler(request);
            if (handler != null) {
                return handler;
            }
        }
    }

    return null;
}

总共有五个处理器映射器:

我们主要用到的是SimpleUrlHandlerMapping与RequestMappingHandlerMapping。其中SimpleUrlHandlerMapping是我们在最初使用配置文件的形式,并继承Controller接口时,来处理这些继承该接口的类的:如其他作者写的博文:https://blog.csdn.net/qq_26464179/article/details/79042989

我们可以看到我们要实现handleRequestInternal接口。

而关于RequestMappingHandlerMapping,是我们现在常用的@Controller以注解的方式实现的。

并且,在SimpleUrlHandlerMapping处理器映射器获取到的处理器是ResourceHttpRequestHandler。

而在RequestMappingHandlerMapping处理器映射器获取到的处理器是HandlerMethod:

 

三、如果没有获取到对应的处理器,则直接返回:

if (mappedHandler == null) {
    this.noHandlerFound(processedRequest, response);
    return;
}

四、如果获取到处理器,则获取到对应的适配器(这里是有用到适配器模式):

   适配器有三个,与处理器映射器是对应的:

if (this.handlerAdapters != null) {
    Iterator var2 = this.handlerAdapters.iterator();

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

我们看先adapter.supports(handler)方法:

1、SimpleControllerHandlerAdapter的supports方法是

public boolean supports(Object handler) {
    return handler instanceof Controller;
}

2、HttpRequestHandlerAdapter的是:
public boolean supports(Object handler) {
    return handler instanceof HttpRequestHandler;
}

上面提到的ResourceHttpRequestHandler,就实现了HttpRequestHandler接口,

3、RquestMappingHandlerAdapter的是:

public final boolean supports(Object handler) {
    return handler instanceof HandlerMethod && this.supportsInternal((HandlerMethod)handler);
}

我们现在的这个请求就是用的这个 Adapter:

五、拿到Adaper后就会执行处理器执行链中的过滤器,不通过则直接返回:

if (!mappedHandler.applyPreHandle(processedRequest, response)) {
    return;
}
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
    HandlerInterceptor[] interceptors = this.getInterceptors();
    if (!ObjectUtils.isEmpty(interceptors)) {
        for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) {
            HandlerInterceptor interceptor = interceptors[i];
            if (!interceptor.preHandle(request, response, this.handler)) {
                this.triggerAfterCompletion(request, response, (Exception)null);
                return false;
            }
        }
    }

    return true;
}

六、通过则通过Adapter执行该处理器。

我们可以看到在通过adapter进行执行是会进行强转,这个与获取适配器是是对应的:

public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    return this.handleInternal(request, response, (HandlerMethod)handler);
}
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    ((HttpRequestHandler)handler).handleRequest(request, response);
    return null;
}

七、关于适配器中处理器的执行执行:

(以我用的@Controller与@RquestMapping注解,注解的方法为例)我们可以看到,在处理器中,已经有RquestMapping注解的方法了。所以,适配器就执行该方法,获取Model,与View的名称,为了理解方便,这里将Model与view分开来,其实他们本身也是分开的。因此适配器通过执行对应的method,获取对应的Model,与view名称(单单就是一个名称,这时候还没有与themeleaf模版相结合):

如果没有获取到对应的ModelAndView,就使用默认的视图:

this.applyDefaultViewName(processedRequest, mv);
private void applyDefaultViewName(HttpServletRequest request, @Nullable ModelAndView mv) throws Exception {
    if (mv != null && !mv.hasView()) {
        String defaultViewName = this.getDefaultViewName(request);
        if (defaultViewName != null) {
            mv.setViewName(defaultViewName);
        }
    }

}

八、获取到ModelAndView后,再执行过滤器的postHandle方法。

九、获取到ModelAndView后,就通过Model与View中名称,找到对应的themeleaf模板,并将模板中的字段填充到模板想要替代的字段中,同时将themeleaf模板以流的方式写入到Response中:

this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);

自此,关于doDispacher方法的执行、解析过程就大致完成。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值