写点什么

SpringMVC 源码分析 -HandlerAdapter(1)- 初始化和简单实现

用户头像
Brave
关注
发布于: 39 分钟前

一,HandlerAdapters 的初始化


DispatcherServlet-onRefresh 初始化 HandlerAdapters:

/** * This implementation calls {@link #initStrategies}. */@Overrideprotected void onRefresh(ApplicationContext context) {  initStrategies(context);}
/*** Initialize the strategy objects that this servlet uses.* <p>May be overridden in subclasses in order to initialize further strategy objects.*/protected void initStrategies(ApplicationContext context) { initMultipartResolver(context); initLocaleResolver(context); initThemeResolver(context); initHandlerMappings(context); // 初始化HandlerAdapters initHandlerAdapters(context); initHandlerExceptionResolvers(context); initRequestToViewNameTranslator(context); initViewResolvers(context); initFlashMapManager(context);}
复制代码


initHandlerAdapters-初始化 HandlerAdapters:

/*** Initialize the HandlerAdapters used by this class.* <p>If no HandlerAdapter beans are defined in the BeanFactory for this namespace,* we default to SimpleControllerHandlerAdapter.*/private void initHandlerAdapters(ApplicationContext context) {  this.handlerAdapters = null;
// 加载所有实现了HandlerAdapter接口的bean if (this.detectAllHandlerAdapters) { // Find all HandlerAdapters in the ApplicationContext, including ancestor contexts. Map<String, HandlerAdapter> matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false); if (!matchingBeans.isEmpty()) { this.handlerAdapters = new ArrayList<HandlerAdapter>(matchingBeans.values()); // We keep HandlerAdapters in sorted order. AnnotationAwareOrderComparator.sort(this.handlerAdapters); } } // 只加载bean name="handlerAdapter"的handlerAdapter else { try { HandlerAdapter ha = context.getBean(HANDLER_ADAPTER_BEAN_NAME, HandlerAdapter.class); this.handlerAdapters = Collections.singletonList(ha); } catch (NoSuchBeanDefinitionException ex) { // Ignore, we'll add a default HandlerAdapter later. } }
// 如果仍未找到,从DispatcherServlet.properties加载默认配置 // Ensure we have at least some HandlerAdapters, by registering // default HandlerAdapters if no other adapters are found. if (this.handlerAdapters == null) { this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class); if (logger.isDebugEnabled()) { logger.debug("No HandlerAdapters found in servlet '" + getServletName() + "': using default"); } }}
复制代码


detectAllHandlerAdapters 属性-是否发现所有 HandlerAdapters:

1)默认为 true,加载当前系统中所有实现了 HandlerAdapter 接口的 bean 到 handlerAdapters

2)此属性可通过 web.xml 中 DispatcherServlet 的初始参数进行修改


<init-param>  <param-name>detectAllHandlerAdapters</param-name>  <param-value>false</param-value></init-param>
复制代码

detectAllHandlerAdapters 值为 false 时,只加载 bean name="handlerAdapter"的 handlerAdapter


3)加载不到的情况下将按照 DispatcherServlet.properties 中所定义的

org.springframework.web.servlet.HandlerAdapter 中的内容来加载缺省的 handlerAdapter。


DispatcherServlet.properties 配置文件-org.springframework.web.servlet.HandlerAdapter

org.springframewoDispatcherServlet#doService 调用了 doDispatch 方法work.web.servlet.mvc.HttpRequestHandlerAdapter,\org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter
复制代码



二,请求处理流程


DispatcherServlet#doService 调用了 doDispatch 方法:

/** * 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);
// Determine handler for the current request. mappedHandler = getHandler(processedRequest); if (mappedHandler == null || mappedHandler.getHandler() == null) { noHandlerFound(processedRequest, response); return; }
// 获取与处理器相匹配的handlerAdapter // Determine handler adapter for the current request. HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// 如果是GET请求,如果内容没有变化的话,则直接返回 // 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; } }
// 调用执行器链中的拦截器,就是循环装配好的执行器链,执行 if (!mappedHandler.applyPreHandle(processedRequest, response)) { return; }
// 执行handle // Actually invoke the handler. mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) { return; } // 如果返回的ModelAndView不为null,并且没有设置view,设置默认的view。 applyDefaultViewName(processedRequest, mv); // 处理拦截器的postHandle。 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); } // 如果出现异常,返回异常页面。 // 如果没有异常,ModelAndView不为null,则正常渲染页面,调用拦截器的afterCompletion方法 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); } } }}
复制代码


在 doDispatch 的整个流程中,涉及 HandlerAdapter 的有以下两处:


1,获取与处理器相匹配的 handlerAdapter

HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
复制代码


getHandlerAdapter 的入参 mappedHandler:

HandlerExecutionChain mappedHandler = getHandler(processedRequest);// 根据request拿到HandlerExecutionChain对象// 包含一个处理器handler(如HandlerMethod对象),多个HandlerInterceptor拦截器对象
复制代码


getHandlerAdapter 源码:

/** * Return the HandlerAdapter for this handler object. * @param handler the handler object to find an adapter for * @throws ServletException if no HandlerAdapter can be found for the handler. This is a fatal error. */protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {  for (HandlerAdapter ha : this.handlerAdapters) {    if (logger.isTraceEnabled()) {      logger.trace("Testing handler adapter [" + ha + "]");    }    if (ha.supports(handler)) {      return ha;    }  }  throw new ServletException("No adapter for handler [" + handler +      "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");}
复制代码


遍历前面加载的 handlerAdapters(全部 handlerAdapter) 找出能够处理 handler 的 handlerAdapter:


备注:handlerAdapters 中包含多种实现了 handlerAdapters 接口的 handlerAdapter

supports 用于判断是否支持处理 handler,不同的 handlerAdapter 实现对不同 handler 的具体处理


2,执行 handle

ModelAndView mv = ha.handle(processedRequest, response, mappedHandler.getHandler());// handle也是handlerAdapter接口的一个方法,用于HandlerAdapter的具体处理
复制代码


到这里前置的一些内容完成了,我们可以开始分析 HandlerAdapter 了


三,HandlerAdapterHandlerAdapter 的作用

之前一步,HandlerMapping,通过request找到对应的处理器Handler接下来在handlerAdapters找到可以处理该handler类型的handlerAdapterHandlerAdapter使用Handler对用户请求进行具体处理,最终返回ModelAndView
HandlerAdapter即适配器模式,用于统一不同handler的接口调用
复制代码


HandlerAdapter 接口:

package org.springframework.web.servlet;
public interface HandlerAdapter {
// 是否支持传入的Handler boolean supports(Object handler); // 使用Handler处理请求 ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;
// 获取资源的LastModified值 long getLastModified(HttpServletRequest request, Object handler);
}
复制代码


四,HandlerAdapter 继承体系 HandlerAdapter 继承体系



从图中可以看出 HandlerAdapter 共有 5 类 Adapter:

  • HttpRequestHandlerAdapter,

SimpleServletHandlerAdapter,

SimpleControllerHandlerAdapter,

分别适配 HttpRequest,Servlet,Controller 类型的 Handler

处理固定类型的 Handler,内部调用固定方法进行处理;

  • AnnotationMethodHandlerAdapter 标记了 @Deprecated 已被弃用

用于适配注解类处理器,如经常使用的 @Controller 的这类处理器;

  • HttpRequestHandlerAdapter 的实现就非常复杂了

所处理的 Handler 可以是任意方法,参数的类型和数量也不确定


五,HttpRequestHandlerAdapter


适配处理器类型:

@Overridepublic boolean supports(Object handler) {    return (handler instanceof HttpRequestHandler);}
复制代码

处理实现了 HttpRequestHandler 接口的处理器,

这类处理器的作用是处理通过 SpringMVC 来访问的静态资源的请求


处理逻辑:

@Override@Nullablepublic ModelAndView handle(HttpServletRequest request,     HttpServletResponse response, Object handler)throws Exception {
((HttpRequestHandler) handler).handleRequest(request, response); return null;}
复制代码

直接调用 HttpRequestHandler#handleRequest,返回值为 null

通过改写 HttpServletResponse 实现前后端交互



六,SimpleServletHandlerAdapter


适配处理器类型:

@Overridepublic boolean supports(Object handler) {  return (handler instanceof Servlet);}
复制代码

适配实现了 Servle t 接口或 Servlet 的子类的处理器,

可以在 web.xml 中配置 Servlet,也可以用 SpringMVC 来配置 Servlet,

此 HandlerAdapter 较少使用,默认加载的 handlerAdapters 中没有这个;


处理逻辑:

@Overridepublic ModelAndView handle(HttpServletRequest request,       HttpServletResponse response, Object handler)throws Exception {
((Servlet) handler).service(request, response); return null;}
复制代码

调用 Servlet#service 对 handler 进行处理



七,SimpleControllerHandlerAdapter


适配处理器类型:

@Overridepublic boolean supports(Object handler) {    return (handler instanceof Controller);}
复制代码

适配实现了 Controller 接口或 Controller 接口子类的处理器,

如:自己写的 Controller 继承自 MultiActionController,由 SimpleControllerHandlerAdapter 适配


处理逻辑:

@Override@Nullablepublic ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)        throws Exception {            return ((Controller) handler).handleRequest(request, response);}
复制代码

直接调用 Controller#handleRequest(具体实现类的 handleRequest 方法)

适配 SimpleUrlHandlerMapping 和 BeanNameUrlHandlerMapping 的映射;


八,结尾


这一节,主要介绍了关于 HandlerAdapter 的整体流程


  • 从 DispatchServlet#onRefresh 初始化九大组件,找到 HandlerAdapter 的初始化加载策略,即注册

DispatcherServlet#doService 调用 doDispatch 方法,看到 HandlerAdapter 在整个请求处理的过程中的作用和角色;

  • HandlerAdapter 接口定义和 HandlerAdapter 继承体系;

  • 介绍了除 RequestMappingHandlerAdapter 外的另外三种 adapter 的实现;


下一节,介绍 HandlerAdapter 的核心 RequestMappingHandlerAdapter;

用户头像

Brave

关注

还未添加个人签名 2018.12.13 加入

还未添加个人简介

评论

发布
暂无评论
SpringMVC源码分析-HandlerAdapter(1)-初始化和简单实现