SpringMvc的源码解析

102 阅读2分钟

SpringMvc的源码解析

SpringMVC处理请求的流程源码剖析

  1. 接收请求。DispatcherServlet是一个Servlet,在浏览器输入url,会接收到对应的请求。HttpServlet#service()
  2. 请求分发。DispatcherServlet顾名思义,负责分发的Servlet。核心方法,DispatcherServlet#doDispatch
  3. 根据请求获取HandlerExecutionChain对象。因为handlerMapping有多个类型,我们最常用的是RequestMappingHandlerMapping。执行AbstractHandlerMethodMapping#lookupHandlerMethod,根据request获取到对应的url,根据url从MappingRegistry#pathLookup变量中获取对应的处理器。
    @Nullable
    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;
    }

AbstractHandlerMapping#getHandlerExecutionChain,对找到的处理器进行封装。

    protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
        HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
                (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
​
        for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
            if (interceptor instanceof MappedInterceptor) {
                MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
                if (mappedInterceptor.matches(request)) {
                    chain.addInterceptor(mappedInterceptor.getInterceptor());
                }
            }
            else {
                chain.addInterceptor(interceptor);
            }
        }
        return chain;
    }
  1. 获取处理器适配器。DispatcherServlet#getHandlerAdapter,常见的还是RequestMappingHandlerAdapter。在执行到ServletInvocableHandlerMethod#invokeAndHandle方法中,会对返回值进行处理。this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest);。我们接口中常用的json字符串返回用到的返回值处理器是RequestResponseBodyMethodProcessor,当返回类型满足AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.class) || returnType.hasMethodAnnotation(ResponseBody.class);,则会调用RequestResponseBodyMethodProcessor来对返回值处理。
  2. 对处理器进行前置处理,主要执行mappedHandler.applyPreHandle(processedRequest, response)。执行HandlerExecutionChain中的处理器的preHandle方法。
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
        for (int i = 0; i < this.interceptorList.size(); i++) {
            HandlerInterceptor interceptor = this.interceptorList.get(i);
            if (!interceptor.preHandle(request, response, this.handler)) {
                triggerAfterCompletion(request, response, null);
                return false;
            }
            this.interceptorIndex = i;
        }
        return true;
    }
  1. 执行处理器。通过获取到的HandlerAdapter,即RequestMappingHandlerAdapter来执行RequestMappingHandlerAdapter#handleInternal。反射调用方法,得到一个ModelAndView对象。
  2. 对处理器进行后置处理,mappedHandler.applyPostHandle(processedRequest, response, mv);。执行HandlerExecutionChain中的处理器的postHandle方法。
  3. 对处理器进行异常处理,triggerAfterCompletion(processedRequest, response, mappedHandler, ex)
  4. 处理分发结果,渲染视图。DispatcherServlet#processDispatchResult。渲染视图,DispatcherServlet#render->AbstractView#render

SpringMvc组件初始化的流程解析

  1. servlet对象初始化,只有在第一次访问的时候执行一次。 所以DispatcherServlet的初始化是在应用第一次处理web请求的时候。
  2. DispatcherServlet初始化。执行父类GenericServlet#init()。核心方法是DispatcherServlet#initStrategies
    protected void initStrategies(ApplicationContext context) {
        // 多文件上传的组件
        initMultipartResolver(context);
        // 初始化本地语言环境
        initLocaleResolver(context);
        // 初始化模板处理器
        initThemeResolver(context);
        // 初始化HandlerMapping
        initHandlerMappings(context);
        // 初始化参数适配器
        initHandlerAdapters(context);
        // 初始化异常拦截器
        initHandlerExceptionResolvers(context);
        // 初始化视图预处理器
        initRequestToViewNameTranslator(context);
        // 初始化视图转换器
        initViewResolvers(context);
        // 初始化 FlashMap 管理器
        initFlashMapManager(context);
    }