Spring源码阅读(十)—SpringMVC的处理逻辑

Spring源码阅读(十)—SpringMVC的处理逻辑

本文主要整理了DispatchServlet进行请求逻辑处理部分的具体实现流程

个人主页:tuzhenyu’s page
原文地址:Spring源码阅读(十)—SpringMVC的处理逻辑


DispatcherServlet逻辑处理

  • Web应用启动经过了ServletContextListener初始化和DispatcherServlet初始化,具体的逻辑处理由DispatcherServlet实现.DispatcherServlet类继承HttpServlet类,所以请求经由Servlet容器转发到DispatcherServlet,由DispatcherServlet类的doGet()方法或者doPost()方法处理;
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);
}
  • DispatcherServlet类的doGet()方法和doPost()方法并未对请求进行具体处理而是委托给processRequest()方法进行具体的处理.processRequest()方法和processRequest()方法调用的doService()方法只是处理请求前的准备工作.
protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    long startTime = System.currentTimeMillis();
    Object failureCause = null;
    LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
    LocaleContext localeContext = this.buildLocaleContext(request);
    RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
    ServletRequestAttributes requestAttributes = this.buildRequestAttributes(request, response, previousAttributes);
    WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new FrameworkServlet.RequestBindingInterceptor(null));
    this.initContextHolders(request, localeContext, requestAttributes);

    try {
        this.doService(request, response);
    } catch (ServletException var17) {
        failureCause = var17;
        throw var17;
    } catch (IOException var18) {
        failureCause = var18;
        throw var18;
    } catch (Throwable var19) {
        failureCause = var19;
        throw new NestedServletException("Request processing failed", var19);
    } finally {
        this.resetContextHolders(request, previousLocaleContext, previousAttributes);
        if(requestAttributes != null) {
            requestAttributes.requestCompleted();
        }

        if(this.logger.isDebugEnabled()) {
            if(failureCause != null) {
                this.logger.debug("Could not complete request", (Throwable)failureCause);
            } else if(asyncManager.isConcurrentHandlingStarted()) {
                this.logger.debug("Leaving response open for concurrent processing");
            } else {
                this.logger.debug("Successfully completed request");
            }
        }

        this.publishRequestHandledEvent(request, response, startTime, (Throwable)failureCause);
    }

}
  • 由doService()方法调用的doDispatch()方法是请求处理的核心所在,进行了请求处理的整个流程.

    • MultipartContent类型的request处理,将request转换成MutipartHttpServletRequest类型的request;

    • 根据HandlerMapping和request信息寻找对应的Handler,返回HandlerExecutionChain调用链条

    • 从HandlerExecutionChain获取系统定义的拦截器的preHandler方法调用

    • 激活handler对请求进行处理并返回视图

    • 从HandlerExecutionChain获取系统定义的拦截器的postHandler方法调用

    • 根据视图跳转具体页面

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 err = null;
            Object dispatchException = null;

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

                HandlerAdapter err1 = this.getHandlerAdapter(mappedHandler.getHandler());
                String method = request.getMethod();
                boolean isGet = "GET".equals(method);
                if(isGet || "HEAD".equals(method)) {
                    long lastModified = err1.getLastModified(request, mappedHandler.getHandler());
                    if(this.logger.isDebugEnabled()) {
                        this.logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
                    }

                    if((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
                        return;
                    }
                }

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

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

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

            this.processDispatchResult(processedRequest, response, mappedHandler, err, (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);
        }

    }
}
  • doDispatch()方法调用getHandler()方法从HandlerMapping映射中返回一个调用链对象

    • HandlerMapping一般是在servlet-dispatch.xml配置文件中通过标签进行映射定义,在Spring启动的时候会在DispatchServlet初始化的时候进行初始化,它的初始化方式主要依赖于AbstractHandlerMethodMapping这个抽象类,利用initHandlerMethods(..)方法获取所有Spring容器托管的bean,然后调用isHandler(..)看是否是@Controller注解修饰的bean,之后调用detectHandlerMethods(..)尝试去解析bean中的方法,也就是去搜索@RequestMapping注解修饰的方法,然后将url和方法绑定注册在HandlerMapping中的一个map映射表中

    • 调用getHandler()方法 ,从映射列表中根据url path返回一个具体的HandlerMethod,然后调用getHandlerExecutionChain构造成一个HandlerExecutionChain,将工程中定义的拦截器和HandlerMethod一起封装在调用链中.

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

    HandlerExecutionChain handler;
    do {
        if(!var2.hasNext()) {
            return null;
        }

        HandlerMapping hm = (HandlerMapping)var2.next();
        if(this.logger.isTraceEnabled()) {
            this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name \'" + this.getServletName() + "\'");
        }

        handler = hm.getHandler(request);
    } while(handler == null);

    return handler;
}
public final HandlerExecutionChain getHandler(PortletRequest request) throws Exception {
    Object handler = this.getHandlerInternal(request);
    if(handler == null) {
        handler = this.getDefaultHandler();
    }

    if(handler == null) {
        return null;
    } else {
        if(handler instanceof String) {
            String handlerName = (String)handler;
            handler = this.getApplicationContext().getBean(handlerName);
        }

        return this.getHandlerExecutionChain(handler, request);
    }
}

protected abstract Object getHandlerInternal(PortletRequest var1) throws Exception;

protected HandlerExecutionChain getHandlerExecutionChain(Object handler, PortletRequest request) {
    if(handler instanceof HandlerExecutionChain) {
        HandlerExecutionChain chain = (HandlerExecutionChain)handler;
        chain.addInterceptors(this.getAdaptedInterceptors());
        return chain;
    } else {
        return new HandlerExecutionChain(handler, this.getAdaptedInterceptors());
    }
}
  • 调用getHandlerAdapter(Object handler)方法根据Handler获取对应的适配器,默认适配器有系统定义的三种HttpRequestHandlerAdapter,SimpleControllerHandlerAdapter,AnnotationMethodHandlerAdapter;
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
    Iterator var2 = this.handlerAdapters.iterator();

    HandlerAdapter ha;
    do {
        if(!var2.hasNext()) {
            throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
        }

        ha = (HandlerAdapter)var2.next();
        if(this.logger.isTraceEnabled()) {
            this.logger.trace("Testing handler adapter [" + ha + "]");
        }
    } while(!ha.supports(handler));

    return ha;
}
  • 从拦截链中获所有的拦截器,并遍历调用其preHandler()方法

  • 调用HandlerAdapter.handle(…)得到一个ModelAndView对象,里面封装了数据对象及具体的View对象

  • 从拦截链中获所有的拦截器,并遍历调用其postHandler()方法

  • 调用processDispatchResult处理结果,相应给客户端。

结论

DispatcherServlet逻辑处理主要是通过调用doDispatch()方法实现的,在该方法中主要先后完成了根据request请求从HandlerMapping中获取Handler映射并同拦截器一起封装成拦截链;根据Handler获取对应的适配器Adapter;从拦截链中获取所有注册的拦截器并执行其preHandler方法;调用适配器执行具体的请求处理逻辑;从拦截链中获取所有注册的拦截器并执行其postHandler方法;将返回的ModlerAndeView对象进行页面跳转处理.

    原文作者:Spring MVC
    原文地址: https://blog.csdn.net/u013967175/article/details/77816193
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞