【SpringMVC】源码阅读

本文深入解析了Spring MVC框架的核心组件,包括处理器Handler、拦截器HandlerInterceptor、处理器映射HandlerMapping、处理器适配器HandlerAdapter等,以及它们在请求处理流程中的作用。还介绍了参数解析器HandlerMethodArgumentResolver和返回值处理器HandlerMethodReturnValueHandler的工作原理,特别是如何支持@ResponseBody注解的JSON响应处理。

这里写图片描述

一、框架预览

img

二、定义与对象

首先必须了解处理器即handler是什么:你在前期可以直接理解为controller方法

  • HttpServlet定义了规范, 但是如果不重写doGet方法的话就会报错

  • FrameworkServlet重写了doGet(),实现了HttpServletBean

  • DispatcherServlet:派发到处理器上

  • HanlderInterceptor,接口3个方法

    • preHandle//请求开始之前
      postHandle//请求结束之后,画面渲染之前
      afterCompletion//画面渲染之后。有的时候画面不存在,只有返回modelAndView时画面才存在,返回json时没有画面
      //jdk8之后该接口有default,可以不重写
      
  • // 抽象类,都是空实现 // JDK8之前需要重写接口所有方法,如果直接使用这个抽象类省略重写方法
    public abstract class HandlerInterceptorAdapter
        implements AsyncHandlerInterceptor {
         
         //内部是HandlerInterceptor接口
        // 为了方便jdk8之前直接使用 
        @Override
        public boolean preHandle(HttpServletRequest request,
                                 HttpServletResponse response, Object handler)
            throws Exception {
         
         
            return true;
      }
    
  • HandlerMapping:处理请求到处理器,即映射到java方法的封装

    • RequestMappingHandlerMapping:映射器+处理器
  • HandlerMethod:java方法的封装

  • HandlerAdapter:为了重写老式重写Controller接口的类。从HandlerMapping中拿到HandlerMethod后ha去参数解析等操作

  • MethodParameter:对HandlerMethod的参数的封装,比如还有@PathVariable

  • HandlerMethodArgumentResolver:对上面参数解析,比如请求/getById/{1}就可以把id注入到id参数上。他的实现比如是解析@PathVariable,又比如是解析@RequestParam

    • // HandlerMethodArgumentResolver接口的方法
      
      //返回true代表是@PathVariable,可以进入resolveArgument
      boolean supportsParameter(MethodParameter parameter);
      // 
      Object resolveArgument(MethodParameter parameter, 
                             @Nullable ModelAndViewContainer mavContainer,
                             NativeWebRequest webRequest, 
                             @Nullable WebDataBinderFactory binderFactory) throws Exception;
      
  • HandlerMethodArgumentResolverComposite:组合模式,持有全部的参数解析器resolver

    • 组合模式就是说 list的调用方法和一个元素怒的调用方法是一样的

    • class HandlerMethodArgumentResolverComposite
          implements HandlerMethodArgumentResolver {
             
             
          
          private final List<HandlerMethodArgumentResolver> argumentResolvers = new LinkedList<>();
          private final Map<MethodParameter, HandlerMethodArgumentResolver> argumentResolverCache =
      			new ConcurrentHashMap<>(256);
      
          public HandlerMethodArgumentResolverComposite addResolver(HandlerMethodArgumentResolver resolver) {
             
             
              this.argumentResolvers.add(resolver);
              return this;
          }
          // 重点 // 是否支持解析该参数
          public boolean supportsParameter(MethodParameter parameter) {
             
             
              return getArgumentResolver(parameter) != null; // 不为空
          }
          // 重点 // 解析参数
          public Object resolveArgument(MethodParameter parameter,
                                        @Nullable ModelAndViewContainer mavContainer,
                                        NativeWebRequest webRequest,
                                        @Nullable WebDataBinderFactory binderFactory)  {
             
             
      
              HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
              if (resolver == null) {
             
              报错无法解析参数类型 parameter.getParameterType() }
              return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
          }
          private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
             
             
              // 缓存
              HandlerMethodArgumentResolver result = this.argumentResolverCache.get(parameter);
              // 缓存为空,遍历list
              if (result == null) {
             
             
                  for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) {
             
             
                      if (resolver.supportsParameter(parameter)) {
             
             
                          result = resolver;
                          // 添加到缓存
                          this.argumentResolverCache.put(parameter, result);
                          break;
                      }
                  }
              }
              return result;
          }
      
  • RequestResponseBodyMethodProcessor:实现了HandlerMethodArgumentResolver。处理两种body请求@RequestBody@ResponseBody

    • public boolean supportsParameter(MethodParameter parameter) {
             
             
          return parameter.hasParameterAnnotation(RequestBody.class);//@RequestBody
      }
      public boolean supportsReturnType(MethodParameter returnType) {
             
             
          //@ResponseBody方法上或者类上有没有注解
          return (AnnotatedElementUtils.hasAnnotation(returnType.getContainingClass(), ResponseBody.class) ||
                  returnType.hasMethodAnnotation(ResponseBody.class));
      }
      // java对象转json
      public void handleReturnValue(@Nullable Object returnValue, MethodParameter returnType,
                                    ModelAndViewContainer mavContainer, NativeWebRequest webRequest){
             
             
      
          mavContainer.setRequestHandled(true);
          ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
          ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);
      
          // Try even with null return value. ResponseBodyAdvice could get involved.
          writeWithMessageConverters(returnValue, returnType, inputMessage, outputMessage);
      }
      

private方法也能被请求到

HttpServlet
protected void doGet(HttpServletRequest req, 
                     HttpServletResponse resp) {
   
   
    String protocol = req.getProtocol();
    String msg = lStrings.getString("http.method_get_not_supported");
    if (protocol.endsWith("1.1")) {
   
   
        resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);//405
    } else {
   
   
        resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);//400
    }
}
FramewordServlet

重写了doGet

public abstract class FrameworkServlet
    extends HttpServletBean
    implements ApplicationContextAware {
   
   
    
    @Override
    protected final void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
   
   
        processRequest(request, response);
    }
    
    @Override
    protected final void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
   
   
        processRequest(request, response);
    }
    
    // get和post都会跳转到这里 // 这个方法是final,而doService需要被重写,这是模板方法模式
    protected final void processRequest(HttpServletRequest request,
                                        HttpServletResponse response) {
   
   

        try {
   
   
            doService(request, response);//要被子类DispatcherServlet重写
        }
        finally {
   
   
            resetContextHolders(request, previousLocaleContext, previousAttributes);
            if (requestAttributes != null) {
   
   
                requestAttributes.requestCompleted();
            }
            logResult(request, response, failureCause, asyncManager);
            publishRequestHandledEvent(request, response, startTime, failureCause);
        }

首先,Tomcat每次启动时都会加载并解析/WEB-INF/web.xml文件,所以可以先从web.xml找突破口,主要代码如下:

<servlet >
    <servlet-name >spring-mvc</servlet-name>
    <!-- servlet类 -->
    <servlet-class>
        org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <!-- 初始化参数 -->
    <init-param >
        <param-name >contextConfigLocation</param-name>
        <param-value >classpath:/spring-mvc.xml</param-value>
    </init-param>
    <!-- 启动时加载 -->
    <load-on-startup >1</load-on-startup>
</servlet>

<servlet-mapping >
    <servlet-name >spring-mvc</servlet-name>
    <url-pattern >/</url-pattern>
</servlet-mapping>

我们可以从web.xml文件获得三个信息,分别是:servlet类为DispatcherServlet,它在启动时加载,加载时初始化参数contextConfigLocation为classpath下spring-mvc.xml的文件地址,接下来我们将目光移到DispatcherServlet类。

DispatcherServlet

很明显,它是一个Servlet的子类,其实不用说也知道,因为web.xml早已有配置。既然是Servlet,我们就要专注于它的service、doGet、doPost等相关方法,在它的父类FrameServlet,我们找到了service方法。

protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
   
   
    logRequest(request);

    // Keep a snapshot of the request attributes in case of an include,
    // to be able to restore the original attributes after the include.
    Map<String, Object> attributesSnapshot = null;
    if (WebUtils.isIncludeRequest(request)) {
   
   
        attributesSnapshot = new HashMap<>();
        Enumeration<?> attrNames = request.getAttributeNames();
        while (attrNames.hasMoreElements()) {
   
   
            String attrName = (String) attrNames.nextElement();
            if (this.cleanupAfterInclude || attrName.startsWith(DEFAULT_STRATEGIES_PREFIX)) {
   
   
                attributesSnapshot.put(attrName, request.getAttribute(attrName));
            }
        }
    }

    // Make framework objects available to handlers and view objects.
    request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, getWebApplicationContext());
    request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
    request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
    request.setAttribute(THEME_SOURCE_ATTRIBUTE, 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 {
   
   
        // ====DispatcherServlet.doDispatch
        doDispatch(request, response);
    }
    finally {
   
   
        if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
   
   
            // Restore the original attribute snapshot, in case of an include.
            if (attributesSnapshot != null) {
   
   
                restoreAttributesAfterInclude(request, attributesSnapshot);
            }
        }
    }
}

@Override
protected void service(HttpServletRequest request, HttpServletResponse response) {
   
   

    String method = request.getMethod();
    if (method.equalsIgnoreCase(RequestMethod.PATCH.name())) {
   
   
        processRequest(request, response);
    }
    else {
   
   
        // 调用父类的service方法
        super.service(request, response);
    }
}

根据service方法,我们一步步找到一个方法链service –> processRequest –> doService –> doDispatch,我们最终将目光定位在doDispatch,因为从它的方法体就可以看出它是整个SpringMVC的核心方法。

三、流程预览

  • FrameworkdServlet.doGet()–>
  • FrameworkdServlet.processRequest()
  • DispatcherServlet.doService(request, response);
  • DispatcherServlet.doDispatch()
dis流程

img

①getHandler(processedRequest)
②getHandlerAdapter
③mappedHandler.applyPreHandle(
④mv = ha.handle
⑤mappedHandler.applyPostHandle
⑥processDispatchResult

四、DispatcherServlet.doDispatch

获取controller流程

  • 扫描整个项目,spring已经做了,定义了一个集合
  • 拿到所有加了 @Controller注解的类
  • 遍历类里面所有的方法对象
  • 判断方法是否加了@RequestMapping注解
  • @RequestMapping注解的value作为map的key。put(value,method对象)
  • 根据用户发送的请求 拿到请求中的URI,如test.do
  • 使用请求的uri作为map的key,去map中get,看看是否有返回值

handlerMappings是比如RequestMapping的,welcome的

每个handlerMapping有一个mappingRegistry,里面有个registry-map,key为如{POST/user}、{PUT/user}等,value为对应的MappingRegistration

doDispatch

这里写图片描述

// DispatcherServlet
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
   
   
    // 原生请求,coyote请求,跟tomcat有关
    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能处理当前请求
            // 解析请求,获取HandlerExecutionChain对象。即获取controller。类#方法()
            mappedHandler = getHandler(processedRequest);//processedRequest是对request的封装
            if (mappedHandler == null || mappedHandler.getHandler() == null) {
   
   
                noHandlerFound(processedRequest, response);
                return;
            }

            // 知道了handler还不够,还要反射调用方法,还要设置参数,把这些操作封装到了HandlerAdapter。用ha.handler()
            // 从HandlerExecutionChain对象获取HandlerAdapter对象,实际上是从HandlerMapping对象中获取
            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 (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
   
   
                    return;
                }
            }

            // 在controller方法执行前,调用拦截器的preHandle()
            if (!mappedHandler.applyPreHandle(processedRequest, response)) {
   
    // 返回false的话直接返回
                return;
            }

            try {
   
   
                // 真正执行HandlerAdapter对象的handler方法,返回ModelAndView
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
            }
            finally {
   
   
                if (asyncManager.isConcurrentHandlingStarted()) {
   
   
                    return;
                }
            }

            applyDefaultViewName(request, mv);
            // 在controller方法执行后,执行【拦截器】的postHandle()
            mappedHandler.applyPostHandle(processedRequest, response, mv);
        }
        catch (Exception ex) {
   
   
            dispatchException = ex;
        }
        // 进行视图解析
        processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
    } catch (Exception ex) {
   
   
        triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
    } catch (Error err) {
   
   
        triggerAfterCompletionWithError(processedRequest, response, mappedHandler, err);
    }
    finally {
   
   
        if (asyncManager.isConcurrentHandlingStarted()) {
   
   
            // Instead of postHandle and afterCompletion
            mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
            return;
        }
        // Clean up any resources used by a multipart request.
        if (multipartRequestParsed) {
   
   
            cleanupMultipart(processedRequest);
        }
    }
}

说它是核心一点也不为过,从上述代码的中文注释可以看出,它包含了解析请求,执行相关拦截器,执行handle方法(到这里关于handle方法是什么,我们一脸懵逼。别急,接下来我们会讲述,总之它很重要就对了),执行视图解析方法。

五、ds.getHandler

①ds.getHandler:从handlerMapping过去methodHandler

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
   
   
    if (this.handlerMappings != null) {
   
   
        // 遍历映射器。一直找,找到一个符合我们请求的映射器。从映射器中拿到处理器,即要拿到java方法,
        // handlerMappings的类型是list,分别是
        /* 
        RequestMappingHandlerMapping,//处理注解@RequestMapping,映射到handler。mapping.mappingRegistry.registry.mappingLookup()就能看到map,kv对映射RequestMappingInfo到HandlerMethod
        BeanNameUrlHandlerMapping,
        
        SimpleUrlHandlerMapping,
        WelcomePageHandlerMapping
        */
        for (HandlerMapping mapping : this.handlerMappings) {
   
   
            // 调用映射器的getHandler  //RequestMappingHandlerMapping  // @RequestMapping
            HandlerExecutionChain handler = mapping.getHandler(request);	//  @RequestMapping注解的
            if (handler != null) {
   
   
                return handler;
            }
        }
    }
    return null;
}

他会依次调用现有的handlerMappings集合,看看谁能处理当前的请求,这就是调用他们的getHandler()方法,要是处理不了他们就返回null了

RequestMapping中有个属性mappingRegistry,类型如下AbstractHandlerMethodMapping

private final MappingRegistry mappingRegistry = new MappingRegistry();//AbstractHandlerMethodMapping

mappingRegistry中有个属性mappingLookUp,是个map。第一个的key是"{GET/user/info/{firstName}}"->"...getUser()"

public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {
   
   

生成了handler之后,里面的属性就有HandlerMethod,interceptorList,

HandlerMethod的属性如

  • bean(controller的类型),
  • beanFactory,
  • bridgeMethod(匹配到的getUser方法)

拿到的handler就是mappedHandler,他的类型是HandlerExecutionChain

AbstractHandlerMapping.getHandler

public abstract class AbstractHandlerMapping 
    extends WebApplicationObjectSupport
    implements HandlerMapping, Ordered, BeanNameAware {
   
   

    // 查找hm中调用的方法
    public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
   
   
        // 
        Object handler = getHandlerInternal(request);
        if (handler == null) {
   
   
            handler = getDefaultHandler();
        }
        if (handler == null) {
   
   
            return null;
        }
        // Bean name or resolved handler?
        if (handler instanceof String) {
   
   
            String handlerName = (String) handler;
            handler = obtainApplicationContext().getBean(handlerName);
        }

        HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);

        if (logger.isTraceEnabled()) {
   
   
            logger.trace("Mapped to " + handler);
        }
        else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) {
   
   
            logger.debug("Mapped to " + executionChain.getHandler());
        }

        if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
   
   
            CorsConfiguration config = (this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(request) : null);
            CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
            config = (config != null ? config.combine(handlerConfig) : handlerConfig);
            executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
        }

        return executionChain;
    }
  • AbstractHandlerMethodMapping:处理注解的controller
  • AbstractUrlHandlerMapping:处理基础的controller
    • 都继承了AbstractHandlerMapping
public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {
   
   
public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping implements MatchableHandlerMapping {
   
   

这两个类都重写了getHandlerInternal方法

Mapping.getHandlerInternal

获取HandlerMethod

// 注解的
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
   
   
    String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
    request.setAttribute(LOOKUP_PATH, lookupPath);
    this.mappingRegistry.acquireReadLock();
    try {
   
   
    // 里面先根据请求拿到list,先添加到匹配集合,然后找到最佳匹配。get (0)
        HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
        return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
    }
    finally {
   
   
        this.mappingRegistry.releaseReadLock();
    }
}

// 查找处理器链 // 他map的key是bean名字
protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
   
   
    // 获得请求的uri
    String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
    request.setAttribute(LOOKUP_PATH, lookupPath);
    // 类的方式返回的是controller类对象,注解方式返回的是HandlerMethod对象。
    Object handler = lookupHandler(lookupPath, request);
    /*
     protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
		// 这个map的key是请求uri,valye是Controller对象
		Object handler = this.handlerMap.get(urlPath);
        */
    if (handler == null) {
   
   
        // We need to care for the default handler directly, since we need to
        // expose the PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE for it as well.
        Object rawHandler = null;
        if ("/".equals(lookupPath)) {
   
   
            rawHandler = getRootHandler();
        }
        if (rawHandler == null) {
   
   
            rawHandler = getDefaultHandler();
        }
        if (rawHandler != null) {
   
   
            // Bean name or resolved handler?
            if (rawHandler instanceof String) {
   
   
                String handlerName = (String) rawHandler;
                rawHandler = obtainApplicationContext().getBean(handlerName);
            }
            validateHandler(rawHandler, request);
            handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null);
        }
    }
    return handler;
}

通过handlerMapping拿到了handlerMethod,别的hm可能拿到的是别的类型
解析参数前有pre

六、ha适配器包装参数和返回值解析器

②ds.getHandlerAdapter

回到dispatch

不同的控制器实现方式需要用不同的方式去调用

protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
   
   
    if (this.handlerAdapters != null) {
   
   
        // handlerAdapters有3种:
        /* 适配器有3个
        RequestMappingHandlerAdaptor,  // @RequestMapping
        HttpRequestHandlerAdaptor,     // 实现HttpRequestHandler的,这里不考虑
        SimpleControllerHandlerAdaptor  // 实现Controller接口的
        // springboot里还有个HandlerrFunctionAdaptor // 支持函数向编程
        为什么3种适配器2种映射器?23在前面合并了
        */
        for (HandlerAdapter adapter : this.handlerAdapters) {
   
   
            if (adapter.supports(handler)) {
   
   //先调用supports
                return adapter;//ha
            }
        }
    }
    throw new ServletException("没有能解析该handler的adapter。DispatcherServlet配置需要包含这个handler的ha");
}

public abstract class AbstractHandlerMethodAdapter 
    extends WebContentGenerator implements HandlerAdapter, Ordered {
   
   
    
    public final boolean supports(Object handler) {
   
   
		return (handler instanceof HandlerMethod &&  // 是HandlerMethod类型,@Controller的都是封装为HandlerMethod
                supportsInternal((HandlerMethod) handler));
	}

已经拿到了RequestMappingHandlerAdaptor这个ha
拿ha是用support

④ha.handle

已经拿到了方法,但是方法参数还没有,把这个过程交给ha

1 ha接口

返回ModelAndView

/** MVC框架的SPI,允许MVC处理参数

Interface that must be implemented for each handler type to handle a request.
 这个接口用于允许DispatcherServlet无线扩展
 DispatcherServlet通过本类判断所有安装的handlers。
 
 handler可以是Object类型。这使其他框架的handlers融合到框架里。
HandlerAdapter的实现类也可能实现了Ordered接口,DispatcherServlet就可以按序获取
 */
public interface HandlerAdapter {
   
   

	/** 当前ha是否能解析该handler。。。HandlerAdapters一般只支持一个handler类型 */
	boolean supports(Object handler);

	/** 本ha是否能处理 使用给定的handlers处理本请求。通过了supports()后经过这个方法
	返回一个ModelAndView,名字为视图名和必要的model数据,如果request没被正确处理,返回null */
	@Nullable
	ModelAndView handle(HttpServletRequest request,  
                        HttpServletResponse response, 
                        Object handler) throws Exception;// 要使用的handler,必须依据经过了supports()

	/** 如果没有支持的handler类,返回-1
	 * Same contract as for HttpServlet's {@code getLastModified} method.
	 * @return the lastModified value for the given handler
	 * @see HttpServlet#getLastModified
	 * @see LastModified#getLastModified
	 */
	long getLastModified(HttpServletRequest request, Object handler);
}

调用supports()分析适配器可用后,我们就调用它的handle()方法

2 ha实现类

  • RequestMappingHandlerAdaptor, // @RequestMapping
  • HttpRequestHandlerAdaptor, // 实现HttpRequestHandler的,这里不考虑
  • SimpleControllerHandlerAdaptor // 实现Controller接口的
//SimpleControllerHandlerAdaptor //继承了Controller接口的自定义controller就是实现了该方法
public ModelAndView handle(HttpServletRequest request, 
                           HttpServletResponse response, 
                           Object handler){
   
   

    return ((Controller) handler).handleRequest(request, response);
}

//AbstractHandlerMethodAdapter  注解方式的
public final ModelAndView handle(HttpServletRequest request, 
                                 HttpServletResponse response, 
                                 Object handler){
   
   

    return handleInternal(request, response, (HandlerMethod) handler);
}

3 ha.handleInternal()

RequestMappingHandlerAdapter.handleInternal()

// 处理@RequestMapping注解的适配器
public class RequestMappingHandlerAdapter 
    extends AbstractHandlerMethodAdapter
    implements BeanFactoryAware, InitializingBean {
   
   

    @Override
    protected ModelAndView handleInternal(HttpServletRequest request,
                                          HttpServletResponse response, 
                                          HandlerMethod handlerMethod) {
   
   

        ModelAndView mav;
        checkRequest(request);

        // Execute invokeHandlerMethod in synchronized block if required.
        if (this.synchronizeOnSession) {
   
   
            HttpSession session = request.getSession(false);
            if (session != null) {
   
   
                Object mutex = WebUtils.getSessionMutex(session);
                synchronized (mutex) {
   
   
                    mav = invokeHandlerMethod(request, response, handlerMethod);
                }
            }else {
   
    // 没有session
                // No HttpSession available -> no mutex necessary
                mav = invokeHandlerMethod(request, response, handlerMethod);
            }
        } else {
   
   
            // No synchronization on session demanded at all...
            // 执行目标方法,返回modelAndView
            mav = invokeHandlerMethod(request, response, handlerMethod);
        }

        if (!response.containsHeader(HEADER_CACHE_CONTROL)) {
   
   
            if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
   
   
                applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
            }
            else {
   
   
                prepareResponse(response);
            }
        }

        return mav;
    }

4 ha.invokeHandlerMethod()流程

RequestMappingHandlerAdapter.invokeHandlerMethod

  • 包装ServletInvocableHandlerMethod
  • invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);给目标方法里设置参数解析器
  • invocableMethod.setHandlerMethodReturnValueHandlers给目标方法里设置返回值解析器
  • invocableMethod.invokeAndHandle(webRequest, mavContainer);
  • getModelAndView 获得视图
// RequestMappingHandlerAdapter
@Nullable
protected ModelAndView invokeHandlerMethod(HttpServletRequest request,
                                           HttpServletResponse response, 
                                           HandlerMethod handlerMethod) throws Exception {
   
   

    ServletWebRequest webRequest = new ServletWebRequest(request, response);
    try {
   
   
        WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod);
        ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory);

        ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod);
        
        // 参数解析器,拿到全部
        if (this.argumentResolvers != null) {
   
   
            // 给目标方法里设置参数解析器
            invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
        }
        
        // 给目标方法里设置返回值解析器,设置全部
        if (this.returnValueHandlers != null) {
   
   
            invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
        }
        
        invocableMethod.setDataBinderFactory(binderFactory);
        invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);

        // 创建ModelAndViewContainer,包含了请求中的视图和模型
        ModelAndViewContainer mavContainer = new ModelAndViewContainer();
        mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
        modelFactory.initModel(webRequest, mavContainer, invocableMethod);
        mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);

        AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
        asyncWebRequest.setTimeout(this.asyncRequestTimeout);

        WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
        asyncManager.setTaskExecutor(this.taskExecutor);
        asyncManager.setAsyncWebRequest(asyncWebRequest);
        asyncManager.registerCallableInterceptors(this.callableInterceptors);
        asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);

        if (asyncManager.hasConcurrentResult()) {
   
   
            Object result = asyncManager.getConcurrentResult();
            mavContainer = (ModelAndViewContainer) asyncManager.getConcurrentResultContext()[0];
            asyncManager.clearConcurrentResult();
            LogFormatUtils.traceDebug(logger, traceOn -> {
   
   
                String formatted = LogFormatUtils.formatValue(result, !traceOn);
                return "Resume with async result [" + formatted + "]";
            });
            invocableMethod = invocableMethod.wrapConcurrentResult(result);
        }

        
        // 去处理结果值【包括视图名、转发的map】,放入mavContainer
        invocableMethod.invokeAndHandle(webRequest, mavContainer);
        
        
        if (asyncManager.isConcurrentHandlingStarted()) {
   
   
            return null;
        }
        // 获得视图
        return getModelAndView(mavContainer, modelFactory, webRequest);
    }
    finally {
   
   
        webRequest.requestCompleted();
    }
}
4.1 createInvocableHandlerMethod
4.2 iM.setHandlerMethodArgumentResolvers(this.argumentResolvers);

给目标方法里设置参数解析器invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);

invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);

有很多参数解析器,RequestParamMapMethodArgumentResolver

参数解析器接口:
/** 解析方法的参数 */
public interface 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值