该系列文档是本人在学习 Spring MVC 的源码过程当中总结下来的,可能对读者不太友好,请结合个人源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读html
Spring 版本:5.2.4.RELEASEjava
该系列其余文档请查看:《精尽 Spring MVC 源码分析 - 文章导读》react
HandlerAdapter 组件,处理器的适配器。由于处理器 handler
的类型是 Object 类型,须要有一个调用者来实现 handler
是怎么被执行。Spring 中的处理器的实现多变,好比用户的处理器能够实现 Controller 接口或者 HttpRequestHandler 接口,也能够用 @RequestMapping
注解将方法做为一个处理器等,这就致使 Spring MVC 没法直接执行这个处理器。因此这里须要一个处理器适配器,由它去执行处理器git
因为 HandlerMapping 组件涉及到的内容较多,考虑到内容的排版,因此将这部份内容拆分红了五个模块,依次进行分析:github
先来回顾一下在 DispatcherServlet
中处理请求的过程当中哪里使用到 HandlerMapping 组件,能够回到《一个请求的旅行过程》中的 DispatcherServlet
的 doDispatch
方法中看看,以下:web
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; ModelAndView mv = null; // ... 省略相关代码 // <3> 得到请求对应的 HandlerExecutionChain 对象(HandlerMethod 和 HandlerInterceptor 拦截器们) mappedHandler = getHandler(processedRequest); // ... 省略相关代码 // <4> 得到当前 handler 对应的 HandlerAdapter 对象 HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler()); // ... 省略相关代码 // <6> 真正的调用 handler 方法,也就是执行对应的方法,并返回视图 mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); // ... 省略相关代码 } protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { if (this.handlerAdapters != null) { for (HandlerAdapter adapter : this.handlerAdapters) { if (adapter.supports(handler)) { return adapter; } } } throw new ServletException("No adapter for handler [..."); }
经过遍历 HandlerAdapter 组件们,判断是否支持处理该 handler
处理器,支持则返回该 HandlerAdapter 组件。注意,这里是经过一个一个的 HandlerAdapter 组件去判断是否支持该处理器,若是支持则直接返回这个 HandlerAdapter 组件,不会继续下去,因此获取处理器对应 HandlerAdapter 组件是有必定的前后顺序的,默认是HttpRequestHandlerAdapter -> SimpleControllerHandlerAdapter -> RequestMappingHandlerAdapterspring
本文涉及到的内容适中,能够先查看个人总结数组
org.springframework.web.servlet.HandlerAdapter
接口,处理器的适配器,去执行处理器,代码以下:缓存
public interface HandlerAdapter { /** * 是否支持该处理器 */ boolean supports(Object handler); /** * 执行处理器,返回 ModelAndView 结果 */ @Nullable ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception; /** * 返回请求的最新更新时间,若是不支持该操做,则返回 -1 便可 */ long getLastModified(HttpServletRequest request, Object handler); }
HandlerAdapter 接口的体系结构以下:session
没有特别多😈 内心有点点欣慰,其中 RequestMappingHandlerAdapter
就是基于@RequestMapping
等注解的 HandlerMethod 的 HandlerMethodAdapter 实现类,名字都差很少
在 DispatcherServlet
的 initHandlerAdapters(ApplicationContext context)
方法,会在 onRefresh
方法被调用,初始化 HandlerAdapter 组件,方法以下:
private void initHandlerAdapters(ApplicationContext context) { this.handlerAdapters = null; 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<>(matchingBeans.values()); // We keep HandlerAdapters in sorted order. AnnotationAwareOrderComparator.sort(this.handlerAdapters); } } 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. } } // Ensure we have at least some HandlerAdapters, by registering // default HandlerAdapters if no other adapters are found. /** * 若是未得到到,则得到默认配置的 HandlerAdapter 类 * {@link org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter} * {@link org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter} * {@link org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter} */ if (this.handlerAdapters == null) { this.handlerAdapters = getDefaultStrategies(context, HandlerAdapter.class); if (logger.isTraceEnabled()) { logger.trace("No HandlerAdapters declared for servlet '" + getServletName() + "': using default strategies from DispatcherServlet.properties"); } } }
若是“开启”探测功能,则扫描已注册的 HandlerAdapter 的 Bean 们,添加到 handlerAdapters
中,默认开启,这里会进行排序,能够经过实现 Order 接口设置排序值
若是“关闭”探测功能,则得到 Bean 名称为 "handlerAdapter" 对应的 Bean ,将其添加至 handlerAdapters
若是未得到到,则得到默认配置的 HandlerAdapter 类,调用 getDefaultStrategies(ApplicationContext context, Class<T> strategyInterface)
方法,就是从 DispatcherServlet.properties
文件中读取 HandlerAdapter 的默认实现类,以下:
org.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\ org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\ org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
能够看到对应的是 HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter、RequestMappingHandlerAdapter 三个实现类,接下来就一个一个分析
org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter
,实现 HandlerAdapter 接口,基于 HttpRequestHandler
接口的 HandlerAdapter 实现类,代码以下:
public class HttpRequestHandlerAdapter implements HandlerAdapter { @Override public boolean supports(Object handler) { // 判断是 HttpRequestHandler 类型 return (handler instanceof HttpRequestHandler); } @Override @Nullable public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // HttpRequestHandler 类型的调用 ((HttpRequestHandler) handler).handleRequest(request, response); return null; } @Override public long getLastModified(HttpServletRequest request, Object handler) { // 处理器实现了 LastModified 接口的状况下 if (handler instanceof LastModified) { return ((LastModified) handler).getLastModified(request); } return -1L; } } // org.springframework.web.HttpRequestHandler.java @FunctionalInterface public interface HttpRequestHandler { /** * 处理请求 */ void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException; }
逻辑比较简单,若是这个处理器实现了 HttpRequestHandler
接口,则使用 HttpRequestHandlerAdapter
调用该处理器的 handleRequest(HttpServletRequest request, HttpServletResponse response)
方法去处理器请求,返回 null
这种处理器如何配置呢?
能够回到《HandlerMapping 组件(四)之 AbstractUrlHandlerMapping》的 SimpleUrlHandlerMapping 或者 BeanNameUrlHandlerMapping 小节中的使用示例看看
org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter
,实现 HandlerAdapter 接口,基于 Controller
接口的 HandlerAdapter 实现类,代码以下:
public class SimpleControllerHandlerAdapter implements HandlerAdapter { @Override public boolean supports(Object handler) { // <1> 判断是 Controller 类型 return (handler instanceof Controller); } @Override @Nullable public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // <2> Controller 类型的调用 return ((Controller) handler).handleRequest(request, response); } @Override public long getLastModified(HttpServletRequest request, Object handler) { // 处理器实现了 LastModified 接口的状况下 if (handler instanceof LastModified) { return ((LastModified) handler).getLastModified(request); } return -1L; } } @FunctionalInterface public interface Controller { /** * 处理请求 */ @Nullable ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception; }
逻辑比较简单,和 HttpRequestHandlerAdapter 差很少,若是这个处理器实现了 Controoler
接口,则使用 HttpRequestHandlerAdapter
调用该处理器的 handleRequest(HttpServletRequest request, HttpServletResponse response)
方法去处理器请求,直接返回处理器执行后返回 ModelAndView
这种处理器如何配置和 HttpRequestHandlerAdapter 相同,见上文描述
SimpleServletHandlerAdapter 实现类就不讲述了,由于默认的 HandlerAdapter 实现类中没有它
逻辑实现和 SimpleControllerHandlerAdapter 差很少,区别在于它判断是否为
javax.servlet.Servlet
对象,是的话则调用其service
方法,返回该方法执行后返回的ModelAndView
对象
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter
,实现 HandlerAdapter、Ordered 接口,继承 WebContentGenerator 抽象类,基于 HandlerMethod 的 HandlerMethodAdapter 抽象类
public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator implements HandlerAdapter, Ordered { /** 最低优先级 */ private int order = Ordered.LOWEST_PRECEDENCE; public AbstractHandlerMethodAdapter() { // no restriction of HTTP methods by default // 调用 WebContentGenerator 类的构造方法 // 参数 restrictDefaultSupportedMethods 参数为 false ,表示不须要严格校验 HttpMethod super(false); } }
实现 supports(Object handler)
方法,判断是否支持该处理器,代码以下:
@Override public final boolean supports(Object handler) { return (handler instanceof HandlerMethod && supportsInternal((HandlerMethod) handler)); } protected abstract boolean supportsInternal(HandlerMethod handlerMethod);
@RequestMapping
等注解方法所生成对应 HandlerMethod 对象supportsInternal(HandlerMethod handlerMethod)
判断是否支持, 交由子类去实现,详情见下文实现 handle(HttpServletRequest request, HttpServletResponse response, Object handler)
方法,用于处理请求,执行该处理器,代码以下:
@Override @Nullable public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return handleInternal(request, response, (HandlerMethod) handler); } @Nullable protected abstract ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception;
handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod)
抽象方法,交由子类去实现,详情见下文实现 getLastModified(HttpServletRequest request, Object handler)
方法,得到最后更新时间,代码以下
@Override public final long getLastModified(HttpServletRequest request, Object handler) { return getLastModifiedInternal(request, (HandlerMethod) handler); } protected abstract long getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod);
getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod)
抽象方法,交由子类去实现,详情见下文org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter
,实现 BeanFactoryAware、InitializingBean 接口,继承 AbstractHandlerMethodAdapter 抽象类,基于 @RequestMapping
注解的 HandlerMethod 处理器的 HandlerMethodAdapter 实现类
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter implements BeanFactoryAware, InitializingBean { /** * MethodFilter that matches {@link InitBinder @InitBinder} methods. */ public static final MethodFilter INIT_BINDER_METHODS = method -> AnnotatedElementUtils.hasAnnotation(method, InitBinder.class); /** * MethodFilter that matches {@link ModelAttribute @ModelAttribute} methods. */ public static final MethodFilter MODEL_ATTRIBUTE_METHODS = method -> (!AnnotatedElementUtils.hasAnnotation(method, RequestMapping.class) && AnnotatedElementUtils.hasAnnotation(method, ModelAttribute.class)); @Nullable private List<HandlerMethodArgumentResolver> customArgumentResolvers; @Nullable private HandlerMethodArgumentResolverComposite argumentResolvers; @Nullable private HandlerMethodArgumentResolverComposite initBinderArgumentResolvers; @Nullable private List<HandlerMethodReturnValueHandler> customReturnValueHandlers; @Nullable private HandlerMethodReturnValueHandlerComposite returnValueHandlers; @Nullable private List<ModelAndViewResolver> modelAndViewResolvers; private ContentNegotiationManager contentNegotiationManager = new ContentNegotiationManager(); private List<HttpMessageConverter<?>> messageConverters; private List<Object> requestResponseBodyAdvice = new ArrayList<>(); @Nullable private WebBindingInitializer webBindingInitializer; private AsyncTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor("MvcAsync"); @Nullable private Long asyncRequestTimeout; private CallableProcessingInterceptor[] callableInterceptors = new CallableProcessingInterceptor[0]; private DeferredResultProcessingInterceptor[] deferredResultInterceptors = new DeferredResultProcessingInterceptor[0]; private ReactiveAdapterRegistry reactiveAdapterRegistry = ReactiveAdapterRegistry.getSharedInstance(); private boolean ignoreDefaultModelOnRedirect = false; private int cacheSecondsForSessionAttributeHandlers = 0; /** * 是否对相同 Session 加锁 */ private boolean synchronizeOnSession = false; private SessionAttributeStore sessionAttributeStore = new DefaultSessionAttributeStore(); private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer(); @Nullable private ConfigurableBeanFactory beanFactory; // ========== 缓存 ========== private final Map<Class<?>, SessionAttributesHandler> sessionAttributesHandlerCache = new ConcurrentHashMap<>(64); private final Map<Class<?>, Set<Method>> initBinderCache = new ConcurrentHashMap<>(64); private final Map<ControllerAdviceBean, Set<Method>> initBinderAdviceCache = new LinkedHashMap<>(); private final Map<Class<?>, Set<Method>> modelAttributeCache = new ConcurrentHashMap<>(64); private final Map<ControllerAdviceBean, Set<Method>> modelAttributeAdviceCache = new LinkedHashMap<>(); // ... 省略 getter、setter 方法 public RequestMappingHandlerAdapter() { // 初始化 messageConverters StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter(); stringHttpMessageConverter.setWriteAcceptCharset(false); // see SPR-7316 this.messageConverters = new ArrayList<>(4); this.messageConverters.add(new ByteArrayHttpMessageConverter()); this.messageConverters.add(stringHttpMessageConverter); try { this.messageConverters.add(new SourceHttpMessageConverter<>()); } catch (Error err) { // Ignore when no TransformerFactory implementation is available } this.messageConverters.add(new AllEncompassingFormHttpMessageConverter()); } }
有许多的属性,不着急理解,先列几个主要的属性对象:
HandlerMethodArgumentResolverComposite argumentResolvers
:参数处理器组合对象HandlerMethodReturnValueHandlerComposite returnValueHandlers
:返回值处理器组合对象List<HttpMessageConverter<?>> messageConverters
:HTTP 消息转换器集合对象List<Object> requestResponseBodyAdvice
: RequestResponseAdvice 集合对象在构造方法中默认会添加了四个 HttpMessageConverter 对象,固然,默认还会添加其余的,例如 MappingJackson2HttpMessageConverter 为 JSON 消息格式的转换器
由于 RequestMappingHandlerAdapter 实现了 InitializingBean 接口,在 Sping 初始化该 Bean 的时候,会调用该方法,完成一些初始化工做,方法以下:
@Override public void afterPropertiesSet() { // Do this first, it may add ResponseBody advice beans // <1> 初始化 ControllerAdvice 相关 initControllerAdviceCache(); // <2> 初始化 argumentResolvers 属性 if (this.argumentResolvers == null) { List<HandlerMethodArgumentResolver> resolvers = getDefaultArgumentResolvers(); this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers); } // <3> 初始化 initBinderArgumentResolvers 属性 if (this.initBinderArgumentResolvers == null) { List<HandlerMethodArgumentResolver> resolvers = getDefaultInitBinderArgumentResolvers(); this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers); } // <4> 初始化 returnValueHandlers 属性 if (this.returnValueHandlers == null) { List<HandlerMethodReturnValueHandler> handlers = getDefaultReturnValueHandlers(); this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers); } }
调用 initControllerAdviceCache()
方法,初始化 ControllerAdvice 相关,详情见下文
初始化 argumentResolvers
属性,调用 getDefaultArgumentResolvers()
方法,得到默认的 HandlerMethodArgumentResolver 数组,详情见下文
初始化 initBinderArgumentResolvers
属性,调用 getDefaultInitBinderArgumentResolvers()
方法,得到默认的 HandlerMethodArgumentResolver 数组,详情见下文
初始化 returnValueHandlers
属性,调用 getDefaultReturnValueHandlers()
方法,得到默认的 HandlerMethodReturnValueHandler 数组,详情见下文
initControllerAdviceCache()
方法,初始化 ControllerAdvice 相关,方法以下:
private void initControllerAdviceCache() { if (getApplicationContext() == null) { return; } // <1> 扫描 @ControllerAdvice 注解的 Bean 们,生成对应的 ControllerAdviceBean 对象,并将进行排序 List<ControllerAdviceBean> adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext()); AnnotationAwareOrderComparator.sort(adviceBeans); List<Object> requestResponseBodyAdviceBeans = new ArrayList<>(); // <2> 遍历 ControllerAdviceBean 数组 for (ControllerAdviceBean adviceBean : adviceBeans) { Class<?> beanType = adviceBean.getBeanType(); if (beanType == null) { throw new IllegalStateException("Unresolvable type for ControllerAdviceBean: " + adviceBean); } // <2.1> 扫描有 `@ModelAttribute` ,无 `@RequestMapping` 注解的方法,添加到 `modelAttributeAdviceCache` 属性中 // 该类方法用于在执行方法前修改 Model 对象 Set<Method> attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS); if (!attrMethods.isEmpty()) { this.modelAttributeAdviceCache.put(adviceBean, attrMethods); } // <2.2> 扫描有 `@InitBinder` 注解的方法,添加到 `initBinderAdviceCache` 属性中 // 该类方法用于在执行方法前初始化数据绑定器 Set<Method> binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS); if (!binderMethods.isEmpty()) { this.initBinderAdviceCache.put(adviceBean, binderMethods); } // <2.3> 若是是 RequestBodyAdvice 或 ResponseBodyAdvice 的子类,添加到 requestResponseBodyAdviceBeans 中 if (RequestBodyAdvice.class.isAssignableFrom(beanType) || ResponseBodyAdvice.class.isAssignableFrom(beanType)) { requestResponseBodyAdviceBeans.add(adviceBean); } } // <2.3> 将 requestResponseBodyAdviceBeans 添加到 this.requestResponseBodyAdvice 属性种 if (!requestResponseBodyAdviceBeans.isEmpty()) { this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans); } // 打印日志 if (logger.isDebugEnabled()) { int modelSize = this.modelAttributeAdviceCache.size(); int binderSize = this.initBinderAdviceCache.size(); int reqCount = getBodyAdviceCount(RequestBodyAdvice.class); int resCount = getBodyAdviceCount(ResponseBodyAdvice.class); if (modelSize == 0 && binderSize == 0 && reqCount == 0 && resCount == 0) { logger.debug("ControllerAdvice beans: none"); } else { logger.debug("ControllerAdvice beans: " + modelSize + " @ModelAttribute, " + binderSize + " @InitBinder, " + reqCount + " RequestBodyAdvice, " + resCount + " ResponseBodyAdvice"); } } }
从 Spring 上下文扫描 @ControllerAdvice
注解的 Bean 们,生成对应的 ControllerAdviceBean
对象,并将进行排序,方法以下:
public static List<ControllerAdviceBean> findAnnotatedBeans(ApplicationContext context) { return Arrays.stream(BeanFactoryUtils.beanNamesForTypeIncludingAncestors(context, Object.class)) // 排除代理目标类,AOP 相关 .filter(name -> !ScopedProxyUtils.isScopedTarget(name)) // 包含 @ControllerAdvice 注解 .filter(name -> context.findAnnotationOnBean(name, ControllerAdvice.class) != null) // 生成对应的 ControllerAdviceBean 对象 .map(name -> new ControllerAdviceBean(name, context)) .collect(Collectors.toList()); }
@ControllerAdvice
注解:用于 Controller 类的加强类,其中可定义多种加强的方法,例如 @ExceptionHandler
注解的方法用于处理器 Controller 抛出的异常
遍历 1
中生成 ControllerAdviceBean 数组
@ModelAttribute
,无 @RequestMapping
注解的方法,添加到 modelAttributeAdviceCache
属性中,该类方法用于在执行方法前修改 Model 对象@InitBinder
注解的方法,添加到 initBinderAdviceCache
属性中,该类方法用于在执行方法前初始化数据绑定器将 2.3
的 requestResponseBodyAdviceBeans 保存至 requestResponseBodyAdvice
属性中
getDefaultArgumentResolvers()
,初始化默认的参数解析器,方法以下:
private List<HandlerMethodArgumentResolver> getDefaultArgumentResolvers() { List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>(); // Annotation-based argument resolution resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false)); resolvers.add(new RequestParamMapMethodArgumentResolver()); resolvers.add(new PathVariableMethodArgumentResolver()); resolvers.add(new PathVariableMapMethodArgumentResolver()); resolvers.add(new MatrixVariableMethodArgumentResolver()); resolvers.add(new MatrixVariableMapMethodArgumentResolver()); resolvers.add(new ServletModelAttributeMethodProcessor(false)); resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice)); resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice)); resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory())); resolvers.add(new RequestHeaderMapMethodArgumentResolver()); resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory())); resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory())); resolvers.add(new SessionAttributeMethodArgumentResolver()); resolvers.add(new RequestAttributeMethodArgumentResolver()); // Type-based argument resolution resolvers.add(new ServletRequestMethodArgumentResolver()); resolvers.add(new ServletResponseMethodArgumentResolver()); resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice)); resolvers.add(new RedirectAttributesMethodArgumentResolver()); resolvers.add(new ModelMethodProcessor()); resolvers.add(new MapMethodProcessor()); resolvers.add(new ErrorsMethodArgumentResolver()); resolvers.add(new SessionStatusMethodArgumentResolver()); resolvers.add(new UriComponentsBuilderMethodArgumentResolver()); // Custom arguments if (getCustomArgumentResolvers() != null) { resolvers.addAll(getCustomArgumentResolvers()); } // Catch-all resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true)); resolvers.add(new ServletModelAttributeMethodProcessor(true)); return resolvers; }
getDefaultInitBinderArgumentResolvers()
,初始化默认的参数绑定器,方法以下:
private List<HandlerMethodArgumentResolver> getDefaultInitBinderArgumentResolvers() { List<HandlerMethodArgumentResolver> resolvers = new ArrayList<>(); // Annotation-based argument resolution resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false)); resolvers.add(new RequestParamMapMethodArgumentResolver()); resolvers.add(new PathVariableMethodArgumentResolver()); resolvers.add(new PathVariableMapMethodArgumentResolver()); resolvers.add(new MatrixVariableMethodArgumentResolver()); resolvers.add(new MatrixVariableMapMethodArgumentResolver()); resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory())); resolvers.add(new SessionAttributeMethodArgumentResolver()); resolvers.add(new RequestAttributeMethodArgumentResolver()); // Type-based argument resolution resolvers.add(new ServletRequestMethodArgumentResolver()); resolvers.add(new ServletResponseMethodArgumentResolver()); // Custom arguments if (getCustomArgumentResolvers() != null) { resolvers.addAll(getCustomArgumentResolvers()); } // Catch-all resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), true)); return resolvers; }
getDefaultReturnValueHandlers()
,初始化默认的返回值处理器,方法以下:
private List<HandlerMethodReturnValueHandler> getDefaultReturnValueHandlers() { List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>(); // Single-purpose return value types handlers.add(new ModelAndViewMethodReturnValueHandler()); handlers.add(new ModelMethodProcessor()); handlers.add(new ViewMethodReturnValueHandler()); handlers.add(new ResponseBodyEmitterReturnValueHandler(getMessageConverters(), this.reactiveAdapterRegistry, this.taskExecutor, this.contentNegotiationManager)); handlers.add(new StreamingResponseBodyReturnValueHandler()); handlers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.contentNegotiationManager, this.requestResponseBodyAdvice)); handlers.add(new HttpHeadersReturnValueHandler()); handlers.add(new CallableMethodReturnValueHandler()); handlers.add(new DeferredResultMethodReturnValueHandler()); handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory)); // Annotation-based return value types handlers.add(new ModelAttributeMethodProcessor(false)); handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.contentNegotiationManager, this.requestResponseBodyAdvice)); // Multi-purpose return value types handlers.add(new ViewNameMethodReturnValueHandler()); handlers.add(new MapMethodProcessor()); // Custom return value types if (getCustomReturnValueHandlers() != null) { handlers.addAll(getCustomReturnValueHandlers()); } // Catch-all if (!CollectionUtils.isEmpty(getModelAndViewResolvers())) { handlers.add(new ModelAndViewResolverMethodReturnValueHandler(getModelAndViewResolvers())); } else { handlers.add(new ModelAttributeMethodProcessor(true)); } return handlers; }
实现 supportsInternal()
接口,方法以下:
@Override protected boolean supportsInternal(HandlerMethod handlerMethod) { return true; }
直接返回 true
,也就是说处理器只要是 HandlerMethod 对象就能够
@Override protected long getLastModifiedInternal(HttpServletRequest request, HandlerMethod handlerMethod) { return -1; }
直接返回 -1
实现 handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod)
方法,处理请求,执行处理器,方法以下:
@Override protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { ModelAndView mav; // <1> 校验请求(HttpMethod 和 Session 的校验) checkRequest(request); // <2> 调用 HandlerMethod 方法 // Execute invokeHandlerMethod in synchronized block if required. if (this.synchronizeOnSession) { // 同步相同 Session 的逻辑,默认状况false HttpSession session = request.getSession(false); if (session != null) { // 获取Session的锁对象 Object mutex = WebUtils.getSessionMutex(session); synchronized (mutex) { mav = invokeHandlerMethod(request, response, handlerMethod); } } else { // No HttpSession available -> no mutex necessary mav = invokeHandlerMethod(request, response, handlerMethod); } } else { // No synchronization on session demanded at all... mav = invokeHandlerMethod(request, response, handlerMethod); } if (!response.containsHeader(HEADER_CACHE_CONTROL)) { // 响应不包含'Cache-Control'头 if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) { applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers); } else { prepareResponse(response); } } return mav; }
调用父类 WebContentGenerator 的 checkRequest(ttpServletRequest request)
方法,校验请求(HttpMethod 和 Session)是否合法
protected final void checkRequest(HttpServletRequest request) throws ServletException { // Check whether we should support the request method. String method = request.getMethod(); if (this.supportedMethods != null && !this.supportedMethods.contains(method)) { throw new HttpRequestMethodNotSupportedException(method, this.supportedMethods); } // Check whether a session is required. if (this.requireSession && request.getSession(false) == null) { throw new HttpSessionRequiredException("Pre-existing session required but none found"); } }
在 AbstractHandlerMethodAdapter 的构造方法中,传入 restrictDefaultSupportedMethods
参数为 false
,表示不须要严格校验 HttpMethod,这里正常状况都会校验经过
调用 invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod)
方法,执行 HandlerMethod 处理器
这里会判断 synchronizeOnSession
属性,控制是否同步相同 Session 的逻辑,其中 WebUtils#getSessionMutex(session)
方法,得到用来锁的对象,方法以下:
public static Object getSessionMutex(HttpSession session) { Assert.notNull(session, "Session must not be null"); Object mutex = session.getAttribute(SESSION_MUTEX_ATTRIBUTE); if (mutex == null) { mutex = session; } return mutex; }
固然,由于锁是经过 synchronized
是 JVM 进程级,因此在分布式环境下,没法达到同步相同 Session 的功能
默认状况下,synchronizeOnSession
为 false
invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod)
方法,执行 HandlerMethod 处理器,方法以下:
@Nullable protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { // <1> 建立 ServletWebRequest 对象 ServletWebRequest webRequest = new ServletWebRequest(request, response); try { // <2> 建立 WebDataBinderFactory 对象 WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod); // <3> 建立 ModelFactory 对象 ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory); // <4> 建立 ServletInvocableHandlerMethod 对象,并设置其相关属性 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); // <5> 建立 ModelAndViewContainer 对象,并初始其相关属性 ModelAndViewContainer mavContainer = new ModelAndViewContainer(); mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request)); modelFactory.initModel(webRequest, mavContainer, invocableMethod); mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect); // <6> 建立 AsyncWebRequest 异步请求对象 AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response); asyncWebRequest.setTimeout(this.asyncRequestTimeout); // <7> 建立 WebAsyncManager 异步请求管理器对象 WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); asyncManager.setTaskExecutor(this.taskExecutor); asyncManager.setAsyncWebRequest(asyncWebRequest); asyncManager.registerCallableInterceptors(this.callableInterceptors); asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors); // <8> 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); } // <9> 执行调用 invocableMethod.invokeAndHandle(webRequest, mavContainer); // <10> if (asyncManager.isConcurrentHandlingStarted()) { return null; } // <11> 得到 ModelAndView 对象 return getModelAndView(mavContainer, modelFactory, webRequest); } finally { // <12> 标记请求完成 webRequest.requestCompleted(); } }
由于,Spring MVC 提供了大量的特性,因此 HandlerAdapter 又涉及许多组件。😈 咱们主要先梳理好主流程,因此涉及的组件,仍是先不详细解析。咱们的目的是,看到怎么调用 HandlerMethod 方法的,即调用 Controller 的 @RequestMapping
注解的方法。
建立 ServletWebRequest 对象,包含了 request
请求和 response
响应
调用 getDataBinderFactory(HandlerMethod handlerMethod)
方法,建立 WebDataBinderFactory 对象,有关于数据绑定,暂时忽略
调用 getModelFactory(HandlerMethod handlerMethod, WebDataBinderFactory binderFactory)
方法,建立 ModelFactory 对象,有关于往 Model 对象设置数据,暂时忽略
【核心】调用 createInvocableHandlerMethod(HandlerMethod handlerMethod)
方法,建立 ServletInvocableHandlerMethod 对象,而后设置其属性。本文会对 ServletInvocableHandlerMethod 作简单的解析。 详细的解析在《HandlerAdapter 组件(二)之 ServletInvocableHandlerMethod》中
建立 ModelAndViewContainer 对象,并初始其相关属性
建立 AsyncWebRequest 异步请求对象,暂时忽略
建立 WebAsyncManager 异步请求管理器对象,暂时忽略
异步处理,并发结果相关,暂时忽略
【核心】调用 ServletInvocableHandlerMethod 的invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs)
方法,执行处理器,方法以下:
// ServletInvocableHandlerMethod.java public void invokeAndHandle(ServletWebRequest webRequest, ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { // <1> 执行调用 Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs); // <2> 设置响应状态码 setResponseStatus(webRequest); // <3> 设置 ModelAndViewContainer 为请求已处理,返回,和 @ResponseStatus 注解相关 if (returnValue == null) { if (isRequestNotModified(webRequest) || getResponseStatus() != null || mavContainer.isRequestHandled()) { disableContentCachingIfNecessary(webRequest); mavContainer.setRequestHandled(true); return; } } else if (StringUtils.hasText(getResponseStatusReason())) { mavContainer.setRequestHandled(true); return; } // <4> 设置 ModelAndViewContainer 为请求未处理 mavContainer.setRequestHandled(false); Assert.state(this.returnValueHandlers != null, "No return value handlers"); try { // <5> 处理返回值 this.returnValueHandlers.handleReturnValue(returnValue, getReturnValueType(returnValue), mavContainer, webRequest); } catch (Exception ex) { if (logger.isTraceEnabled()) { logger.trace(formatErrorForReturnValue(returnValue), ex); } throw ex; } } // InvocableHandlerMethod.java @Nullable public Object invokeForRequest(NativeWebRequest request, @Nullable ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception { // <y> 解析参数 Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs); if (logger.isTraceEnabled()) { logger.trace("Arguments: " + Arrays.toString(args)); } // 执行调用 return doInvoke(args); } // InvocableHandlerMethod.java @Nullable protected Object doInvoke(Object... args) throws Exception { // <z1> 设置方法为可访问 ReflectionUtils.makeAccessible(getBridgedMethod()); try { // <z2> 执行调用 return getBridgedMethod().invoke(getBean(), args); } catch (IllegalArgumentException ex) { assertTargetBean(getBridgedMethod(), getBean(), args); String text = (ex.getMessage() != null ? ex.getMessage() : "Illegal argument"); throw new IllegalStateException(formatInvokeError(text, args), ex); } catch (InvocationTargetException ex) { // Unwrap for HandlerExceptionResolvers ... Throwable targetException = ex.getTargetException(); if (targetException instanceof RuntimeException) { throw (RuntimeException) targetException; } else if (targetException instanceof Error) { throw (Error) targetException; } else if (targetException instanceof Exception) { throw (Exception) targetException; } else { throw new IllegalStateException(formatInvokeError("Invocation failure", args), targetException); } } }
能够大体过一下上面的执行逻辑,解析参数,经过反射执行方法,解析执行结果,详细解析在后续的《HandlerAdapter 组件(二)之 ServletInvocableHandlerMethod》文档中
异步处理,并发结果相关,暂时忽略
调用 getModelAndView(ModelAndViewContainer mavContainer, ModelFactory modelFactory, NativeWebRequest webRequest)
方法,得到 ModelAndView 对象,方法以下:
@Nullable private ModelAndView getModelAndView(ModelAndViewContainer mavContainer, ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception { modelFactory.updateModel(webRequest, mavContainer); // 状况一,若是 mavContainer 已处理,则返回“空”的 ModelAndView 对象。 if (mavContainer.isRequestHandled()) { return null; } // 状况二,若是 mavContainer 未处理,则基于 `mavContainer` 生成 ModelAndView 对象 ModelMap model = mavContainer.getModel(); // 建立 ModelAndView 对象,并设置相关属性 ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus()); if (!mavContainer.isViewReference()) { mav.setView((View) mavContainer.getView()); } if (model instanceof RedirectAttributes) { Map<String, ?> flashAttributes = ((RedirectAttributes) model).getFlashAttributes(); HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class); if (request != null) { RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes); } } return mav; }
mavContainer
已处理,则返回“空”的 ModelAndView 对象,@ResponseBody
注解的结果处理则直接返回 null
mavContainer
未处理,则基于 mavContainer
生成 ModelAndView 对象在后续的文档分析中会讲到,注意这里的 requestHandled
属性,到时候再回过头来理解😈
标记请求完成,暂时忽略
Spring MVC 经过 HandlerMapping
组件会为请求找到合适的 HandlerExecutionChain
处理器执行链,包含处理器(handler
)和拦截器们(interceptors
)。其中处理器的实现有多种,例如经过实现 Controller 接口、HttpRequestHandler 接口,或者使用 @RequestMapping
注解将方法做为一个处理器等。这就致使 Spring MVC 没法直接执行这个处理器,因此这里须要一个处理器适配器,由它去执行处理器。
HandlerAdapter
处理器适配器对应的也有多种,那种适配器支持处理这种类型的处理器,则由该适配器去执行,以下:
HttpRequestHandlerAdapter
:执行实现了 HttpRequestHandler 接口的处理器SimpleControllerHandlerAdapter
:执行实现了 Controller 接口的处理器SimpleServletHandlerAdapter
:执行实现了 Servlet 接口的处理器RequestMappingHandlerAdapter
:执行 HandlerMethod 类型的处理器,也就是经过 @RequestMapping
等注解标注的方法这里咱们重点看 RequestMappingHandlerAdapter 对象,由于这种方式是目前使用最广泛的,其余类型的 HandlerAdapter
处理器适配器作了解便可
本文讲述了 RequestMappingHandlerAdapter 处理执行器的整个流程,大体逻辑以下:
ServletInvocableHandlerMethod
(HandlerMethod
处理器的封装)对象去执行HandlerMethodArgumentResolver
对象进行参数解析HandlerMethodReturnValueHandler
对象对执行结果进行处理,设置到 response
响应中,生成对应的 ModelAndView 对象上面涉及到的三个组件分别在后续的文档中进行解析,先总体,后局部😈
参考文章:芋道源码《精尽 Spring MVC 源码分析》