SpringMVC源码研究之DispatcherServlet处理请求

上一篇文章我们已经讨论过了DispatcherServlet类的初始化问题,本篇博客则就SpringMVC处理一次完整的请求进行讨论。

1. 继承链

首先让我们再来看看继承链
SpringMVC源码研究之DispatcherServlet处理请求_第1张图片

由继承图来看: ServletServletConfig功能被合并在一个类中。但又通过不同的接口进行功能分离

2. doDispatch方法

作为DispatcherServlet类中的核心实现,也是SpringMVC的调度中心,这个方法直接好好研读。

// DispatcherServlet.doDispatch
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    HttpServletRequest processedRequest = request;
    // HandlerExecutionChain, 典型的职责链模式
    //  在springMVC里非常常见,例如4.1新增的接口ResourceResolverChain。
    HandlerExecutionChain mappedHandler = null;
    boolean multipartRequestParsed = false;

    WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

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

        try {
            // 默认情况下 this.multipartResolver 为null;
            // Convert the request into a multipart request, and make multipart resolver available.
            processedRequest = checkMultipart(request);
            multipartRequestParsed = (processedRequest != request);

            // Determine handler for the current request.
            // 筛选出处理当前request的handler(HandlerExecutionChain类型的)
            mappedHandler = getHandler(processedRequest);
            if (mappedHandler == null || mappedHandler.getHandler() == null) {
                // 处理没有匹配项的情况
                noHandlerFound(processedRequest, response);
                return;
            }

            // Determine handler adapter for the current request.
            // 根据当前的handler找到对应的HandlerAdapter, 对当前Handler进行适配, 而不是直接拿来就进行处理。
            //  1. 这里的适配是对我们Object类型的Handler进行适配;
            //  2. 而上面返回的HandlerExecutionChain 类型也是围绕该Object类型的Handler进行封装的一个Chain.
            //  3. 再强调下该handler是个Object类型,这几乎是给与了无尚的灵活性。
            // 这里的技巧是将权限下方给每个HandlerAdapter, 由HandlerAdapter决定是否适配这个Handler(注意这个方法参数handler是Object类型)
            // 对于我们使用@RequestMapping注解的方法,这里的ha是RequestMappingHandlerAdapter类型
            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;
                }
            }
            // 拦截器的前置处理,若某个拦截器返回false,直接结束本次请求的处理
            if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                return;
            }

            // Actually invoke the handler.
            // 调用真正的handler,即调用用户逻辑; 返回ModelAndView
            //  对于本次示例, 这里返回的是null
            mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

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

            // 对于本次示例, 这里直接是空执行
            applyDefaultViewName(request, mv);
            // 拦截器的后置处理。
            // 默认拦截器有三个,其对applyPostHandle的实现都是空处理。
            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) {
        // 触发Error完成事件
        triggerAfterCompletionWithError(processedRequest, response, mappedHandler, 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);
            }
        }
    }
}

2.1 关于handler

先分析下这两行代码

HandlerExecutionChain  mappedHandler = getHandler(processedRequest);

HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
  1. 其中HandlerExecutionChain类就是围绕该Object类型的handler进行封装的一个Chain。
  2. HandlerAdapter接口也是针对该Object类型的handler进行的适配 。
  3. 该handler又是个Object类型,所以这几乎是预留了无上的灵活性

然后我们来具体分析 getHandlergetHandlerAdapter方法

2.2 getHandler方法

// DispatcherServlet类定义的getHandler方法
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    // 在handlerMappings的顺序,可以通过实现Order接口来设置
    // 这是因为在 initHandlerMappings 方法中,会使用AnnotationAwareOrderComparator 类对找到的 HandlerMapping集合进行排序(详细请参见本人的上一篇博客, 或者直接查阅相应源码)
    // 关于HandlerMapping接口,可以参见下面的专门讲解
    for (HandlerMapping hm : this.handlerMappings) {
        // 这里的精妙就在于HandlerMapping接口唯一定义的getHandler方法; 更详尽的参见下面的讨论。      
        HandlerExecutionChain handler = hm.getHandler(request);
        if (handler != null) {
            return handler;
        }
    }
    return null;
}

2.3 getHandlerAdapter方法

在获取到HandlerExecutionChain类实例之后,SpringMVC并没有直接对找到的handler进行处理;而是再次引入一个中间层——将对当前Object类型的Handler进行适配, 适配为对应的HandlerAdapter中间层作为软件开发中的银弹,再一次在这里得以实证。

// DispatcherServlet类定义的getHandlerAdapter方法
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
    // 关于HandlerAdapter接口,可以参见下面的专门讲解
    for (HandlerAdapter ha : this.handlerAdapters) {
        // 将权限下方给每个HandlerAdapter, 由HandlerAdapter自主决定是否适配这个Handler(注意这个方法参数handler是Object类型)
        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");
}

3. HandlerMapping接口

public interface HandlerMapping {
    // 省略了其他常量和注释

    // 声明的唯一方法`getHandler`
    HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}

该方法的参数为request, 而返回值则是HandlerExecutionChain类型。
1. 返回值HandlerExecutionChain本身就是一个扩展性非常强的类。其内部的Object类型的handler以及HandlerInterceptor类型的interceptor集合至少能吞掉90%的自定义需求。(注意此类出现于2003年,至今没有出现子类)。
2. 而方法参数request也符合《Clean Code》里Bob大叔对函数的建议——参数要尽可能少;再加上Servlet规范的精妙设计,所以这个HandlerMapping接口的设计堪称完美

4. HandlerAdapter接口

public interface HandlerAdapter {
    // 为节省篇幅, 我把注释删除掉了

    boolean supports(Object handler);

    ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;

    long getLastModified(HttpServletRequest request, Object handler);
}

这个接口的设计也是相当精妙。虽然在Spring的源码里第一次体会到主从关系颠倒是在SmartApplicationListener接口声明中,但这里的再次出现依然让我惊叹这种思路的精妙——由子元素自己决定是否支持适配这个Object类型的handler, 如果你支持,那么调度者才去调用你实现的handle方法。

5. 实例详解

这里以以下的代码为示例,来讲解下SpringMVC的处理流程,顺带给各位看官演示下阅读源码的一种方式。至于为什么是下面这段代码——因为最近在给公司研发部门制定一整套完整的代码规范。而以下Controller层的代码规范参考了《华为简约代码规范》。

// ----------- Controller层
//@RequestMapping(value = "/standardmethod2", method = { RequestMethod.POST,RequestMethod.GET })
// GetMapping("/standardmethod2")  // 同时注解GetMapping,PostMapping只会生效一个 
@PostMapping("/standardmethod2")
@ResponseBody // 必须要有; `RequestResponseBodyMethodProcessor`类的supportsReturnType方法使用到了
public ResponseBean<Map<String, String>> standardmethod2(long id) {
    return ResponseBean.of(Collections.singletonMap("YWID", "123"));        
}

// ----------- spring-mvc.xml中 ;更多详情看下面给出的链接
<mvc:annotation-driven>
    <mvc:message-converters register-defaults="true">
        
        <bean class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
            <property name="supportedMediaTypes">
                <list>
                    <value>text/html;charset=UTF-8value>
                    <value>application/jsonvalue>
                list>
            property>
            <property name="features">
                <list>
                    <value>WriteMapNullValuevalue>
                    <value>QuoteFieldNamesvalue>
                list>
            property>
        bean>
    mvc:message-converters>
mvc:annotation-driven>

现在我想知道SpringMVC是如何调用这个方法的?那好,我在这个方法体里打个断点。于是我们得到了下面这幅堆栈图。 笔者的笔记本屏幕大小有限,只能截取这么多了。

SpringMVC源码研究之DispatcherServlet处理请求_第2张图片

5.1 RequestMappingHandlerAdapter

  1. 全称为org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
  2. 对于我们使用@RequestMapping注解的方法,DispatcherServlet.doDispatch中的
    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    返回值ha就是RequestMappingHandlerAdapter类型。
  3. 看以上的堆栈图就可以发现,最终主流程会回调本类中声明的invokeHandlerMethod方法来调用用户自定义的方法(standardmethod2(long id))。
  4. 其实invokeHandlerMethod方法内部实现细节表明:调用自定义方法来获取返回值的操作最终是被委托给了ServletInvocableHandlerMethod类来实现了

5.2 ServletInvocableHandlerMethod

全称是org.springframework.web.method.support.InvocableHandlerMethod

// ---------- ServletInvocableHandlerMethod.invokeAndHandle
public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer,
        Object... providedArgs) throws Exception {

    // 这里就是真正调用自定义方法, 获取用户方法的返回值。
    Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
    setResponseStatus(webRequest);

    // 如果我们在自定义的方法里返回null的话, 就会进入这条分支了
    if (returnValue == null) {
        if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) {
            mavContainer.setRequestHandled(true);
            return;
        }
    }
    else if (StringUtils.hasText(getResponseStatusReason())) {
        mavContainer.setRequestHandled(true);
        return;
    }

    mavContainer.setRequestHandled(false);
    try {
        // 使用注册的returnValueHandler集合处理返回值
        // 这里的returnValueHandlers是HandlerMethodReturnValueHandlerComposite类型。(见下方的详解)
        // 我们在示例中会在spring-mvc.xml中注册的FastJsonHttpMessageConverter就是在这个方法里被调用的。
        this.returnValueHandlers.handleReturnValue(
                returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
    }
    catch (Exception ex) {
        throw ex;
    }
}

// ---------- ServletInvocableHandlerMethod.invokeForRequest(其实是基类中定义的)
public Object invokeForRequest(NativeWebRequest request, ModelAndViewContainer mavContainer,
        Object... providedArgs) throws Exception {
    // 获取 将要传递给我们自定义方法 的参数
    Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
    if (logger.isTraceEnabled()) {
        logger.trace("Invoking '" + ClassUtils.getQualifiedMethodName(getMethod(), getBeanType()) +
                "' with arguments " + Arrays.toString(args));
    }
    Object returnValue = doInvoke(args);
    if (logger.isTraceEnabled()) {
        logger.trace("Method [" + ClassUtils.getQualifiedMethodName(getMethod(), getBeanType()) +
                "] returned [" + returnValue + "]");
    }
    return returnValue;
}

5.3 HandlerMethodReturnValueHandlerComposite

直接上方法实现

// HandlerMethodReturnValueHandlerComposite重载的handleReturnValue方法
@Override
public void handleReturnValue(Object returnValue, MethodParameter returnType,
        ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
    // 挑选出合适的HandlerMethodReturnValueHandler
    // 这里的技巧依然是权限下放, 由各个HandlerMethodReturnValueHandler自己决定是否处理该类型和值
    HandlerMethodReturnValueHandler handler = selectHandler(returnValue, returnType);
    if (handler == null) {
        throw new IllegalArgumentException("Unknown return value type: " + returnType.getParameterType().getName());
    }

    // 在本次示例中, 这个hanlder为RequestResponseBodyMethodProcessor类型(见下方的详解)
    handler.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
}

这里我们列出HandlerMethodReturnValueHandlerComposite类中的returnValueHandlers字段里的Item:

  1. org.springframework.web.servlet.mvc.method.annotation.ModelAndViewMethodReturnValueHandler
  2. org.springframework.web.method.annotation.ModelMethodProcessor
  3. org.springframework.web.servlet.mvc.method.annotation.ViewMethodReturnValueHandler
  4. org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitterReturnValueHandler
  5. org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBodyReturnValueHandler
  6. org.springframework.web.servlet.mvc.method.annotation.HttpEntityMethodProcessor
  7. org.springframework.web.servlet.mvc.method.annotation.HttpHeadersReturnValueHandler
  8. org.springframework.web.servlet.mvc.method.annotation.CallableMethodReturnValueHandler
  9. org.springframework.web.servlet.mvc.method.annotation.DeferredResultMethodReturnValueHandler
  10. org.springframework.web.servlet.mvc.method.annotation.AsyncTaskMethodReturnValueHandler
  11. org.springframework.web.method.annotation.ModelAttributeMethodProcessor
  12. org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor // 本次的主角
  13. org.springframework.web.servlet.mvc.method.annotation.ViewNameMethodReturnValueHandler
  14. org.springframework.web.method.annotation.MapMethodProcessor
  15. org.springframework.web.method.annotation.ModelAttributeMethodProcessor

5.4 RequestResponseBodyMethodProcessor

该类实现的supportsReturnType方法说明了我们在自定义方法上标注@ResponseBody的作用

// RequestResponseBodyMethodProcessor覆写的handleReturnValue方法
@Override
public void handleReturnValue(Object returnValue, MethodParameter returnType,
        ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
        throws IOException, HttpMediaTypeNotAcceptableException, HttpMessageNotWritableException {

    mavContainer.setRequestHandled(true);
    ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
    ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);

    // Try even with null return value. ResponseBodyAdvice could get involved.
    // 示例中在spring-mvc.xml中注册的FastJsonHttpMessageConverter将在这个方法里将返回的ResponseBean示例转换为JSON字符串
    writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
}

依然是列举下RequestResponseBodyMethodProcessor类中的 messageConverters 集合字段中存储的Item
1. com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter // 本次主角,也就是我们在spring-mvc.xml中注册的。
1. org.springframework.http.converter.ByteArrayHttpMessageConverter
1. org.springframework.http.converter.StringHttpMessageConverter
1. org.springframework.http.converter.ResourceHttpMessageConverter
1. org.springframework.http.converter.xml.SourceHttpMessageConverter
1. org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter
1. org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter

5.5 补充

  1. 注意在本示例中,最终mv = ha.handle(processedRequest, response, mappedHandler.getHandler());返回的mv为null。
  1. 《Spring源码深度解析》 – P320
  2. http://jinnianshilongnian.iteye.com/blog/1602617
  3. http://blog.csdn.net/zhenghuasheng/article/details/51223106

你可能感兴趣的:(Spring,SpringMVC)