美文网首页
Spring MVC源码阅读

Spring MVC源码阅读

作者: 飞盏 | 来源:发表于2018-09-21 17:31 被阅读0次
    spring mvc 请求处理流程
    SpringMVC核心处理流程:
    
    1、DispatcherServlet前端控制器接收发过来的请求,交给HandlerMapping处理器映射器
    
    2、HandlerMapping处理器映射器,根据请求路径找到相应的HandlerAdapter处理器适配器(处理器适配器就是那些拦截器或Controller)
    
    3、HandlerAdapter处理器适配器,请求数据绑定和转换,处理一些功能请求,返回一个ModelAndView对象(包括模型数据、逻辑视图名)
    
    4、ViewResolver视图解析器,先根据ModelAndView中设置的View解析具体视图
    
    5、然后再将Model模型中的数据渲染到View上
    
    这些过程都是以DispatcherServlet为中轴线进行的。
    
    

    1.入口源码

    springMVC的请求会交由dispatcherServlet处理,其本质上是一个多线程的请求处理机制;核心业务逻辑被设计在doDispatcher(..)方法中;

    /**
     * Process the actual dispatching to the handler.
     * <p>The handler will be obtained by applying the servlet's HandlerMappings in order.
     * The HandlerAdapter will be obtained by querying the servlet's installed HandlerAdapters
     * to find the first that supports the handler class.
     * <p>All HTTP methods are handled by this method. It's up to HandlerAdapters or handlers
     * themselves to decide which methods are acceptable.
     * @param request current HTTP request
     * @param response current HTTP response
     * @throws Exception in case of any kind of processing failure
     */
    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);
     
              // 绑定url -> 具体的handler/Controller.method(..)
             // Determine handler for the current request.
             mappedHandler = getHandler(processedRequest);
             if (mappedHandler == null || mappedHandler.getHandler() == null) {
                noHandlerFound(processedRequest, response);
                return;
             }
     
             // 根据handler绑定具体的adapter
             // 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;
                }
             }
     
             // interceptor 拦截器进行前置预处理
             if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                return;
             }
     
             // 在handle方法中进行了请求数据的绑定,方法invoke,返回model的处理和封装等
             // Actually invoke the handler.
             mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
     
             if (asyncManager.isConcurrentHandlingStarted()) {
                return;
             }
     
             applyDefaultViewName(processedRequest, mv);
             mappedHandler.applyPostHandle(processedRequest, response, mv);
          }
          catch (Exception ex) {
             dispatchException = ex;
          }
          catch (Throwable err) {
             // As of 4.3, we're processing Errors thrown from handler methods as well,
             // making them available for @ExceptionHandler methods and other scenarios.
             dispatchException = new NestedServletException("Handler dispatch failed", err);
          }
          processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
       }
       catch (Exception ex) {
          triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
       }
       catch (Throwable err) {
          triggerAfterCompletion(processedRequest, response, mappedHandler,
                new NestedServletException("Handler processing failed", 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.核心关注的几个问题

    2.1 请求如何路由到具体的Controller上的方法进行处理?

    根据请求路径,与已知的handlerMapping进行匹配,并加入interceptors:

    dispatcherServlet.getHandler()最终调用AbstracteHandlerMapping.getHandlerExecutionChain(..)中
    进行url与handlerMapping进行匹配,并加入interceptors;

    2.2 扁平化的前端请求数据如何进行数据绑定?

    我们知道,前端的get/post等请求,会被requestServlet接受,并封装成HttpServletRequest的parameterMap中,每一项请求的数据结构都是 K-V 形的。

    而我们知道,像这样的形式, image.png

    那么在这个中间数据如何实现数据绑定到Bean,String格式的Value 转换成各种目标格式。

    事实上,spring MVC将整个网络请求的处理流程进行了合理的切分,其大致的处理流程如下:

    1.调用匹配到的adapter.handle(..)
    
    2.然后调用invokeAndHandle(..)
    
    3.调用invokeForRequest(..)获取getMethodArgumentValues(..)获取和绑定入参;
    
    4.在具体的方法中,获取支持处理的argumentResolvers,然后调用resolveArgument(..)方法;
    
    5.在ModelAttributeMethodProcessor中调用bindRequestParameters(binder, webRequest),方法,然后再调用bind()进行bean参数的绑定;
    
    6.调用binder.convertIfNecessary(arg, parameter.getParameterType(), parameter)方法进行参数的转换;
    
    数据绑定调用堆栈 请求参数最初都是扁平化的

    相关文章

      网友评论

          本文标题:Spring MVC源码阅读

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