• Spring 框架中Http请求处理流程


    Spring Web http request请求流程:

    首先介绍这边你需要知道的继承体系,DispacherServlet继承自FrameworkServlet,FrameworkServlet继承自HttpServletBean,HttpServletBean继承自HttpServlet,HttpServlet继承自GenericServlet,GenericServlet实现Servlet、ServletConfig接口,我们的流程从请求进入到GenericServlet的service方法开始说起。
    
    • 拦截器是在DispacherServlet的doDispatch方法中执行的,(url拦截器和用户自定义的其他业务拦截器)

    流程总览:

    容器监听端口,接收到请求后调用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 {
                    //处理multipart 请求
                    processedRequest = this.checkMultipart(request);
                    multipartRequestParsed = processedRequest != request;
                    //从容器中获取mappedHandler 
                    mappedHandler = this.getHandler(processedRequest);
                    if (mappedHandler == null || mappedHandler.getHandler() == null) {
                        this.noHandlerFound(processedRequest, response);
                        return;
                    }
                     // 从容器中获取适配器HandlerAdapter 。这个过程中,会调用MappedInterceptor的matches方法,以此来判断次url是否在拦截范围内
                    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);
            }
    
        }
    }
  • 相关阅读:
    解析python数据后用html输出
    python 自动化测试HTTP接口
    python 自动化对比返回结果
    Java 基础知识 练习
    Java 菜鸟学习之 script脚本语句
    java语言的认识
    Script 语言的简单练习题 乘法口诀
    Script 简单语句的练习题
    Java菜鸟培训第二天
    36个号码随机摇奖编码
  • 原文地址:https://www.cnblogs.com/canmeng-cn/p/9040395.html
Copyright © 2020-2023  润新知