diff --git a/README.md b/README.md index 2b7da7d..27eaa79 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ 1. [\[2021-10-14\] Spring 源码解析三:Bean 的注册、解析、实例化机制](spring/3.md) 1. [\[2021-10-14\] Spring 源码解析四:Bean 的构造装载、属性值解析、注解扫描](spring/4.md) 1. [\[2021-10-19\] Spring 源码解析五:Bean 的配置、定义、注册](spring/5.md) +1. [\[2021-10-20\] Spring 源码解析六:处理器映射与处理器适配处理](spring/6.md) ## 前端进阶 diff --git a/spring/1.md b/spring/1.md index ea35388..7aab17a 100644 --- a/spring/1.md +++ b/spring/1.md @@ -837,10 +837,6 @@ public class DispatcherServlet extends FrameworkServlet { 文件(开发者不能自定义覆盖)如下: ```properties -# Default implementation classes for DispatcherServlet's strategy interfaces. -# Used as fallback when no matching beans are found in the DispatcherServlet context. -# Not meant to be customized by application developers. - org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver @@ -868,14 +864,29 @@ org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet. `DispatcherServlet.properties` 文件中指明: -- 把 `AcceptHeaderLocaleResolver` 作为默认的本地化解析器 -- 把 `FixedThemeResolver` 作为默认的主题解析器 -- 把 `BeanNameUrlHandlerMapping, RequestMappingHandlerMapping, RouterFunctionMapping` 作为默认的处理器映射组件 -- 把 `HttpRequestHandlerAdapter, SimpleControllerHandlerAdapter, RequestMappingHandlerAdapter, HandlerFunctionAdapter` 作为默认的处理器适配组件 -- 把 `ExceptionHandlerExceptionResolver, ResponseStatusExceptionResolver, DefaultHandlerExceptionResolver` 作为默认的处理器异常解析器 -- 把 `DefaultRequestToViewNameTranslator` 作为默认的视图查找处理器 -- 把 `InternalResourceViewResolver` 作为默认的视图解析器 -- 把 `SessionFlashMapManager` 作为默认的内存暂存 session 数据管理器 +- 把 [AcceptHeaderLocaleResolver](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/AcceptHeaderLocaleResolver.java) + 作为默认的本地化解析器 +- 把 [FixedThemeResolver](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/theme/FixedThemeResolver.java) + 作为默认的主题解析器 +- 把 [BeanNameUrlHandlerMapping](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/BeanNameUrlHandlerMapping.java) + 、[RequestMappingHandlerMapping](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java) + 、[RouterFunctionMapping](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/function/support/RouterFunctionMapping.java) + 作为默认的处理器映射组件 +- 把 [HttpRequestHandlerAdapter](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/HttpRequestHandlerAdapter.java) + 、[SimpleControllerHandlerAdapter](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/SimpleControllerHandlerAdapter.java) + 、[RequestMappingHandlerAdapter](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.java) + 、[HandlerFunctionAdapter](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/function/support/HandlerFunctionAdapter.java) + 作为默认的处理器适配组件 +- 把 [ExceptionHandlerExceptionResolver](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java) + 、[ResponseStatusExceptionResolver](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/annotation/ResponseStatusExceptionResolver.java) + 、[DefaultHandlerExceptionResolver](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolver.java) + 作为默认的处理器异常解析器 +- 把 [DefaultRequestToViewNameTranslator](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/view/DefaultRequestToViewNameTranslator.java) + 作为默认的视图查找处理器 +- 把 [InternalResourceViewResolver](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/view/InternalResourceViewResolver.java) + 作为默认的视图解析器 +- 把 [SessionFlashMapManager](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/support/SessionFlashMapManager.java) + 作为默认的内存暂存 session 数据管理器 ##### 3.6.1.2. DispatcherServlet.initHandlerAdapters diff --git a/spring/6.md b/spring/6.md new file mode 100644 index 0000000..23d5ffe --- /dev/null +++ b/spring/6.md @@ -0,0 +1,1149 @@ +# Spring 源码解析六:处理器映射与处理器适配处理 + +在 [Spring 源码解析一:SpringMVC 的加载机制](./1.md) 中,留有一些点待解析: + +1. `ConfigurableWebApplicationContext.refresh` 刷新上下文 +1. `ApplicationContext.getBean` 从上下文中获取 bean +1. `DispatcherServlet.properties` 文件中定义的策略处理 +1. `ContextLoader.properties` 文件中定义的策略处理 +1. `View.render` 视图渲染 + +其中第一、二、四条已在 [Spring 源码解析二:上下文组件(WebApplicationContext)](./2.md) 中解析了,这一节来看看后面第三条:`DispatcherServlet.properties` 文件中定义的策略处理 + +[DispatcherServlet.properties](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/resources/org/springframework/web/servlet/DispatcherServlet.properties) +文件内容如下: + +```properties +org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver + +org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver + +org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\ + org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping,\ + org.springframework.web.servlet.function.support.RouterFunctionMapping + +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,\ + org.springframework.web.servlet.function.support.HandlerFunctionAdapter + + +org.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\ + org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\ + org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver + +org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator + +org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver + +org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager +``` + +`DispatcherServlet.properties` 文件中指明: + +- 把 [AcceptHeaderLocaleResolver](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/AcceptHeaderLocaleResolver.java) + 作为默认的本地化解析器 +- 把 [FixedThemeResolver](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/theme/FixedThemeResolver.java) + 作为默认的主题解析器 +- 把 [BeanNameUrlHandlerMapping](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/BeanNameUrlHandlerMapping.java) + 、[RequestMappingHandlerMapping](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java) + 、[RouterFunctionMapping](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/function/support/RouterFunctionMapping.java) + 作为默认的处理器映射组件 +- 把 [HttpRequestHandlerAdapter](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/HttpRequestHandlerAdapter.java) + 、[SimpleControllerHandlerAdapter](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/SimpleControllerHandlerAdapter.java) + 、[RequestMappingHandlerAdapter](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.java) + 、[HandlerFunctionAdapter](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/function/support/HandlerFunctionAdapter.java) + 作为默认的处理器适配组件 +- 把 [ExceptionHandlerExceptionResolver](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ExceptionHandlerExceptionResolver.java) + 、[ResponseStatusExceptionResolver](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/annotation/ResponseStatusExceptionResolver.java) + 、[DefaultHandlerExceptionResolver](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolver.java) + 作为默认的处理器异常解析器 +- 把 [DefaultRequestToViewNameTranslator](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/view/DefaultRequestToViewNameTranslator.java) + 作为默认的视图查找处理器 +- 把 [InternalResourceViewResolver](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/view/InternalResourceViewResolver.java) + 作为默认的视图解析器 +- 把 [SessionFlashMapManager](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/support/SessionFlashMapManager.java) + 作为默认的内存暂存 session 数据管理器 + +`LocaleResolver`与`ThemeResolver`策略比较简单,这里就不解析了 + +## 1. BeanNameUrlHandlerMapping + +[BeanNameUrlHandlerMapping](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/BeanNameUrlHandlerMapping.java) +的主要功能是映射 url 到 bean,继承关系如下 + +``` +- AbstractHandlerMapping + - AbstractUrlHandlerMapping + - AbstractDetectingUrlHandlerMapping + - BeanNameUrlHandlerMapping +``` + +### 1.1. AbstractHandlerMapping + +[AbstractHandlerMapping](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMapping.java) +的主要功能是支持处理器排序、指定默认处理器、处理器拦截等 + +```java +public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport + implements HandlerMapping, Ordered, BeanNameAware { + // 获取处理器 + public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { + // 获取匹配的处理器 + Object handler = getHandlerInternal(request); + // 没有匹配的处理器,则获取默认的处理器 + if (handler == null) { + handler = getDefaultHandler(); + } + // 没有处理器,返回null + if (handler == null) { + return null; + } + // handler是String的话,当做一个bean名字去获取bean实例 + if (handler instanceof String) { + String handlerName = (String) handler; + handler = obtainApplicationContext().getBean(handlerName); + } + + // 获取处理器执行链 + HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); + + // ... 代码省略 + + return executionChain; + } + + // 获取匹配的处理器,子类实现 + protected abstract Object getHandlerInternal(HttpServletRequest request) throws Exception; + + // 获取处理器执行链 + protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) { + // 创建处理器执行链 + HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ? + (HandlerExecutionChain) handler : new HandlerExecutionChain(handler)); + + // 添加连接器,如安全验证、CORS、CSRF等 + for (HandlerInterceptor interceptor : this.adaptedInterceptors) { + if (interceptor instanceof MappedInterceptor) { + MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor; + if (mappedInterceptor.matches(request)) { + chain.addInterceptor(mappedInterceptor.getInterceptor()); + } + } + else { + chain.addInterceptor(interceptor); + } + } + return chain; + } +} +``` + +### 1.2. AbstractUrlHandlerMapping + +[AbstractUrlHandlerMapping](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractUrlHandlerMapping.java) +的主要功能是实现 url 映射 + +先来看看 handler 的注册 + +```java +public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping implements MatchableHandlerMapping { + // 容器 urlPath => handler + private final Map handlerMap = new LinkedHashMap<>(); + // 容器 urlPattern => handler + private final Map pathPatternHandlerMap = new LinkedHashMap<>(); + + // 注册一个handler + protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException { + Object resolvedHandler = handler; + + // handler是String的话,当做一个bean名字去获取bean实例 + if (handler instanceof String) { + String handlerName = (String) handler; + ApplicationContext applicationContext = obtainApplicationContext(); + if (applicationContext.isSingleton(handlerName)) { + resolvedHandler = applicationContext.getBean(handlerName); + } + } + + Object mappedHandler = this.handlerMap.get(urlPath); + if (mappedHandler != null) { + if (mappedHandler != resolvedHandler) { + // 已经注册过了,报错 + } + } + else { + if (urlPath.equals("/")) { + // 设为根处理器,只匹配 / + setRootHandler(resolvedHandler); + } + else if (urlPath.equals("/*")) { + // 设为默认处理器,匹配所有 + setDefaultHandler(resolvedHandler); + } + else { + // 装进容器 + this.handlerMap.put(urlPath, resolvedHandler); + if (getPatternParser() != null) { + // 装进模式匹配的容器 + this.pathPatternHandlerMap.put(getPatternParser().parse(urlPath), resolvedHandler); + } + } + } + } +} +``` + +再来看看 handler 的获取 + +```java +public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping implements MatchableHandlerMapping { + // 获取匹配的处理器 + @Override + protected Object getHandlerInternal(HttpServletRequest request) throws Exception { + // 获取真实的path部分 + String lookupPath = initLookupPath(request); + Object handler; + + // 使用模式匹配 + if (usesPathPatterns()) { + RequestPath path = ServletRequestPathUtils.getParsedRequestPath(request); + handler = lookupHandler(path, lookupPath, request); + } + // 直接匹配路径 + else { + handler = lookupHandler(lookupPath, request); + } + + // 如果都没有 + if (handler == null) { + Object rawHandler = null; + // 如果是 /,则调用根处理器 + if (StringUtils.matchesCharacter(lookupPath, '/')) { + rawHandler = getRootHandler(); + } + // 如果仍没有,获取默认的解析器,/* + if (rawHandler == null) { + rawHandler = getDefaultHandler(); + } + if (rawHandler != null) { + // handler是String的话,当做一个bean名字去获取bean实例 + if (rawHandler instanceof String) { + String handlerName = (String) rawHandler; + rawHandler = obtainApplicationContext().getBean(handlerName); + } + // 包裹handler为HandlerExecutionChain + handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null); + } + } + return handler; + } + + // 查找处理器 + protected Object lookupHandler( + RequestPath path, String lookupPath, HttpServletRequest request) throws Exception { + // 直接通过lookupPath获取处理器 + Object handler = getDirectMatch(lookupPath, request); + // 存在就返回 + if (handler != null) { + return handler; + } + + // 用模式匹配 + List matches = null; + for (PathPattern pattern : this.pathPatternHandlerMap.keySet()) { + if (pattern.matches(path.pathWithinApplication())) { + matches = (matches != null ? matches : new ArrayList<>()); + matches.add(pattern); + } + } + // 没有匹配的模式,返回null + if (matches == null) { + return null; + } + + // ... 代码省略 + + // 获取第一个匹配的模式 + PathPattern pattern = matches.get(0); + // 获取第一个匹配的模式处理器 + handler = this.pathPatternHandlerMap.get(pattern); + // handler是String的话,当做一个bean名字去获取bean实例 + if (handler instanceof String) { + String handlerName = (String) handler; + handler = obtainApplicationContext().getBean(handlerName); + } + + // 提取pattern匹配的部分,如 + // '/docs/cvs/commit.html' and '/docs/cvs/commit.html' => '' + // '/docs/*' and '/docs/cvs/commit' => 'cvs/commit' + // '/docs/cvs/*.html' and '/docs/cvs/commit.html' => 'commit.html' + // '/docs/**' and '/docs/cvs/commit' => 'cvs/commit' + PathContainer pathWithinMapping = pattern.extractPathWithinPattern(path.pathWithinApplication()); + // 包裹handler为HandlerExecutionChain + return buildPathExposingHandler(handler, pattern.getPatternString(), pathWithinMapping.value(), null); + } +} +``` + +### 1.3. AbstractDetectingUrlHandlerMapping + +[AbstractDetectingUrlHandlerMapping](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractDetectingUrlHandlerMapping.java) +的主要功能是侦测上下文中的 bean,然后注册 handler + +```java +public abstract class AbstractDetectingUrlHandlerMapping extends AbstractUrlHandlerMapping { + // 初始化上下文后,侦测上下文中的bean,然后注册handler + @Override + public void initApplicationContext() throws ApplicationContextException { + super.initApplicationContext(); + detectHandlers(); + } + + // 侦测上下文中的bean,然后注册handler + protected void detectHandlers() throws BeansException { + ApplicationContext applicationContext = obtainApplicationContext(); + // 使用Object.class,就是获取所有的bean + String[] beanNames = (this.detectHandlersInAncestorContexts ? + BeanFactoryUtils.beanNamesForTypeIncludingAncestors(applicationContext, Object.class) : + applicationContext.getBeanNamesForType(Object.class)); + + // 遍历beanNames + for (String beanName : beanNames) { + // 获取一个handler的多个url匹配 + String[] urls = determineUrlsForHandler(beanName); + // 如果是url=>bean的匹配,就注册 + // 如果beanName是以斜线"/"开头的,则认为是url + if (!ObjectUtils.isEmpty(urls)) { + // 注册url和beanName + registerHandler(urls, beanName); + } + } + } + + + // 获取一个handler的多个url匹配,由子类实现 + protected abstract String[] determineUrlsForHandler(String beanName); +} +``` + +### 1.4. BeanNameUrlHandlerMapping + +[BeanNameUrlHandlerMapping](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/BeanNameUrlHandlerMapping.java) +的主要功能是侦测 handler 的 url + +```java +public class BeanNameUrlHandlerMapping extends AbstractDetectingUrlHandlerMapping { + // 侦测handler的url + @Override + protected String[] determineUrlsForHandler(String beanName) { + List urls = new ArrayList<>(); + // 如果beanName是 / 开头,表示是url + if (beanName.startsWith("/")) { + urls.add(beanName); + } + String[] aliases = obtainApplicationContext().getAliases(beanName); + for (String alias : aliases) { + // 如果别名是 / 开头,表示是url + if (alias.startsWith("/")) { + urls.add(alias); + } + } + return StringUtils.toStringArray(urls); + } +} +``` + +## 2. RequestMappingHandlerMapping + +[RequestMappingHandlerMapping](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java) +的主要功能是处理`@RequestMapping`与`@Controller`注解,继承关系如下 + +``` +- AbstractHandlerMapping + - AbstractHandlerMethodMapping + - RequestMappingInfoHandlerMapping + - RequestMappingHandlerMapping +``` + +### 2.1. AbstractHandlerMethodMapping + +[AbstractHandlerMethodMapping](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java) +的主要功能是定义 request 到 HandlerMethod 映射 + +先来看看 handler 的注册 + +```java +public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMapping implements InitializingBean { + // 注册一个映射 + public void registerMapping(T mapping, Object handler, Method method) { + this.mappingRegistry.register(mapping, handler, method); + } + + // 当属性都注入后,由上下文环境调用此方法初始化 + @Override + public void afterPropertiesSet() { + initHandlerMethods(); + } + + // 初始化所有处理器方法 + protected void initHandlerMethods() { + // 获取上下文环境所有的bean + for (String beanName : getCandidateBeanNames()) { + // beanName以"scopedTarget."开头 + if (!beanName.startsWith(SCOPED_TARGET_NAME_PREFIX)) { + processCandidateBean(beanName); + } + } + + // ... 代码省略 + } + + // 处理bean + protected void processCandidateBean(String beanName) { + Class beanType = null; + try { + beanType = obtainApplicationContext().getType(beanName); + } + catch (Throwable ex) { + // ... 代码省略 + } + // 如果有`@RequestMapping`与`@Controller`注解,则是处理器 + if (beanType != null && isHandler(beanType)) { + // 探测处理器方法 + detectHandlerMethods(beanName); + } + } + + // 探测处理器方法 + protected void detectHandlerMethods(Object handler) { + // 获取bean类型 + Class handlerType = (handler instanceof String ? + obtainApplicationContext().getType((String) handler) : handler.getClass()); + + if (handlerType != null) { + Class userType = ClassUtils.getUserClass(handlerType); + // 查找bean类型上的方法 + Map methods = MethodIntrospector.selectMethods(userType, + (MethodIntrospector.MetadataLookup) method -> { + try { + // 包裹为RequestMappingInfo + return getMappingForMethod(method, userType); + } + catch (Throwable ex) { + // ... 代码省略 + } + }); + + methods.forEach((method, mapping) -> { + // 使用mappingRegistry注册处理器映射 + registerHandlerMethod(handler, method, mapping); + }); + } + } +} +``` + +再来看看 handler 的获取 + +```java +public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMapping implements InitializingBean { + // 获取匹配的处理器 + @Override + protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception { + // 获取真实的path部分 + String lookupPath = initLookupPath(request); + + // ... 代码省略 + + try { + // 获取path匹配的方法处理器 + HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request); + // handlerMethod的bean是String的话,当做一个bean名字去获取bean实例 + return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null); + } + finally { + // ... 代码省略 + } + } + + // 获取path匹配的方法处理器 + protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception { + List matches = new ArrayList<>(); + + // 直接匹配path + List directPathMatches = this.mappingRegistry.getMappingsByDirectPath(lookupPath); + // 直接匹配到了path + if (directPathMatches != null) { + // 添加匹配映射到matches中 + addMatchingMappings(directPathMatches, matches, request); + } + // 如果没有直接匹配到path + if (matches.isEmpty()) { + // 把所有的注册模式拿来匹配 + addMatchingMappings(this.mappingRegistry.getRegistrations().keySet(), matches, request); + } + // 匹配到了 + if (!matches.isEmpty()) { + // 默认取第一个匹配 + Match bestMatch = matches.get(0); + if (matches.size() > 1) { + // 如果匹配到了多个模式,则进行排序,取最优的 + Comparator comparator = new MatchComparator(getMappingComparator(request)); + matches.sort(comparator); + bestMatch = matches.get(0); + + // ... 代码省略 + } + + // ... 代码省略 + + return bestMatch.handlerMethod; + } + else { + // 未匹配到,返回null + return handleNoMatch(this.mappingRegistry.getRegistrations().keySet(), lookupPath, request); + } + } +} +``` + +对处理器的注册与管理,其实都是内部类 [RequestMappingHandlerMapping.MappingRegistry](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java#L557) +完成的 + +```java +class MappingRegistry { + // 处理器注册容器 + private final Map> registry = new HashMap<>(); + // 路径查找容器 + private final MultiValueMap pathLookup = new LinkedMultiValueMap<>(); + // 名字查找容器 + private final Map> nameLookup = new ConcurrentHashMap<>(); + + // 注册一个处理器 + public void register(T mapping, Object handler, Method method) { + try { + // 包裹为HandlerMethod + HandlerMethod handlerMethod = createHandlerMethod(handler, method); + + // 获取非模式匹配的路径 + Set directPaths = AbstractHandlerMethodMapping.this.getDirectPaths(mapping); + for (String path : directPaths) { + // 添加到路径查找容器 + this.pathLookup.add(path, mapping); + } + + String name = null; + if (getNamingStrategy() != null) { + // 获取bean名字 + name = getNamingStrategy().getName(handlerMethod, mapping); + // 添加到名字查找容器 + addMappingName(name, handlerMethod); + } + + // ... 代码省略 + + // 添加到处理器注册容器 + this.registry.put(mapping, new MappingRegistration<>(mapping, handlerMethod, directPaths, name)); + } + finally { + // ... 代码省略 + } + } +} +``` + +### 2.2. RequestMappingInfoHandlerMapping + +[RequestMappingInfoHandlerMapping](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMapping.java) +的主要功能是通过 RequestMappingInfo 实现 request 到 HandlerMethod 映射 + +```java +public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMethodMapping { + // 检查请求与路径映射是否匹配 + @Override + protected void handleMatch(RequestMappingInfo info, String lookupPath, HttpServletRequest request) { + super.handleMatch(info, lookupPath, request); + + // 获取模式匹配的条件 + RequestCondition condition = info.getActivePatternsCondition(); + // 路径匹配,会解析通配符,如*? + if (condition instanceof PathPatternsRequestCondition) { + extractMatchDetails1((PathPatternsRequestCondition) condition, lookupPath, request); + } + // 普通字符串匹配 + else { + extractMatchDetails2((PatternsRequestCondition) condition, lookupPath, request); + } + + // ... 代码省略 + } + + // 路径匹配,会解析通配符,如*? + private void extractMatchDetails1( + PathPatternsRequestCondition condition, String lookupPath, HttpServletRequest request) { + // 最佳匹配 + PathPattern bestPattern; + // uri变量,如 /path/:userId/:page + Map uriVariables; + + // 匹配到空字符串 "" + if (condition.isEmptyPathMapping()) { + bestPattern = condition.getFirstPattern(); + uriVariables = Collections.emptyMap(); + } + else { + PathContainer path = ServletRequestPathUtils.getParsedRequestPath(request).pathWithinApplication(); + bestPattern = condition.getFirstPattern(); + // PathPattern解析匹配,并提取变量(PathPattern是AntPathMatcher的增强版) + PathPattern.PathMatchInfo result = bestPattern.matchAndExtract(path); + + uriVariables = result.getUriVariables(); + + // ... 代码省略 + } + + // ... 代码省略 + } + + // 普通字符串匹配 + private void extractMatchDetails2( + PatternsRequestCondition condition, String lookupPath, HttpServletRequest request) { + // 最佳匹配 + PathPattern bestPattern; + // uri变量,如 /path/:userId/:page + Map uriVariables; + + // 匹配到空字符串 "" + if (condition.isEmptyPathMapping()) { + bestPattern = lookupPath; + uriVariables = Collections.emptyMap(); + } + else { + bestPattern = condition.getPatterns().iterator().next(); + // AntPathMatcher解析匹配,并提取变量 + uriVariables = getPathMatcher().extractUriTemplateVariables(bestPattern, lookupPath); + uriVariables = getUrlPathHelper().decodePathVariables(request, uriVariables); + } + + // ... 代码省略 + } +} +``` + +### 2.3. RequestMappingHandlerMapping + +[RequestMappingHandlerMapping](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java) +的主要功能是实现`@RequestMapping`与`@Controller`注解的处理器映射注册 + +```java +public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMapping + implements MatchableHandlerMapping, EmbeddedValueResolverAware { + // 获取方法的映射信息 + @Override + protected RequestMappingInfo getMappingForMethod(Method method, Class handlerType) { + RequestMappingInfo info = createRequestMappingInfo(method); + if (info != null) { + RequestMappingInfo typeInfo = createRequestMappingInfo(handlerType); + if (typeInfo != null) { + info = typeInfo.combine(info); + } + String prefix = getPathPrefix(handlerType); + if (prefix != null) { + info = RequestMappingInfo.paths(prefix).options(this.config).build().combine(info); + } + } + return info; + } + + // 创建映射信息对象 + private RequestMappingInfo createRequestMappingInfo(AnnotatedElement element) { + // 找到@RequestMapping注解 + RequestMapping requestMapping = AnnotatedElementUtils.findMergedAnnotation(element, RequestMapping.class); + + // ... 代码省略 + + return (requestMapping != null ? createRequestMappingInfo(requestMapping, condition) : null); + } + + // 根据RequestMapping创建映射信息对象 + protected RequestMappingInfo createRequestMappingInfo( + RequestMapping requestMapping, @Nullable RequestCondition customCondition) { + + RequestMappingInfo.Builder builder = RequestMappingInfo + // path元信息 + .paths(resolveEmbeddedValuesInPatterns(requestMapping.path())) + // method元信息 + .methods(requestMapping.method()) + // params元信息 + .params(requestMapping.params()) + // headers元信息 + .headers(requestMapping.headers()) + // consumes元信息 + .consumes(requestMapping.consumes()) + // produces元信息 + .produces(requestMapping.produces()) + // name元信息 + .mappingName(requestMapping.name()); + if (customCondition != null) { + builder.customCondition(customCondition); + } + return builder.options(this.config).build(); + } +} +``` + +## 3. RouterFunctionMapping + +[RouterFunctionMapping](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/function/support/RouterFunctionMapping.java) +的主要功能是实现对[RouterFunction](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/function/RouterFunction.java) +的支持,使用 `RouterFunctions.route` 来定义路由,比如 + +```java +@Configuration +public class MyRoutes { + @Bean + RouterFunction home() { + return route(GET("/"), request -> ok().body(fromObject("Home page"))); + } + + @Bean + RouterFunction about() { + return route(GET("/about"), request -> ok().body(fromObject("About page"))); + } +} +``` + +`RouterFunctionMapping` 继承关系如下 + +``` +- AbstractHandlerMapping + - RouterFunctionMapping +``` + +```java +public class RouterFunctionMapping extends AbstractHandlerMapping implements InitializingBean { + // 当属性都注入后,由上下文环境调用此方法初始化 + @Override + public void afterPropertiesSet() throws Exception { + if (this.routerFunction == null) { + // 初始化RouterFunction + initRouterFunction(); + } + + // ... 代码省略 + } + + // 初始化RouterFunction + private void initRouterFunction() { + ApplicationContext applicationContext = obtainApplicationContext(); + // 获取RouterFunction的bean + Map beans = + (this.detectHandlerFunctionsInAncestorContexts ? + BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RouterFunction.class) : + applicationContext.getBeansOfType(RouterFunction.class)); + + List routerFunctions = new ArrayList<>(beans.values()); + + // 把这些bean组合起来 + this.routerFunction = routerFunctions.stream() + .reduce(RouterFunction::andOther) + .orElse(null); + } + + // 获取匹配的处理器 + @Override + protected Object getHandlerInternal(HttpServletRequest servletRequest) throws Exception { + if (this.routerFunction != null) { + ServerRequest request = ServerRequest.create(servletRequest, this.messageConverters); + setAttributes(servletRequest, request); + + // 使用routerFunction来路由请求,没有则返回null + return this.routerFunction.route(request).orElse(null); + } + else { + return null; + } + } +} +``` + +## 4. RequestMappingHandlerAdapter + +`HttpRequestHandlerAdapter`与`SimpleControllerHandlerAdapter`策略比较简单,这里就不解析了 + +[RequestMappingHandlerAdapter](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerAdapter.java) +的主要功能是支持 `@RequestMapping` 定义路由适配调用,继承关系如下 + +``` +- WebContentGenerator + - AbstractHandlerMethodAdapter + - RequestMappingHandlerAdapter +``` + +[WebContentGenerator](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/support/WebContentGenerator.java) +的主要功能是处理响应的头信息,如`Pragma`、`Expires`、`Cache-Control`等 + +[AbstractHandlerMethodAdapter](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/AbstractHandlerMethodAdapter.java) +的主要功能是支持响应 `HandlerMethod` + +```java +public abstract class AbstractHandlerMethodAdapter extends WebContentGenerator implements HandlerAdapter, Ordered { + // 调用处理器,响应请求 + public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) + throws Exception { + + return handleInternal(request, response, (HandlerMethod) handler); + } + + // 调用处理器,响应请求,子类实现 + protected abstract ModelAndView handleInternal(HttpServletRequest request, + HttpServletResponse response, HandlerMethod handlerMethod) throws Exception; +} +``` + +现在来看 `RequestMappingHandlerAdapter` + +### 4.1. RequestMappingHandlerAdapter.afterPropertiesSet + +```java +public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter + implements BeanFactoryAware, InitializingBean { + // 当属性都注入后,由上下文环境调用此方法初始化 + @Override + public void afterPropertiesSet() { + // 初始化`@ControllerAdvice`注解标注的组件 + initControllerAdviceCache(); + + if (this.argumentResolvers == null) { + // 获取默认的参数解析器 + List resolvers = getDefaultArgumentResolvers(); + this.argumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers); + } + if (this.initBinderArgumentResolvers == null) { + // 获取默认的@InitBinder解析器 + List resolvers = getDefaultInitBinderArgumentResolvers(); + this.initBinderArgumentResolvers = new HandlerMethodArgumentResolverComposite().addResolvers(resolvers); + } + if (this.returnValueHandlers == null) { + // 获取默认的响应值处理器 + List handlers = getDefaultReturnValueHandlers(); + this.returnValueHandlers = new HandlerMethodReturnValueHandlerComposite().addHandlers(handlers); + } + } + + // 初始化`@ControllerAdvice`注解标注的组件 + private void initControllerAdviceCache() { + // ... 代码省略 + + // 获取有`@ControllerAdvice`注解的bean + List adviceBeans = ControllerAdviceBean.findAnnotatedBeans(getApplicationContext()); + // 可用的bean + List requestResponseBodyAdviceBeans = new ArrayList<>(); + // 进行遍历 + for (ControllerAdviceBean adviceBean : adviceBeans) { + Class beanType = adviceBean.getBeanType(); + if (beanType == null) { + // 没有类型,报错 + } + // 查找有`@RequestMapping`与`@ModelAttribute`注解的方法 + Set attrMethods = MethodIntrospector.selectMethods(beanType, MODEL_ATTRIBUTE_METHODS); + if (!attrMethods.isEmpty()) { + // 添加进容器 + this.modelAttributeAdviceCache.put(adviceBean, attrMethods); + } + // 查找有`@InitBinder`注解的方法 + Set binderMethods = MethodIntrospector.selectMethods(beanType, INIT_BINDER_METHODS); + if (!binderMethods.isEmpty()) { + // 添加进容器 + this.initBinderAdviceCache.put(adviceBean, binderMethods); + } + // 如何bean类型是RequestBodyAdvice或ResponseBodyAdvice的子类 + if (RequestBodyAdvice.class.isAssignableFrom(beanType) || ResponseBodyAdvice.class.isAssignableFrom(beanType)) { + // 添加进容器 + requestResponseBodyAdviceBeans.add(adviceBean); + } + } + + if (!requestResponseBodyAdviceBeans.isEmpty()) { + // 添加进容器 + this.requestResponseBodyAdvice.addAll(0, requestResponseBodyAdviceBeans); + } + + // ... 代码省略 + } +} +``` + +```java +public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter + implements BeanFactoryAware, InitializingBean { + // 获取默认的参数解析器 + private List getDefaultArgumentResolvers() { + List resolvers = new ArrayList<>(30); + + // @RequestParam 解析 + resolvers.add(new RequestParamMethodArgumentResolver(getBeanFactory(), false)); + resolvers.add(new RequestParamMapMethodArgumentResolver()); + // @PathVariable 解析 + resolvers.add(new PathVariableMethodArgumentResolver()); + resolvers.add(new PathVariableMapMethodArgumentResolver()); + // @MatrixVariable 解析 + resolvers.add(new MatrixVariableMethodArgumentResolver()); + resolvers.add(new MatrixVariableMapMethodArgumentResolver()); + // 数据绑定解析 + resolvers.add(new ServletModelAttributeMethodProcessor(false)); + // @RequestBody @ResponseBody 解析 + resolvers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice)); + // @RequestPart 解析 + resolvers.add(new RequestPartMethodArgumentResolver(getMessageConverters(), this.requestResponseBodyAdvice)); + // @RequestHeader 解析 + resolvers.add(new RequestHeaderMethodArgumentResolver(getBeanFactory())); + resolvers.add(new RequestHeaderMapMethodArgumentResolver()); + // Cookie 解析 + resolvers.add(new ServletCookieValueMethodArgumentResolver(getBeanFactory())); + // @Value 解析 + resolvers.add(new ExpressionValueMethodArgumentResolver(getBeanFactory())); + // @SessionAttribute 解析 + resolvers.add(new SessionAttributeMethodArgumentResolver()); + // @RequestAttribute 解析 + resolvers.add(new RequestAttributeMethodArgumentResolver()); + + // 从原生 ServletRequest 对象的输入流中解析请求头、请求体等 + resolvers.add(new ServletRequestMethodArgumentResolver()); + // 把处理器最终的数据写入到原生 ServletResponse 对象的输出流中,包括响应头、响应体等 + resolvers.add(new ServletResponseMethodArgumentResolver()); + // HttpEntity 处理 + resolvers.add(new HttpEntityMethodProcessor(getMessageConverters(), this.requestResponseBodyAdvice)); + // 重定向处理 + resolvers.add(new RedirectAttributesMethodArgumentResolver()); + // Model 处理 + resolvers.add(new ModelMethodProcessor()); + // Map 处理 + resolvers.add(new MapMethodProcessor()); + // 错误方法解析 + resolvers.add(new ErrorsMethodArgumentResolver()); + // SessionStatus 解析 + resolvers.add(new SessionStatusMethodArgumentResolver()); + // UriComponentsBuilder 解析 + resolvers.add(new UriComponentsBuilderMethodArgumentResolver()); + + // ... 代码省略 + + return resolvers; + } + + // 获取默认的@InitBinder解析器 + private List getDefaultInitBinderArgumentResolvers() { + List resolvers = new ArrayList<>(20); + + 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()); + + resolvers.add(new ServletRequestMethodArgumentResolver()); + resolvers.add(new ServletResponseMethodArgumentResolver()); + + // ... 代码省略 + + return resolvers; + } +} +``` + +```java +public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter + implements BeanFactoryAware, InitializingBean { + // 获取默认的响应值处理器 + private List getDefaultReturnValueHandlers() { + List handlers = new ArrayList<>(20); + + // ModelAndView 处理 + handlers.add(new ModelAndViewMethodReturnValueHandler()); + // Model 处理 + handlers.add(new ModelMethodProcessor()); + // View 处理 + handlers.add(new ViewMethodReturnValueHandler()); + // ResponseBodyEmitter 处理 + handlers.add(new ResponseBodyEmitterReturnValueHandler(getMessageConverters(), + this.reactiveAdapterRegistry, this.taskExecutor, this.contentNegotiationManager)); + // StreamingResponseBody 处理 + handlers.add(new StreamingResponseBodyReturnValueHandler()); + // HttpEntity 处理 + handlers.add(new HttpEntityMethodProcessor(getMessageConverters(), + this.contentNegotiationManager, this.requestResponseBodyAdvice)); + // HttpHeaders 处理 + handlers.add(new HttpHeadersReturnValueHandler()); + // Callable 处理 + handlers.add(new CallableMethodReturnValueHandler()); + // DeferredResult 处理 + handlers.add(new DeferredResultMethodReturnValueHandler()); + // WebAsyncTask 处理 + handlers.add(new AsyncTaskMethodReturnValueHandler(this.beanFactory)); + + // 数据绑定解析 + handlers.add(new ServletModelAttributeMethodProcessor(false)); + // @RequestBody @ResponseBody 解析 + handlers.add(new RequestResponseBodyMethodProcessor(getMessageConverters(), + this.contentNegotiationManager, this.requestResponseBodyAdvice)); + + // 视图名字处理 + handlers.add(new ViewNameMethodReturnValueHandler()); + // Map 处理 + handlers.add(new MapMethodProcessor()); + + // ... 代码省略 + + return handlers; + } +} +``` + +上面的这些解析器和处理器,都在 [web/servlet/mvc/method/annotation](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/) +包和 [web/method/annotation](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-web/src/main/java/org/springframework/web/method/annotation/) +包下,后面再具体解析 + +### 4.2. RequestMappingHandlerAdapter.handleInternal + +```java +public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter + implements BeanFactoryAware, InitializingBean { + // 调用处理器,响应请求 + @Override + protected ModelAndView handleInternal(HttpServletRequest request, + HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { + // 响应对象,可能是视图、数据、视图数据绑定 + ModelAndView mav; + + // ... 代码省略 + + // 调用处理器 + mav = invokeHandlerMethod(request, response, handlerMethod); + + // ... 代码省略 + + return mav; + } + + // 调用处理器 + protected ModelAndView invokeHandlerMethod(HttpServletRequest request, + HttpServletResponse response, HandlerMethod handlerMethod) throws Exception { + // 请求对象 + ServletWebRequest webRequest = new ServletWebRequest(request, response); + try { + // 处理`@ControllerAdvice`与`@InitBinder`,并注入参数解析器argumentResolvers + // 再加上响应模型的数据绑定,生成一个绑定工厂binderFactory + WebDataBinderFactory binderFactory = getDataBinderFactory(handlerMethod); + // 把binderFactory绑定到模型上,并注入参数解析器argumentResolvers + // 生成一个模型工厂modelFactory + ModelFactory modelFactory = getModelFactory(handlerMethod, binderFactory); + + // 封装成一个对象 + ServletInvocableHandlerMethod invocableMethod = createInvocableHandlerMethod(handlerMethod); + if (this.argumentResolvers != null) { + // 注入参数解析器argumentResolvers + invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers); + } + if (this.returnValueHandlers != null) { + // 注入响应处理returnValueHandlers + invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers); + } + // 设置数据绑定工厂 + invocableMethod.setDataBinderFactory(binderFactory); + + // ... 代码省略 + + // 响应容器 + ModelAndViewContainer mavContainer = new ModelAndViewContainer(); + // 初始化模型及容器 + modelFactory.initModel(webRequest, mavContainer, invocableMethod); + + // ... 代码省略 + + // 调用处理器,获取处理结果,应用响应处理returnValueHandlers + invocableMethod.invokeAndHandle(webRequest, mavContainer); + + // ... 代码省略 + + // 获取最终的ModelAndView + return getModelAndView(mavContainer, modelFactory, webRequest); + } + finally { + // 标记当前请求为已完成 + webRequest.requestCompleted(); + } + } + + // 获取最终的ModelAndView + private ModelAndView getModelAndView(ModelAndViewContainer mavContainer, + ModelFactory modelFactory, NativeWebRequest webRequest) throws Exception { + // 更新模型工厂数据 + modelFactory.updateModel(webRequest, mavContainer); + // 如果是纯接口数据,不需要视图,返回null + if (mavContainer.isRequestHandled()) { + return null; + } + // 获取模型对象 + ModelMap model = mavContainer.getModel(); + // 生成ModelAndView + ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, mavContainer.getStatus()); + + // ... 代码省略 + + // 处理重定向 + if (model instanceof RedirectAttributes) { + // ... 代码省略 + } + return mav; + } +} +``` + +## 5. HandlerFunctionAdapter + +[HandlerFunctionAdapter](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/function/support/HandlerFunctionAdapter.java) +的主要功能是实现对[RouterFunction](https://github.com/spring-projects/spring-framework/blob/v5.3.10/spring-webmvc/src/main/java/org/springframework/web/servlet/function/RouterFunction.java) +的适配处理 + +```java +public class HandlerFunctionAdapter implements HandlerAdapter, Ordered { + @Override + public ModelAndView handle(HttpServletRequest servletRequest, + HttpServletResponse servletResponse, + Object handler) throws Exception { + + // ... 代码省略 + + ServerRequest serverRequest = getServerRequest(servletRequest); + ServerResponse serverResponse; + + // ... 代码省略 + + // 直接调用HandlerFunction.handle方法处理 + HandlerFunction handlerFunction = (HandlerFunction) handler; + serverResponse = handlerFunction.handle(serverRequest); + + if (serverResponse != null) { + // 把响应数据直接写入到原生的ServletResponse对象输出流中 + return serverResponse.writeTo(servletRequest, servletResponse, new ServerRequestContext(serverRequest)); + } + else { + return null; + } + } +} +``` + +## 后续 + +更多博客,查看 [https://github.com/senntyou/blogs](https://github.com/senntyou/blogs) + +作者:[深予之 (@senntyou)](https://github.com/senntyou) + +版权声明:自由转载-非商用-非衍生-保持署名([创意共享 3.0 许可证](https://creativecommons.org/licenses/by-nc-nd/3.0/deed.zh))