美文网首页spring
Spring MVC源码解读三

Spring MVC源码解读三

作者: 测试你个头 | 来源:发表于2017-02-24 11:25 被阅读0次

接上一篇:Spring MVC源码解析二

  • spring mvc请求分发链路:
    通过时序图可以看到,servlet对request请求进行拦截后,先后调用了FrameworkServlet的processRequest()、doService(),最终调用了DispatcherServlet的doDispatch()方法
    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);

                // Determine handler for the current request.
                mappedHandler = getHandler(processedRequest);
                if (mappedHandler == null || mappedHandler.getHandler() == null) {
                    noHandlerFound(processedRequest, response);
                    return;
                }

                // Determine handler adapter for the current request.
                HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

                // Process last-modified header, if supported by the handler.
                String method = request.getMethod();
                boolean isGet = "GET".equals(method);
                if (isGet || "HEAD".equals(method)) {
                    long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                    if (logger.isDebugEnabled()) {
                        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;
                }

                try {
                    // Actually invoke the handler.
                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                }
                finally {
                    if (asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }
                }

                applyDefaultViewName(request, mv);
                mappedHandler.applyPostHandle(processedRequest, response, mv);
            }
            catch (Exception ex) {
                dispatchException = ex;
            }
            processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
        }
        catch (Exception ex) {
            triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
        }
        catch (Error err) {
            triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
        }
        finally {
            if (asyncManager.isConcurrentHandlingStarted()) {
                // Instead of postHandle and afterCompletion
                mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                return;
            }
            // Clean up any resources used by a multipart request.
            if (multipartRequestParsed) {
                cleanupMultipart(processedRequest);
            }
        }
    }

核心处理如下:

mappedHandler  = getHandler()  //get handler by url handlermapping
ha = getHandlerAdapter()  //get handleradapter
ha.handle()  //通过adapter调用handler的处理方法
processDispatchResult()  //处理doDispatch的处理结果

分别查看源码:
getHandler()

    /**
     * Return the HandlerExecutionChain for this request.
     * <p>Tries all handler mappings in order.
     * @param request current HTTP request
     * @return the HandlerExecutionChain, or {@code null} if no handler could be found
     */
    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        for (HandlerMapping hm : this.handlerMappings) {
            if (logger.isTraceEnabled()) {
                logger.trace(
                        "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
            }
            HandlerExecutionChain handler = hm.getHandler(request);
            if (handler != null) {
                return handler;
            }
        }
        return null;
    }

1、getHandler()主要就是通过this.handlerMappings中的HandlerMapping实例来对具体request映射一个handler(spring mvc中的controller类和controller类中的具体方法) 2、如果看过[spring mvc源码解析二]中对于this.handlerMappings初始化的解读,便知道HandlerMapping的具体实现有3个: 1.RequestMappingHandlerMapping 2.BeanNameUrlHandlerMapping 3.SimpleUrlHandlerMapping 3、spring mvc中正是通过这3个类实现了重要的request和controller的mapping

getHandlerAdapter从this.handlerAdapters中匹配获取对应的handlerAdapter,且获取对应的handler

    /**
     * Return the HandlerAdapter for this handler object.
     * @param handler the handler object to find an adapter for
     * @throws ServletException if no HandlerAdapter can be found for the handler. This is a fatal error.
     */
    protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
        for (HandlerAdapter ha : this.handlerAdapters) {
            if (logger.isTraceEnabled()) {
                logger.trace("Testing handler adapter [" + ha + "]");
            }
            if (ha.supports(handler)) {
                return ha;
            }
        }
        throw new ServletException("No adapter for handler [" + handler +
                "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
    }

handle()是HandleAdapter中定义的接口,具体的实现类有很多,在DispatcherServlet中具体使用哪个实现,是由上一步调用的getHandlerAdapter决定的,handle()接口的具体作用如接口注释描述:使用指定的handler来处理http请求

    /**
     * Use the given handler to handle this request.
     * The workflow that is required may vary widely.
     * @param request current HTTP request
     * @param response current HTTP response
     * @param handler handler to use. This object must have previously been passed
     * to the {@code supports} method of this interface, which must have
     * returned {@code true}.
     * @throws Exception in case of errors
     * @return ModelAndView object with the name of the view and the required
     * model data, or {@code null} if the request has been handled directly
     */
    ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;

相关文章

  • Spring MVC源码解读二

    接上一篇:Spring MVC源码解读一 DispatchServlet:源码位置: DispatcherServ...

  • Spring MVC源码解读三

    接上一篇:Spring MVC源码解析二 spring mvc请求分发链路:通过时序图可以看到,servlet对r...

  • Java之Spring mvc详解(非原创)

    文章大纲 一、Spring mvc介绍二、Spring mvc代码实战三、项目源码下载四、参考文章 一、Sprin...

  • spring源码解读网上知识摘要

    spring 启动源码 spring 启动流程源码解读spring 启动注解加载类源码解读springxml 文件...

  • 2018-05-05

    spring源码分析(三) 目录五、Spring 源码解读--5.4、IOC 容器的依赖注入----1、依赖注入发...

  • spring mvc源码解读(一)

    一、最近努力可好? 二、 springMVC通过Dispactcher类就行分发,由doService--->do...

  • Spring MVC源码解读一

    阅读前提:1、理解IOC的一些概念,以及在Spring中的实现(上下文,BeanFactory,BeanDefin...

  • Spring MVC源码解读四

    接上一篇:Spring MVC源码解析三 在上一篇对于DispatcherServlet中的doDispatch方...

  • Spring Mvc源码分析

    Spring Mvc源码分析 mvc源码图解springmvc经过一系列的调用到DispatcherServlet...

  • READY EVERYDAY #1

    1.Spring, Spring MVC原理, 源码 Spring 简介 https://www.ibm.com/...

网友评论

    本文标题:Spring MVC源码解读三

    本文链接:https://www.haomeiwen.com/subject/kvopwttx.html