springMVC 请求处理流程

因为 DispatcherServlet 是一个 servlet,所以初始化的时候是入口是 init() 方法

处理请求也是一样的,Servlet 处理请求的方法是 service(),所以入口也是这里,开始找子类,看哪个类复写了 service(),发现是 HttpServlet ,从这里开始分析

注意不要找到 FrameworkServlet 类了,这个类的参数和 Servlet 的参数不一致,一个是 ServletRequest 和 HttpServletRequest

  1. javax.servlet.http.HttpServlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)

    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;
            // 强转 HttpServletRequest 调用 service
            this.service(request, response);
        } else {
            throw new ServletException("non-HTTP request or response");
        }
    }
    
  2. javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)

    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getMethod();
        long lastModified;
        if (method.equals("GET")) {
            // 巴拉巴拉,主要是调用这个方法
            this.doGet(req, resp);
        } 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 调用 doGet(),如果是 delete 调用 doDelete()

    点进每个 doXXX 方法,这时要注意,这个虽然不是模板方法(有具体实现),但是有子类复写,根据面向对象,所以不管自己的实现,要去找子类的实现

    子类是 FrameworkServlet,每个方法调用了的同一个方法 processRequest()

  3. org.springframework.web.servlet.FrameworkServlet#processRequest

        protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            ...
    
            try {
                // 这里调用了 doService
                this.doService(request, response);
            } catch (IOException | ServletException var16) {
              ...
            } finally {
               ...
                this.publishRequestHandledEvent(request, response, startTime, (Throwable)failureCause);
            }
    
        }
    

    doService() 是个模板方法,又找子类,就到了 DispatcherServlet 了,doService() 又调用了 doDispatch() 方法

    至此,可以知道,每个请求过来都会到 DispatcherServlet 的 doDispatch 方法,开始分析这个方法

  4. org.springframework.web.servlet.DispatcherServlet#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);
    
                // 这里找 handler(注意是处理器执行链,不仅仅是 handler)
                mappedHandler = getHandler(processedRequest);
                
                ...
    
                // 这里找 handler 的适配器(目前有个 handler 执行链,不会直接执行,而是要用适配器去执行)
                HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    
                ...
    
                // 这里通过是配置执行处理器执行链(其实只是执行 handler,拦截器不在这里执行)
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    
                if (asyncManager.isConcurrentHandlingStarted()) {
                    return;
                }
    
                applyDefaultViewName(processedRequest, mv);
                // 这里执行拦截器
                mappedHandler.applyPostHandle(processedRequest, response, mv);
            }
            catch (Exception ex) {
               ...
            }
            catch (Throwable err) {
                ...
            }
            // 处理异常、视图渲染、生成模型数据、完成请求处理(释放资源啥的)。因为现在都是 json 异步交互,视图这块没必要看,后面专门说参数转换
            processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
        }
        catch (Exception ex) {
            ...
        }
        catch (Throwable err) {
          ...
        }
        finally {
            ...
        }
    }
    
  5. 怎么得到处理器执行链

    // org.springframework.web.servlet.DispatcherServlet#getHandler
    @Nullable
    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        // 这里直接遍历所有的处理器映射器(初始化完成的,具体是根据 mvc 注解驱动完成,初始化过程在上一篇文章中)
        if (this.handlerMappings != null) {
            for (HandlerMapping mapping : this.handlerMappings) {
                // 得到了 handler(处理器执行链)
                HandlerExecutionChain handler = mapping.getHandler(request);
                if (handler != null) {
                    return handler;
                }
            }
        }
        return null;
    }
    
    // org.springframework.web.servlet.handler.AbstractHandlerMapping#getHandler
    @Override
    @Nullable
    public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        // 这里拿到 handler(handler其实就是 controller 里方法的抽象,一个 controller 的方法就是一个 handler)
        // 具体就不贴源码了,不然篇幅太多了。大致原理是:初始化的时候再 RequestMappingHandlerMapping 维护了一堆属性,根据 url 去匹配得到
        Object handler = getHandlerInternal(request);
        
        ...
            
        // 这里得到了处理器执行链,源码也不翻了,代码很少,并且也很清晰,就是遍历所有拦截器包装原始的处理器得到处理器执行链
        HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
    
        ...
            
        return executionChain;
    }
    
  6. 怎么得到处理器适配器

    // org.springframework.web.servlet.DispatcherServlet#getHandlerAdapter
    protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
        // 同处理器映射器,初始化时就准备好了
        if (this.handlerAdapters != null) {
            for (HandlerAdapter adapter : this.handlerAdapters) {
                // 当前适配器是否能处理 handler
                if (adapter.supports(handler)) {
                    return adapter;
                }
            }
        }
        throw new ServletException("No adapter for handler [" + handler +
                "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
    }
    
    // org.springframework.web.servlet.handler.SimpleServletHandlerAdapter#supports
    @Override
    public boolean supports(Object handler) {
        // 如果当前 handler 是 Servlet,SimpleServletHandlerAdapter 就能处理
        return (handler instanceof Servlet);
    }
    
    // org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter#supports
    @Override
    public boolean supports(Object handler) {
        // 如果当前 handler 是 Controller,SimpleControllerHandlerAdapter 就能处理
        return (handler instanceof Controller);
    }
    
    // org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#supports
    @Override
    public final boolean supports(Object handler) {
        return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler));
    }
    // org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#supportsInternal
    @Override
    protected boolean supportsInternal(HandlerMethod handlerMethod) {
        return true;
    }
    
  7. 怎么执行处理器,源码就不贴了,流程中真正执行的方法在这里

    // org.springframework.web.method.support.InvocableHandlerMethod#invokeForRequest
    @Nullable
    public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
        // 这是请求参数,这里会把参数封装到 controller 的参数上,具体怎么解析也是一门大学问,包括 @ResponseBody 怎么把对象转成 json 的,放在后面的文章中
        Object[] args = this.getMethodArgumentValues(request, mavContainer, providedArgs);
        if (this.logger.isTraceEnabled()) {
            this.logger.trace("Arguments: " + Arrays.toString(args));
        }
    	// 把参数传到 doInvoke,这里真正执行
        return this.doInvoke(args);
    }
    
    // org.springframework.web.method.support.InvocableHandlerMethod#doInvoke
    @Nullable
    protected Object doInvoke(Object... args) throws Exception {
        ReflectionUtils.makeAccessible(getBridgedMethod());
        try {
            // getBridgedMethod() 是一个 java.lang.reflect.Method(jdk 的,也就是 handler 那个方法),就是 java 的反射执行方法而已
            return getBridgedMethod().invoke(getBean(), args);
        }
        ...
    }
    

    问题:已经找到了 handler(具体 controller 的方法),底层已经知道了是反射执行,为什么要用适配器去执行?为什么不直接反射执行?

    因为还要处理参数,请求参数响应参数都要根据具体的类型去处理,所以抽象到一个对象中统一处理,所以每一个适配器中会有对应的参数解析器

posted @ 2024-07-01 15:54  CyrusHuang  阅读(1)  评论(0编辑  收藏  举报