SpringBoot 中DispatcherServlet请求分发流程源码分析

以一个简单的请求为例(实际RedisController包含多个请求)

@RestController
@RequestMapping("/redis")
public class RedisController {
 
 
    @RequestMapping(value = {"/getmsg"})
    public String getmsg(){
 
        return  "hello";
    }
 
    .....
 
}
 

整个 DispatcherServlet执行流程:

正常情况下整个request流程代码都在DispatcherServlet#doService()方法中执行,由同一个线程完成从请求到响应

FrameworkServlet#doPost/doGet

FrameworkServlet#processRequest

DispatcherServlet#doService

DispatcherServlet#doDispatch

doDispatch是SpringMvc中的核心请求处理方法,几乎全部的请求处理流程都在这个方法中。下图就是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 {
            ModelAndView mv = null;
            Exception dispatchException = null;
 
            try {
                processedRequest = checkMultipart(request);//是否上传文件
                multipartRequestParsed = (processedRequest != request);
 
                //根据request信息Uri找到对应HandlerExecutionChain执行链
                mappedHandler = getHandler(processedRequest);
                if (mappedHandler == null) {
                                        //没有找到HandlerExecutionChain 的通过response反馈
                    noHandlerFound(processedRequest, response);
                    return;
                }
 
                //通过已找到的Handler取得HandlerAdapter
                HandlerAdapter ha = 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;
                    }
                }
                                //pre拦截器执行
                if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                    return;
                }
 
                //执行handle,Controller方法
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
 
                if (asyncManager.isConcurrentHandlingStarted()) {
                    return;
                }
 
                applyDefaultViewName(processedRequest, mv);
                                //post拦截器执行(倒序)
                mappedHandler.applyPostHandle(processedRequest, response, mv);
            }
            catch (Exception ex) {
                dispatchException = ex;
            }
            catch (Throwable err) {
                // As of 4.3, we're processing Errors thrown from handler methods as well,
                // making them available for @ExceptionHandler methods and other scenarios.
                dispatchException = new NestedServletException("Handler dispatch failed", err);
            }
                       //页面跳转,响应信息
            processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
        }
        catch (Exception ex) {
            triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
        }
        catch (Throwable err) {
            triggerAfterCompletion(processedRequest, response, mappedHandler,
                    new NestedServletException("Handler processing failed", err));
        }
        finally {
            if (asyncManager.isConcurrentHandlingStarted()) {
                // Instead of postHandle and afterCompletion
                if (mappedHandler != null) {
                    mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                }
            }
            else {
                // Clean up any resources used by a multipart request.
                if (multipartRequestParsed) {
                    cleanupMultipart(processedRequest);
                }
            }
        }
    }
DispatcherServlet#getHandler

可以看到springboot启动时装载的全部handlerMapping都保存在List<HandlerMapping> handlerMappings中。这里遍历handlerMappings中所有handlerMapping,直到找到请求对应的Mapping并返回执行立链HandlerExecutionChain。因为是@RequestMapping映射,所以遍历到handlerMappings[1]==RequestMappingHandlerMapping可以找到对应执行链。

下边直接步进到RequestMappingHandlerMapping其继承自AbstractHandlerMapping。

RequestMappingHandlerMapping初始化时注册@RequestMapping映射

https://blog.csdn.net/shanchahua123456/article/details/89816167

RequestMappingHandlerMapping成员变量

AbstractHandlerMapping#getHandler

AbstractHandlerMethodMapping#getHandlerInternal 

 AbstractHandlerMethodMapping其继承自AbstractHandlerMapping,实现了getHandlerInternal()。

这里取得mappingRegistry的读锁,后续就是通过URL从mappingRegistry匹配HandlerMethod(执行方法)。

mappingRegistry中注册了SpringMvc的控制器和HandlerMethod,以及URL的映射关系。下面有mappingRegistry的成员变量介绍。

AbstractHandlerMethodMapping#lookupHandlerMethod

AbstractHandlerMethodMapping.MappingRegistry#getMappingsByUrl

到这里可以看到通过urlPath从urlLookUp中找到 

返回List<RequestMappingInfo>

AbstractHandlerMethodMapping#lookupHandlerMethod

AbstractHandlerMethodMapping#addMatchingMappings

RequestMappingInfoHandlerMapping#getMatchingMapping

AbstractHandlerMethodMapping.MappingRegistry#getMappings

AbstractHandlerMethodMapping#addMatchingMappings

到这里可以看到Spring已经通过mappingRegistry匹配到URL对应HandlerMethod对象,其成员变量包括: Bean对象,Method对象,参数列表等信息。将匹配到的HandlerMethod对象等信息保存到matches中。

mappingRegistry

mappingRegistry对象中成员变量:各种Map还有一个读写锁。

mappingRegistry的各个主要变量

 

 

返回 AbstractHandlerMethodMapping#lookupHandlerMethod 

返回lookupHandlerMethod()中从返回的List<Match> matches中匹配最合适的handlerMethod返回getHandlerInternal()方法。

if (!matches.isEmpty()) {
            Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
            matches.sort(comparator);
            Match bestMatch = matches.get(0);
            if (matches.size() > 1) {
                if (logger.isTraceEnabled()) {
                    logger.trace(matches.size() + " matching mappings: " + matches);
                }
                if (CorsUtils.isPreFlightRequest(request)) {
                    return PREFLIGHT_AMBIGUOUS_MATCH;
                }
                Match secondBestMatch = matches.get(1);
                if (comparator.compare(bestMatch, secondBestMatch) == 0) {
                    Method m1 = bestMatch.handlerMethod.getMethod();
                    Method m2 = secondBestMatch.handlerMethod.getMethod();
                    String uri = request.getRequestURI();
                    throw new IllegalStateException(
                            "Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");
                }
            }
            handleMatch(bestMatch.mapping, lookupPath, request);
            return bestMatch.handlerMethod;
        }
返回 AbstractHandlerMethodMapping#getHandlerInternal 

此时已取得 handlerMethod。 

 

返回 AbstractHandlerMapping#getHandler

此时已取得 handlerMethod,剩下的工作是完成执行链HandlerExecutionChain

取得执行链HandlerExecutionChain

AbstractHandlerMapping#getHandlerExecutionChain 

创建HandlerExecutionChain(handler),遍历ArrayList<HandlerInterceptor> adaptedInterceptors把interceptor加入其中。

返回AbstractHandlerMapping#getHandler

返回DispatcherServlet#getHandler

此时已取得完整执行链,回到最初的DispatcherServlet类中。

可以看到IDE提示HandlerExecutionChain handler中包含HandlerMethod和两个拦截器 

返回DispatcherServlet#doDispatch

取得执行链HandlerExecutionChain 后,取得HandlerAdapter。

HandlerExecutionChain#getHandler

上图mappedHandler为之前取得的执行链HandlerExecutionChain ,取得执行链中的handler。

DispatcherServlet#getHandlerAdapter 

遍历handlerAdapters找到合适。

 返回DispatcherServlet#doDispatch

此时回到doDispatch方法,已经获得HandlerExecutionChain和HandlerAdapter。剩下的流程执行前置拦截器,执行Controller,执行post拦截器。

HandlerExecutionChain mappedHandler执行pre拦截器

HandlerExecutionChain#applyPreHandle

执行PRE拦截器,此处将当前执行链中的(HandlerMethod)this.handler传入拦截器。

返回DispatcherServlet#doDispatch

继续执行Controller方法(Handler)

AbstractHandlerMethodAdapter#handle

RequestMappingHandlerAdapter#handleInternal 

RequestMappingHandlerAdapter#invokeHandlerMethod

protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
            HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
 
        ServletWebRequest webRequest = new ServletWebRequest(request, response);
                //webRequest : uri=/redis/getmsg;client=127.0.0.1
        try {
            WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
            ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);
 
            ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
            if (this.argumentResolvers != null) {
                invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
            }
            if (this.returnValueHandlers != null) {
                invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
            }
            invocableMethod.setDataBinderFactory(binderFactory);
            invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
 
            ModelAndViewContainer mavContainer = new ModelAndViewContainer();
            mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
            modelFactory.initModel(webRequest, mavContainer, invocableMethod);
            mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
 
            AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
            asyncWebRequest.setTimeout(this.asyncRequestTimeout);
 
            WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
            asyncManager.setTaskExecutor(this.taskExecutor);
            asyncManager.setAsyncWebRequest(asyncWebRequest);
            asyncManager.registerCallableInterceptors(this.callableInterceptors);
            asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
 
            if (asyncManager.hasConcurrentResult()) {
                Object result = asyncManager.getConcurrentResult();
                mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
                asyncManager.clearConcurrentResult();
                LogFormatUtils.traceDebug(logger, traceOn -> {
                    String formatted = LogFormatUtils.formatValue(result, !traceOn);
                    return "Resume with async result [" + formatted + "]";
                });
                invocableMethod = invocableMethod.wrapConcurrentResult(result);
            }
 
            invocableMethod.invokeAndHandle(webRequest, mavContainer);
            if (asyncManager.isConcurrentHandlingStarted()) {
                return null;
            }
 
            return getModelAndView(mavContainer, modelFactory, webRequest);
        }
        finally {
            webRequest.requestCompleted();
        }
    }


最终会走到此方法中InvocableHandlerMethod#doInvoke

通过HandlerMethod中的BridgedMethod反射执行Controller中的@RequestMapping映射方法调用。

getBridgedMethod().invoke(getBean(), args);
getBridgedMethod()返回的是HandlerMethod中的bridgedMethod(下图)。

getBean()返回的是HandlerMethod中的bean(下图)。 

RedisController#getmsg 

 此时通过放射调用,执行真正的RedisController中的@RequestMapping映射方法

一直返回到ServletInvocableHandlerMethod#invokeAndHandle

ModelAndViewContainer mavContainer: View is [null]; default model {}  因为是@RestController,View=null

returnValue="hello"

RequestMappingHandlerAdapter#invokeHandlerMethod

通过getModelAndView()将mavContainer转换成ModelAndView返回

 

一直返回DispatcherServlet#doDispatch

Controller@RequestMapping映射方法执行完毕,返回MV。向下执行POST拦截器。

HandlerExecutionChain#applyPostHandle

倒序执行Post拦截器(后进先出)

响应用户请求DispatcherServlet#processDispatchResult

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值