springmvc源码解析----执行流程(1)

该流程是基于继承controller来编写的接口来解析的:

在这里插入图片描述

根据Servlet规范,当用户请求到达应用时,由Servlet的service()方法进行处理,对于Spring MVC而言,处理用户请求的入口为DispatcherServlet,通过其父类FrameworkServlet的service()拦截处理。

FrameworkServlet

用户请求的入口方法为service(request,response),源码如下:

org.springframework.web.servlet.FrameworkServlet#service

/**
*主要是判断请求的类型
*/
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
// Spring3.0增加了PATCH方法拦截处理
    if (httpMethod != HttpMethod.PATCH && httpMethod != null) {
        super.service(request, response);
    } else {  // GET, HEAD, POST, PUT, DELETE, OPTIONS, TRACE
        this.processRequest(request, response);
    }
}

该方法重写了HttpServlet的service()方法,并增加了PATCH请求的拦截处理,其他诸如GET、POST、PUT等请求则调用父类的service方法,HttpServlet类的service()方法就是根据请求类型进行不同的路由处理,如为GET请求,则路由至doGet()方法处理,以此类推,此处省略源码。最终都会调用到processRequest(request, response)方法。

processRequest()方法源码如下:

org.springframework.web.servlet.FrameworkServlet#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);
    RequestAttributes previousAttributes = RequestContextHolder.getRequestAttributes();
    
    // 构建请求(request)的ServletRequestAttributes对象,保存本次请求的request和response
    ServletRequestAttributes requestAttributes = this.buildRequestAttributes(request, response, previousAttributes);
    
    // 异步请求处理的管理核心类
    WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    asyncManager.registerCallableInterceptor(FrameworkServlet.class.getName(), new FrameworkServlet.RequestBindingInterceptor());
    
    // 绑定request context上线到当前线程
    this.initContextHolders(request, localeContext, requestAttributes);
    try {
    
        // 模板方法,调用子类(DispatcherServlet)的doService方法进行处理
        this.doService(request, response);
    } catch (IOException | ServletException var16) {
        failureCause = var16;
        throw var16;
    } catch (Throwable var17) {
        failureCause = var17;
        throw new NestedServletException("Request processing failed", var17);
    } finally {
        this.resetContextHolders(request, previousLocaleContext, previousAttributes);
        if (requestAttributes != null) {
            requestAttributes.requestCompleted();
        }
        this.logResult(request, response, (Throwable)failureCause, asyncManager);
        this.publishRequestHandledEvent(request, response, startTime, (Throwable)failureCause);
    }
}

DispatcherServlet

org.springframework.web.servlet.DispatcherServlet#doService

//这里只看一条关键代码:
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
    this.logRequest(request);
    Map<String, Object> attributesSnapshot = null;
    if (WebUtils.isIncludeRequest(request)) {
        attributesSnapshot = new HashMap();
        Enumeration attrNames = request.getAttributeNames();
        label95:
        while(true) {
            String attrName;
            do {
                if (!attrNames.hasMoreElements()) {
                    break label95;
                }
                attrName = (String)attrNames.nextElement();
            } while(!this.cleanupAfterInclude && !attrName.startsWith("org.springframework.web.servlet"));
            attributesSnapshot.put(attrName, request.getAttribute(attrName));
        }
    }
    request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.getWebApplicationContext());
    request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
    request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
    request.setAttribute(THEME_SOURCE_ATTRIBUTE, this.getThemeSource());
    if (this.flashMapManager != null) {
        FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
        if (inputFlashMap != null) {
            request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
        }
        request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
        request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
    }
    try {
        //调用本类的doDispatch做请求分发处理
        this.doDispatch(request, response);
    } finally {
        if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted() && attributesSnapshot != null) {
            this.restoreAttributesAfterInclude(request, attributesSnapshot);
        }
    }
}

doDispatch

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 {
        try {
            ModelAndView mv = null;
            Object dispatchException = null;
            try {
            
	            //检查请求有没有附带一个文件
                processedRequest = this.checkMultipart(request);
                
                multipartRequestParsed = processedRequest != request;
                
            	//1.根据请求的地址确定相应的映射对象,简单来说就是找到controller,具体看下面1.的解析
                mappedHandler = this.getHandler(processedRequest);
                
	            //如果没有找到对应的控制器来处理这个请求,则报404
                if (mappedHandler == null) {
                    this.noHandlerFound(processedRequest, response);
                    return;
                }
                
	            //2.根据控制器映射对象确定对应的适配器,该适配器(反射工具)用于调用控制器方法
                HandlerAdapter ha = this.getHandlerAdapter(mappedHandler.getHandler());
                
                String method = request.getMethod();
                boolean isGet = "GET".equals(method);
                if (isGet || "HEAD".equals(method)) {
                    long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                    if ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
                        return;
                    }
                }
                if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                    return;
                }
                
	             //3.调用自己写的Controller1,返回给ModelAndView,ModelAndView又定义在DispatcherServlet中,所以DispatcherServlet也就拿到了,源码看下面3.
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                if (asyncManager.isConcurrentHandlingStarted()) {
                    return;
                }

				/**
				*设置默认的逻辑视图名称
				*如果handler返回null或者ViewName属性为null时,Spring进行取视图规则为:前缀+url+后缀
				*比如访问url为:http://localhost:8086/test,前缀配置/WEB-INF/jsp,后缀配置为.jsp,那么最终查找的
				*是:/WEB-INF/jsp/test.jsp
				*/
                this.applyDefaultViewName(processedRequest, mv);
                
                mappedHandler.applyPostHandle(processedRequest, response, mv);
            } catch (Exception var20) {
                dispatchException = var20;
            } catch (Throwable var21) {
                dispatchException = new NestedServletException("Handler dispatch failed", var21);
            }
            
	        //4. 根据封装了数据和视图的ModelAndView处理转发的页面
            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);
        }
    }
}

1. getHandler()

org.springframework.web.servlet.DispatcherServlet#getHandler

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    if (this.handlerMappings != null) {
        Iterator var2 = this.handlerMappings.iterator();

		//通过遍历的方法找到合适的映射器
        while(var2.hasNext()) {
            HandlerMapping mapping = (HandlerMapping)var2.next();
            HandlerExecutionChain handler = mapping.getHandler(request);
            if (handler != null) {
                return handler;
            }
        }
    }
    return null;
}

源码解析(1)中处理器我们是通过继承controller类来实现的,所以这里映射器匹配的是BeanNameUrlHandlerMapping,在未进行任何配置HandlerMapping时,系统使用(支持)默认的BeanNameUrlHandlerMapping和RequestMappingHandlerMapping映射解析器。

Spring MVC为我们提供了多种处理用户的处理器(Handler),Spring实现的处理器类型有Servlet、Controller、HttpRequestHandler以及注解类型的处理器,即我们可以通过实现这些接口或者注解我们的类来使用这些处理器,那么针对不同类型的处理器,如何将用户请求转发到相应类型的处理器方法中的呢,这就需求Spring MVC的处理器适配器来完成适配操作,这就是处理器适配器要完成的工作。

2. getHandlerAdapter()

//通过获取的处理器映射器匹配合适的处理器适配器
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
    if (this.handlerAdapters != null) {
        Iterator var2 = this.handlerAdapters.iterator();
        while(var2.hasNext()) {
            HandlerAdapter adapter = (HandlerAdapter)var2.next();
         	//校验是否支持
            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");
}

适配器有如下几种:

在这里插入图片描述

SimpleServletHandlerAdapter 适配Servlet处理器
HttpRerquestHandlerAdapter 适配HttpRequestHandler处理器
RequestMappingHandlerAdapter 适配注解处理器
SimpleControllerHandlerAdapter 适配Controller处理器

3. 进入handle()方法中

因为在源码解析(1)中我们是通过继承controller类来实现的处理器,所以使用的处理器适配器是
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter#handle

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

    //转成controller调用对应的handleRequest方法,因为是继承controller类实现的处理器,当然能转成controller
    return ((Controller)handler).handleRequest(request, response);
}

4. processDispatchResult

private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv, @Nullable Exception exception) throws Exception {
    boolean errorView = false;
    //异常处理
    if (exception != null) {
        if (exception instanceof ModelAndViewDefiningException) {
            this.logger.debug("ModelAndViewDefiningException encountered", exception);
            mv = ((ModelAndViewDefiningException)exception).getModelAndView();
        } else {
            Object handler = mappedHandler != null ? mappedHandler.getHandler() : null;
            mv = this.processHandlerException(request, response, handler, exception);
            errorView = mv != null;
        }
    }
    if (mv != null && !mv.wasCleared()) {
    
  		/* *渲染ModelAndView */
        this.render(mv, request, response);
        
        if (errorView) {
            WebUtils.clearErrorRequestAttributes(request);
        }
    } else if (this.logger.isTraceEnabled()) {
        this.logger.trace("No view rendering, null ModelAndView returned.");
    }
    if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
        if (mappedHandler != null) {
            mappedHandler.triggerAfterCompletion(request, response, (Exception)null);
        }
    }
}

Render():

org.springframework.web.servlet.DispatcherServlet#render

protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response) throws Exception {
    Locale locale = this.localeResolver != null ? this.localeResolver.resolveLocale(request) : request.getLocale();
    response.setLocale(locale);
    
    // 获取逻辑视图名称
    String viewName = mv.getViewName();
    
    View view;
    if (viewName != null) {
    
        // 根据逻辑视图名解析视图,返回View对象
        view = this.resolveViewName(viewName, mv.getModelInternal(), locale, request);
        if (view == null) {
            throw new ServletException("Could not resolve view with name '" + mv.getViewName() + "' in servlet with name '" + this.getServletName() + "'");
        }
    } else {
        view = mv.getView();
        if (view == null) {
            throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a View object in servlet with name '" + this.getServletName() + "'");
        }
    }

    if (this.logger.isTraceEnabled()) {
        this.logger.trace("Rendering view [" + view + "] ");
    }

    try {
        if (mv.getStatus() != null) {
            response.setStatus(mv.getStatus().value());
        }
        
		// 调用View的render方法进行视图渲染,这一步才是到了真正的视图渲染
        view.render(mv.getModelInternal(), request, response);
    } catch (Exception var8) {
        if (this.logger.isDebugEnabled()) {
            this.logger.debug("Error rendering view [" + view + "]", var8);
        }
        throw var8;
    }
}
org.springframework.web.servlet.view.AbstractView#render

public void render(@Nullable Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception {

      // .....
      
     // 暴露模型,此方法主要在子类中被重写
    this.renderMergedOutputModel(mergedModel, this.getRequestToExpose(request), response);
}

进入实现的renderMergedOutputModel()方法 :

org.springframework.web.servlet.view.InternalResourceView#renderMergedOutputModel

protected void renderMergedOutputModel(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
    this.exposeModelAsRequestAttributes(model, request);
    this.exposeHelpers(request);
    String dispatcherPath = this.prepareForRendering(request, response);
    RequestDispatcher rd = this.getRequestDispatcher(request, dispatcherPath);
    if (rd == null) {
        throw new ServletException("Could not get RequestDispatcher for [" + this.getUrl() + "]: Check that the corresponding file exists within your web application archive!");
    } else {
        if (this.useInclude(request, response)) {
            response.setContentType(this.getContentType());
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Including [" + this.getUrl() + "]");
            }

            rd.include(request, response);
        } else {
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Forwarding to [" + this.getUrl() + "]");
            }
             //将请求返回给前端,这个等同于我们原来的 request.getRequestDispatcher(dispatcherPath).forward(request,response);
            rd.forward(request, response);
        }
    }
}

当接口是继承HttpRequestHandler类来实现的时候,执行过程跟此过程类似,只是其中调用的 映射器 跟 适配器实现类 不同,映射器使用的是BeanNameUrlHandlerMapping ,适配器使用的是HttpRerquestHandlerAdapter。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值