Spring 框架中Http请求处理流程

Posted SheaChen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring 框架中Http请求处理流程相关的知识,希望对你有一定的参考价值。

Spring Web http request请求流程:

首先介绍这边你需要知道的继承体系,DispacherServlet继承自FrameworkServlet,FrameworkServlet继承自HttpServletBean,HttpServletBean继承自HttpServlet,HttpServlet继承自GenericServlet,GenericServlet实现Servlet、ServletConfig接口,我们的流程从请求进入到GenericServlet的service方法开始说起。

流程总览:

容器监听端口,接收到请求后调用Servlet的service方法,

在service方法中判断用户使用的是get还是post请求,决定后续调用对应的doGet/doPost方法,

在doGet/doPost方法中执行processRequest方法,

processRequest方法执行请求上下文的初始化过程,

然后调用doService()方法,

由该doService方法执行doDispatch方法,

最后由doDispatch方法去获取请求的mappedHandler和HandlerAdapter,处理完用户请求之后通过新建一个ServletWebRequest来渲染返回数据

首先调用GenericServlet的service()方法,源码如下:
public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;
事实上GenericServlet的service()方法是一个抽象方法,而HttpServlet继承了GenericServlet,所以此处实际调用了HttpServlet的service方法,HttpServlet的service方法源码如下:

public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
    if (req instanceof HttpServletRequest && res instanceof HttpServletResponse) {
    HttpServletRequest request = (HttpServletRequest)req;
    HttpServletResponse response = (HttpServletResponse)res;
    this.service(request, response);
     } else {
         throw new ServletException("non-HTTP request or response");
    }
 }
首先判断ServletRequest、ServletResponse是否是标准的HttpServletRequest、HttpServletResponse,如果不是则抛出ServletException异常,否则继续调用实现类的service()方法
对源码做debug我们知道,this.service(request, response);执行到spring FrameworkServlet的service方法。
在spring框架中,FrameworkServlet继承自HttpServletBean,HttpServletBean是一个抽象类,HttpServletBean继承自HttpServlet。
所以HttpServlet的service方法中调用的this.service(request, response);其实是执行的是FrameworkServlet中的service方法。继续看源码:
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
    if (httpMethod != HttpMethod.PATCH && httpMethod != null) {
        super.service(request, response);
    } else {
        this.processRequest(request, response);
    }

}
我们的HttpMethod 应该是POST或者GET方法,所以执行super.service(request, response);回到HttpServlet的service(HttpServletRequest req, HttpServletResponse resp)方法:
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String method = req.getMethod();
    long lastModified;
    if (method.equals("GET")) {
        lastModified = this.getLastModified(req);
        if (lastModified == -1L) {
            this.doGet(req, resp);
        } else {
            long ifModifiedSince = req.getDateHeader("If-Modified-Since");
            if (ifModifiedSince < lastModified) {
                this.maybeSetLastModified(resp, lastModified);
                this.doGet(req, resp);
            } else {
                resp.setStatus(304);
            }
        }
    } else if (method.equals("HEAD")) {
        lastModified = this.getLastModified(req);
        this.maybeSetLastModified(resp, lastModified);
        this.doHead(req, resp);
    } else if (method.equals("POST")) {
        this.doPost(req, resp);
    } else if (method.equals("PUT")) {
        this.doPut(req, resp);
    } else if (method.equals("DELETE")) {
        this.doDelete(req, resp);
    } else if (method.equals("OPTIONS")) {
        this.doOptions(req, resp);
    } else if (method.equals("TRACE")) {
        this.doTrace(req, resp);
    } else {
        String errMsg = lStrings.getString("http.method_not_implemented");
        Object[] errArgs = new Object[]{method};
        errMsg = MessageFormat.format(errMsg, errArgs);
        resp.sendError(501, errMsg);
    }
}
我们一GET请求为例,直接看this.doGet(req, resp);回到FrameworkServlet的doGet方法:
protected final void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    this.processRequest(request, response);
}
执行processRequest方法:
protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    long startTime = System.currentTimeMillis();
    Throwable failureCause = null;
    //
    LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
    LocaleContext localeContext = this.buildLocaleContext(request);//此处调用其实现类的buildLocaleContext方法,spring中即DispatcherServlet,来创建localeContext 对象
    RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
    ServletRequestAttributes requestAttributes = this.buildRequestAttributes(request, response, previousAttributes);
    WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    //注册拦截器registerCallableInterceptor
    asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new FrameworkServlet.RequestBindingInterceptor());
    //初始化应用context
    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);
    }

}
可以看到,在FrameworkServlet的processRequest方法中执行了一系列的初始化操作,然后调用this.doService(request, response);也就是调用DispatcherServlet的doService方法
来看DispatcherServlet的doService方法的源码:
    protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
    //省略掉一些request属性的代码
    try {
        this.doDispatch(request, response);
    } finally {
        if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted() && attributesSnapshot != null) {
            this.restoreAttributesAfterInclude(request, attributesSnapshot);
        }
    }
}
该方法中主要完成一些request的属性设置,然后this.doDispatch(request, response);源码如下:
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 mv = null;
            Object dispatchException = null;

            try {
                //检查容器中是否同时存在多个不同的请求
                processedRequest = this.checkMultipart(request);
                multipartRequestParsed = processedRequest != request;
                //从容器中获取mappedHandler 
                mappedHandler = this.getHandler(processedRequest);
                if (mappedHandler == null || mappedHandler.getHandler() == null) {
                    this.noHandlerFound(processedRequest, response);
                    return;
                }
                 //从容器中获取适配器HandlerAdapter 
                HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
                String method = request.getMethod();
                boolean isGet = "GET".equals(method);
                //处理get请求
                if (isGet || "HEAD".equals(method)) {
                    //lastModified 上一次请求,此处返回-1
                    long lastModified = ha.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;
                    }
                }
                //执行拦截器中的preHandle拦截方法
                if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                    return;
                }
                //执行用户controller中对应的业务
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                if (asyncManager.isConcurrentHandlingStarted()) {
                    return;
                }
                //渲染默认的mv
                this.applyDefaultViewName(processedRequest, mv);
                //执行PostHandle拦截方法
                mappedHandler.applyPostHandle(processedRequest, response, mv);
            } catch (Exception var20) {
                dispatchException = var20;
            } catch (Throwable var21) {
                dispatchException = new NestedServletException("Handler dispatch failed", var21);
            }
            //渲染返回值
            this.processDispatchResult(processedRequest, response, mappedHandler, mv, (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);
        }

    }
}

以上是关于Spring 框架中Http请求处理流程的主要内容,如果未能解决你的问题,请参考以下文章

图解 Spring:HTTP 请求的处理流程与机制

图解 Spring:HTTP 请求的处理流程与机制

图解 Spring:HTTP 请求的处理流程与机制

struts 处理流程

图解 Spring:HTTP 请求的处理流程与机制

图解 Spring:HTTP 请求的处理流程与机制