该系列文档是本人在学习 Spring MVC 的源码过程当中总结下来的,可能对读者不太友好,请结合个人源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读html
Spring 版本:5.2.4.RELEASEjava
该系列其余文档请查看:《精尽 Spring MVC 源码分析 - 文章导读》git
HandlerMapping 组件,请求的处理器匹配器,负责为请求找到合适的 HandlerExecutionChain
处理器执行链,包含处理器(handler
)和拦截器们(interceptors
)github
handler
处理器是 Object 类型,能够将其理解成 HandlerMethod 对象(例如咱们使用最多的 @RequestMapping
注解所标注的方法会解析成该对象),包含了方法的全部信息,经过该对象可以执行该方法web
HandlerInterceptor
拦截器对处理请求进行加强处理,可用于在执行方法前、成功执行方法后、处理完成后进行一些逻辑处理spring
因为 HandlerMapping 组件涉及到的内容比较多,考虑到内容的排版,因此将这部份内容拆分红了四个模块,依次进行分析:websocket
先来回顾一下HandlerMapping 接口体系的结构:app
在《HandlerMapping 组件(一)之 AbstractHandlerMapping》文档中已经分析了 HandlerMapping 组件的 AbstractHandlerMapping 抽象类基类socket
在《HandlerMapping 组件(三)之 AbstractHandlerMethodMapping》文档中也已经分析了图中红色框部分的 AbstractHandlerMethodMapping 系,基于 Method 进行匹配。例如,咱们所熟知的 @RequestMapping 等注解的方式。ide
那么本文就接着来分析图中黄色框部分的 AbstractUrlHandlerMapping 系,基于 URL 进行匹配。例如 《基于 XML 配置的 Spring MVC 简单的 HelloWorld 实例应用》 ,固然,目前这种方式已经基本不用了,被 @RequestMapping
等注解的方式所取代。不过,Spring MVC 内置的一些路径匹配,仍是使用这种方式。
由于 AbstractUrlHandlerMapping 在实际开发基本不会涉及到,因此本文选读,能够直接查看总结部分
一共有五个子类,分红两条线:
其中,WebSocketHandlerMapping 是 spring-websocket
项目中的类,本文会无视它
因此,本文按照 AbstractUrlHandlerMapping、SimpleUrlHandlerMapping、AbstractDetectingUrlHandlerMapping、BeanNameUrlHandlerMapping 顺序进行分析
先来回顾一下在 DispatcherServlet
中处理请求的过程当中经过 HandlerMapping 组件,获取到 HandlerExecutionChain 处理器执行链的方法,是经过AbstractHandlerMapping 的 getHandler 方法来获取的,以下:
@Override @Nullable public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { // <1> 得到处理器(HandlerMethod 或者 HandlerExecutionChain),该方法是抽象方法,由子类实现 Object handler = getHandlerInternal(request); // <2> 得到不到,则使用默认处理器 // <3> 仍是得到不到,则返回 null // <4> 若是找到的处理器是 String 类型,则从 Spring 容器中找到对应的 Bean 做为处理器 // <5> 建立 HandlerExecutionChain 对象(包含处理器和拦截器) // ... 省略相关代码 return executionChain; }
在 AbstractHandlerMapping 获取 HandlerExecutionChain 处理器执行链的方法中,须要先调用 getHandlerInternal(HttpServletRequest request)
抽象方法,获取请求对应的处理器,该方法由子类去实现,也就上图中黄色框和红色框两类子类,本文分析黄色框部份内容
org.springframework.web.servlet.handler.AbstractUrlHandlerMapping
,实现 MatchableHandlerMapping 接口,继承 AbstractHandlerMapping 抽象类,以 URL 做为 Handler 处理器 的 HandlerMapping 抽象类,提供 Handler 的获取、注册等等通用的骨架方法。
public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping implements MatchableHandlerMapping { /** * 根路径("/")的处理器 */ @Nullable private Object rootHandler; /** * 使用后置的 / 匹配 */ private boolean useTrailingSlashMatch = false; /** * 是否延迟加载处理器,默认关闭 */ private boolean lazyInitHandlers = false; /** * 路径和处理器的映射 * * KEY:路径 {@link #lookupHandler(String, HttpServletRequest)} */ private final Map<String, Object> handlerMap = new LinkedHashMap<>(); }
registerHandler(String[] urlPaths, String beanName)
方法,注册多个 URL 的处理器,方法以下:
protected void registerHandler(String[] urlPaths, String beanName) throws BeansException, IllegalStateException { Assert.notNull(urlPaths, "URL path array must not be null"); for (String urlPath : urlPaths) { registerHandler(urlPath, beanName); } } protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException { Assert.notNull(urlPath, "URL path must not be null"); Assert.notNull(handler, "Handler object must not be null"); Object resolvedHandler = handler; // Eagerly resolve handler if referencing singleton via name. // <1> 若是非延迟加载,而且 handler 为 String 类型,而且仍是单例,则去获取 String 对应的 Bean 对象 if (!this.lazyInitHandlers && handler instanceof String) { String handlerName = (String) handler; ApplicationContext applicationContext = obtainApplicationContext(); if (applicationContext.isSingleton(handlerName)) { resolvedHandler = applicationContext.getBean(handlerName); } } // <2> 得到 urlPath 对应的处理器 Object mappedHandler = this.handlerMap.get(urlPath); // <3> 检验 mappedHandler 是否已存在,若是已存在,而且不是当前 resolvedHandler 对象,则抛出异常 if (mappedHandler != null) { if (mappedHandler != resolvedHandler) { throw new IllegalStateException( "Cannot map " + getHandlerDescription(handler) + " to URL path [" + urlPath + "]: There is already " + getHandlerDescription(mappedHandler) + " mapped."); } } else { // <4.1> 若是是 / 根路径,则设置为 rootHandler if (urlPath.equals("/")) { if (logger.isTraceEnabled()) { logger.trace("Root mapping to " + getHandlerDescription(handler)); } setRootHandler(resolvedHandler); } // <4.2> 若是是 /* 路径,则设置为默认处理器 else if (urlPath.equals("/*")) { if (logger.isTraceEnabled()) { logger.trace("Default mapping to " + getHandlerDescription(handler)); } setDefaultHandler(resolvedHandler); } // <4.3> 添加到 handlerMap 中 else { this.handlerMap.put(urlPath, resolvedHandler); if (logger.isTraceEnabled()) { logger.trace("Mapped [" + urlPath + "] onto " + getHandlerDescription(handler)); } } } }
遍历 URL,依次注册处理器
handler
为 String 类型,而且仍是单例,则去获取 String 对应的 Bean 对象,resolvedHandler
handlerMap
中得到 urlPath
对应的处理器resolvedHandler
对象,则抛出异常resolvedHandler
处理器保存
/
根路径,则设置 resolvedHandler
为 rootHandler
/*
路径,则设置为默认处理器 defaultHandler
(在父类中)handlerMap
中实现父类的 getHandlerInternal(HttpServletRequest request)
方法,得到处理器,方法以下:
@Override @Nullable protected Object getHandlerInternal(HttpServletRequest request) throws Exception { // <1> 得到请求的路径 String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); // <2> 得到处理器 Object handler = lookupHandler(lookupPath, request); // <3> 若是找不处处理器,则使用 rootHandler 或 defaultHandler 处理器 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; // <3.1> 若是是根路径,则使用 rootHandler 处理器 if ("/".equals(lookupPath)) { rawHandler = getRootHandler(); } // <3.2> 使用默认处理器 if (rawHandler == null) { rawHandler = getDefaultHandler(); } if (rawHandler != null) { // Bean name or resolved handler? // <3.3> 若是找到的处理器是 String 类型,则从容器中找到该 beanName 对应的 Bean 做为处理器 if (rawHandler instanceof String) { String handlerName = (String) rawHandler; rawHandler = obtainApplicationContext().getBean(handlerName); } // <3.4> 空方法,校验处理器。目前暂无子类实现该方法 validateHandler(rawHandler, request); // <3.5> 建立处理器(HandlerExecutionChain 对象) handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null); } } return handler; }
得到请求路径
调用 lookupHandler(String urlPath, HttpServletRequest request)
方法,得到处理器,详情见下文
若是找不处处理器,则使用 rootHandler
或 defaultHandler
处理器
/
根路径,则使用 rootHandler
处理器defaultHandler
默认处理器validateHandler(Object handler, HttpServletRequest request)
,对处理器进行校验,空方法,暂无子类实现该方法buildPathExposingHandler
方法,建立 HandlerExecutionChain 处理器执行链,赋值给handler
处理器,详情见下文返回请求对应的handler
处理器
因此说这里但会的处理器对象多是一个 HandlerExecutionChain 对象,用途目前不清楚😈 😈 先继续往下看
lookupHandler(String urlPath, HttpServletRequest request)
方法,得到请求对应的处理器,方法以下:
@Nullable protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception { // Direct match? // <1.1> 状况一,从 handlerMap 中,直接匹配处理器 Object handler = this.handlerMap.get(urlPath); if (handler != null) { // Bean name or resolved handler? // <1.2> 若是找到的处理器是 String 类型,则从容器中找到该 beanName 对应的 Bean 做为处理器 if (handler instanceof String) { String handlerName = (String) handler; handler = obtainApplicationContext().getBean(handlerName); } // <1.3> 空方法,校验处理器。目前暂无子类实现该方法 validateHandler(handler, request); // <1.4> 建立处理器 return buildPathExposingHandler(handler, urlPath, urlPath, null); } // Pattern match? List<String> matchingPatterns = new ArrayList<>(); // <2.1> 状况二,Pattern 匹配合适的,并添加到 matchingPatterns 中 for (String registeredPattern : this.handlerMap.keySet()) { if (getPathMatcher().match(registeredPattern, urlPath)) { // 路径经过Pattern匹配成功 matchingPatterns.add(registeredPattern); } else if (useTrailingSlashMatch()) { if (!registeredPattern.endsWith("/") && getPathMatcher().match(registeredPattern + "/", urlPath)) { matchingPatterns.add(registeredPattern + "/"); } } } // <2.2> 得到首个匹配(最优)的结果 String bestMatch = null; Comparator<String> patternComparator = getPathMatcher().getPatternComparator(urlPath); if (!matchingPatterns.isEmpty()) { // 排序 matchingPatterns.sort(patternComparator); if (logger.isTraceEnabled() && matchingPatterns.size() > 1) { logger.trace("Matching patterns " + matchingPatterns); } bestMatch = matchingPatterns.get(0); } if (bestMatch != null) { // <2.3> 得到 bestMatch 对应的处理器 handler = this.handlerMap.get(bestMatch); if (handler == null) { if (bestMatch.endsWith("/")) { handler = this.handlerMap.get(bestMatch.substring(0, bestMatch.length() - 1)); } if (handler == null) { // 若是得到不到,抛出 IllegalStateException 异常 throw new IllegalStateException( "Could not find handler for best pattern match [" + bestMatch + "]"); } } // <2.4> 若是找到的处理器是 String 类型,则从容器中找到该 beanName 对应的 Bean 做为处理器 // Bean name or resolved handler? if (handler instanceof String) { String handlerName = (String) handler; handler = obtainApplicationContext().getBean(handlerName); } // <2.5> 空方法,校验处理器。目前暂无子类实现该方法 validateHandler(handler, request); // <2.6> 得到匹配的路径 String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestMatch, urlPath); // There might be multiple 'best patterns', let's make sure we have the correct URI template variables // for all of them // <2.7> 得到路径参数集合 Map<String, String> uriTemplateVariables = new LinkedHashMap<>(); for (String matchingPattern : matchingPatterns) { if (patternComparator.compare(bestMatch, matchingPattern) == 0) { Map<String, String> vars = getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath); Map<String, String> decodedVars = getUrlPathHelper().decodePathVariables(request, vars); uriTemplateVariables.putAll(decodedVars); } } if (logger.isTraceEnabled() && uriTemplateVariables.size() > 0) { logger.trace("URI variables " + uriTemplateVariables); } // <2.8> 建立处理器 return buildPathExposingHandler(handler, bestMatch, pathWithinMapping, uriTemplateVariables); } // No handler found... return null; }
状况一
handlerMap
中,直接匹配处理器buildPathExposingHandler
方法,详情见下文状况二
matchingPatterns
中bestMatch
bestMatch
对应的处理器,若是得到不到,抛出异常pathWithinMapping
uriTemplateVariables
buildPathExposingHandler
方法,详情见下文都不匹配则返回 null
buildPathExposingHandler(Object rawHandler, String bestMatchingPattern, String pathWithinMapping, @Nullable Map<String, String> uriTemplateVariables)
方法
构建一个 HandlerExecutionChain 类型的处理器,添加两个拦截器,方法以下:
protected Object buildPathExposingHandler(Object rawHandler, String bestMatchingPattern, String pathWithinMapping, @Nullable Map<String, String> uriTemplateVariables) { // <1> 建立 HandlerExecutionChain 对象 HandlerExecutionChain chain = new HandlerExecutionChain(rawHandler); // <2> 添加 PathExposingHandlerInterceptor 拦截器,到 chain 中 chain.addInterceptor(new PathExposingHandlerInterceptor(bestMatchingPattern, pathWithinMapping)); if (!CollectionUtils.isEmpty(uriTemplateVariables)) { // <3> 添加 UriTemplateVariablesHandlerInterceptor 拦截器,到 chain 中 chain.addInterceptor(new UriTemplateVariablesHandlerInterceptor(uriTemplateVariables)); } return chain; }
bestMatchingPattern
属性到请求中uriTemplateVariables
属性到请求中两个拦截器以下:
private class PathExposingHandlerInterceptor extends HandlerInterceptorAdapter { /** 最佳匹配的路径 */ private final String bestMatchingPattern; /** 被匹配的路径 */ private final String pathWithinMapping; public PathExposingHandlerInterceptor(String bestMatchingPattern, String pathWithinMapping) { this.bestMatchingPattern = bestMatchingPattern; this.pathWithinMapping = pathWithinMapping; } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { exposePathWithinMapping(this.bestMatchingPattern, this.pathWithinMapping, request); request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, handler); request.setAttribute(INTROSPECT_TYPE_LEVEL_MAPPING, supportsTypeLevelMappings()); return true; } } protected void exposePathWithinMapping(String bestMatchingPattern, String pathWithinMapping, HttpServletRequest request) { request.setAttribute(BEST_MATCHING_PATTERN_ATTRIBUTE, bestMatchingPattern); request.setAttribute(PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, pathWithinMapping); } private class UriTemplateVariablesHandlerInterceptor extends HandlerInterceptorAdapter { private final Map<String, String> uriTemplateVariables; public UriTemplateVariablesHandlerInterceptor(Map<String, String> uriTemplateVariables) { this.uriTemplateVariables = uriTemplateVariables; } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { exposeUriTemplateVariables(this.uriTemplateVariables, request); return true; } } protected void exposeUriTemplateVariables(Map<String, String> uriTemplateVariables, HttpServletRequest request) { request.setAttribute(URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVariables); }
都是往请求中设置相关属性,用途目前不清楚😈 😈 先继续往下看
match(HttpServletRequest request, String pattern)
方法,执行匹配,代码以下:
@Override @Nullable public RequestMatchResult match(HttpServletRequest request, String pattern) { // <1> 得到请求路径 String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); // <2> 模式匹配,若匹配,则返回 RequestMatchResult 对象 if (getPathMatcher().match(pattern, lookupPath)) { return new RequestMatchResult(pattern, lookupPath, getPathMatcher()); } else if (useTrailingSlashMatch()) { if (!pattern.endsWith("/") && getPathMatcher().match(pattern + "/", lookupPath)) { return new RequestMatchResult(pattern + "/", lookupPath, getPathMatcher()); } } return null; }
org.springframework.web.servlet.handler.SimpleUrlHandlerMapping
,继承 AbstractUrlHandlerMapping 抽象类,简单的就 URL 匹配的 HandlerMapping 实现类
在接触 Spring MVC 比较早,你也许见过这样配置
<!-- 定义一个 helloController Bean,实现了 Controller 接口 --> <bean id="helloController" class="com.fullmoon.study.controller.HelloController"/> <!-- 定义请求处理映射 HandlerMapping --> <bean class="org.springframework.web.servlet.handler. SimpleUrlHandlerMapping"> <property name="mappings" ref="urlMappings" /> </bean> <!-- 定义请求映射表 map --> <util:properties id="urlMappings"> <prop key="/hello.form">helloController</prop> </util:properties>
固然,上述这种配置基本已经不存在了,由于被 @RequestMapping
注解这样的方式所取代。更多的是 Spring MVC 本身内部的组件可能在使用这种类型的 HandlerMapping ,例以下图:
public class SimpleUrlHandlerMapping extends AbstractUrlHandlerMapping { /** * 配置的 URL 与处理器的映射 * * 最终,会调用 {@link #registerHandlers(Map)} 进行注册到 {@link AbstractUrlHandlerMapping#handlerMap} 中 */ private final Map<String, Object> urlMap = new LinkedHashMap<>(); public void setMappings(Properties mappings) { CollectionUtils.mergePropertiesIntoMap(mappings, this.urlMap); } public void setUrlMap(Map<String, ?> urlMap) { this.urlMap.putAll(urlMap); } }
例如上面的配置示例就会经过 setMappings(Properties mappings)
方法,将 /hello.form
与 HelloController
设置到 urlMap
中
因此说处理器也多是一个 Controller 接口
initApplicationContext()
方法,用于初始化,将 urlMap
中的URL与处理器添加到父类的 handlerMap
中
在父类 WebApplicationObjectSupport 的父类 ApplicationObjectSupport 中能够看到,由于实现了 ApplicationContextAware 接口,则在初始化该 Bean 的时候会调用
setApplicationContext(@Nullable ApplicationContext context)
方法,在这个方法中会调用initApplicationContext()
这个方法在父类 AbstractHandlerMapping 中,该方法会初始化拦截器们
@Override public void initApplicationContext() throws BeansException { super.initApplicationContext(); registerHandlers(this.urlMap); } protected void registerHandlers(Map<String, Object> urlMap) throws BeansException { if (urlMap.isEmpty()) { logger.trace("No patterns in " + formatMappingName()); } else { urlMap.forEach((url, handler) -> { // Prepend with slash if not already present. if (!url.startsWith("/")) { url = "/" + url; } // Remove whitespace from handler bean name. if (handler instanceof String) { handler = ((String) handler).trim(); } // 【核心代码】注册处理器 registerHandler(url, handler); }); if (logger.isDebugEnabled()) { List<String> patterns = new ArrayList<>(); if (getRootHandler() != null) { patterns.add("/"); } if (getDefaultHandler() != null) { patterns.add("/**"); } patterns.addAll(getHandlerMap().keySet()); logger.debug("Patterns " + patterns + " in " + formatMappingName()); } } }
逻辑很简单,调用父类的registerHandler(String urlPath, Object handler)
方法,添加注册器
org.springframework.web.servlet.handler.AbstractDetectingUrlHandlerMapping
,继承 AbstractUrlHandlerMapping 抽象类,自动探测的基于 URL 匹配的 HandlerMapping 抽象实现类
public abstract class AbstractDetectingUrlHandlerMapping extends AbstractUrlHandlerMapping { /** * 是否只扫描可访问的 Handler 们 */ private boolean detectHandlersInAncestorContexts = false; public void setDetectHandlersInAncestorContexts(boolean detectHandlersInAncestorContexts) { this.detectHandlersInAncestorContexts = detectHandlersInAncestorContexts; } }
initApplicationContext()
方法,用于初始化,找到符合条件的处理器,添加到父类的 handlerMap
中
在父类 WebApplicationObjectSupport 的父类 ApplicationObjectSupport 中能够看到,由于实现了 ApplicationContextAware 接口,则在初始化该 Bean 的时候会调用
setApplicationContext(@Nullable ApplicationContext context)
方法,在这个方法中会调用initApplicationContext()
这个方法在父类 AbstractHandlerMapping 中,该方法会初始化拦截器们
@Override public void initApplicationContext() throws ApplicationContextException { super.initApplicationContext(); // 自动探测处理器 detectHandlers(); } protected void detectHandlers() throws BeansException { // <1> 从 Spring 上下文获取全部 Object 类型的 Bean 的名称们 ApplicationContext applicationContext = obtainApplicationContext(); String[] beanNames = (this.detectHandlersInAncestorContexts ? BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext, Object.class) : applicationContext.getBeanNamesForType(Object.class)); // Take any bean name that we can determine URLs for. // <2> 遍历全部的 Bean ,逐个注册 for (String beanName : beanNames) { // <2.1> 得到 Bean 对应的 URL 们 String[] urls = determineUrlsForHandler(beanName); // <2.2> 若是该 Bean 存在对应的 URL,则添加该处理器 if (!ObjectUtils.isEmpty(urls)) { // 调用父类的方法,往 `handlerMap` 中添加注册器 registerHandler(urls, beanName); } } if ((logger.isDebugEnabled() && !getHandlerMap().isEmpty()) || logger.isTraceEnabled()) { logger.debug("Detected " + getHandlerMap().size() + " mappings in " + formatMappingName()); } }
determineUrlsForHandler(String beanName)
抽象方法,交由子类实现,详情见 BeanNameUrlHandlerMapping
handlerMap
中添加注册器org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping
,继承 AbstractDetectingUrlHandlerMapping 抽象类,基于 Bean 的名字来自动探测的 HandlerMapping 实现类
<!-- 定义一个 helloController Bean,实现了 Controller 接口 --> <bean id="/hello.form" class="com.fullmoon.study.controller.HelloController"/>
和 SimpleUrlHandlerMapping 不一样,只须要设置它的 beanName 以 /
开头就行了,会被 BeanNameUrlHandlerMapping 探测到
public class BeanNameUrlHandlerMapping extends AbstractDetectingUrlHandlerMapping { @Override protected String[] determineUrlsForHandler(String beanName) { List<String> urls = new ArrayList<>(); // 若是是以 / 开头,添加到 urls if (beanName.startsWith("/")) { urls.add(beanName); } // 得到 beanName 的别名们,若是以 / 开头,则添加到 urls String[] aliases = obtainApplicationContext().getAliases(beanName); for (String alias : aliases) { if (alias.startsWith("/")) { urls.add(alias); } } return StringUtils.toStringArray(urls); } }
逻辑很简单,若是 Bean 的名称或者别名是以 /
开头,则会做为一个 url
返回,父类则会将该 Bean 做为一个处理器
在 Spring MVC 处理请求的过程当中,须要经过 HandlerMapping 组件会为请求找到合适的 HandlerExecutionChain
处理器执行链,包含处理器(handler
)和拦截器们(interceptors
),该组件体系结构以下:
本文就黄色框中的内容进行了分析,基于 URL 进行匹配。若是你接触 Spring MVC 较早,可能见过 SimpleUrlHandlerMapping
和 BeanNameUrlHandlerMapping
中的使用示例的配置方式。固然,目前这种方式已经基本不用了,被 @RequestMapping
等注解的方式所取代。不过,Spring MVC 内置的一些路径匹配,仍是使用这种方式。
相对来讲逻辑比较简单,若是你有一个 Controller
或者 HttpRequestHandler
接口的实现类,有如下两种方式将其设置为处理器,能够处理请求
Map<String, Object> urlMap
中添加 url
与 Controller 实现类
的映射就行了Controller 实现类
的 beanName
为以 /
开头的名称就行了,它会探测到,将这个 Bean 的 beanName
做为 url
,将 Controller 实现类
做为处理器至此,HandlerMapping 组件就分析到这里了,相信你对 HandlerMapping 组件有了一个深刻的了解,更加的清楚 Spring MVC 是如何处理器请求的
HandlerMapping 组件返回的
HandlerExecutionChain
处理器执行链,包含处理器(handler
)和拦截器们(interceptors
),那么这个处理器是被谁调用的呢?由于不一样的 HandlerMapping 实现类返回的处理器类型可能不同,如何执行这个处理器,这部分工做都交由 HandlerAdapter 组件(处理器的适配器)来完成
这里咱们就把处理器理解为
HandlerMethod
处理器对象吧,由于咱们平时使用最多的方式就是经过@RequestMapping
注解来标注某个方法处理对应的请求别慌,接下来分析 HandlerAdapter 组件不会特别复杂😈
参考文章:芋道源码《精尽 Spring MVC 源码分析》