HandlerMapping / HandlerAdapter / Interceptor 族全解析
概述
Spring MVC 中 DispatcherServlet 将请求分发给处理器(Handler)的过程依赖于 HandlerMapping、HandlerAdapter、HandlerInterceptor 三大核心体系。HandlerMapping 负责将请求映射到处理器,HandlerAdapter 负责调用处理器,HandlerInterceptor 在请求前后提供拦截能力。
本文将深入拆解这三大体系的 10 个关键细节,涵盖 HandlerMapping 实现排序、@RequestMapping 注册、RequestMappingInfo 条件匹配、拦截器链三阶段、参数解析器链、返回值处理器链等核心内容。
本文基于 Spring Framework 6.1.6 源码分析。
DispatcherServlet 整体流程可参考 DispatcherServlet 源码分析。
1. HandlerMapping 的 5 个实现
HandlerMapping 接口定义了将 HTTP 请求映射到处理器的契约。Spring Boot 中默认注册了 5 个 HandlerMapping 实现,按优先级排序。
public interface HandlerMapping {
// 返回处理器执行链(包含处理器和拦截器)
@Nullable
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
// 优先级常量(值越小优先级越高)
int BEST_MATCHING_HANDLER_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingHandler";
}默认注册的 5 个 HandlerMapping 及其优先级:
| 排序 | HandlerMapping | 说明 | 优先级顺序值 |
|---|---|---|---|
| 1 | RequestMappingHandlerMapping | @RequestMapping 注解映射(最高优先级) | 0 |
| 2 | WelcomePageHandlerMapping | Spring Boot 首页 /** → index.html | 1 |
| 3 | BeanNameUrlHandlerMapping | Bean 名称以 / 开头的 URL 映射 | 2 |
| 4 | RouterFunctionMapping | 函数式端点(WebFlux 风格) | 3 |
| 5 | SimpleUrlHandlerMapping | 显式 URL 模式映射(最低优先级) | Integer.MAX_VALUE |
注册和排序代码:
// WebMvcAutoConfiguration 中的注册
@Configuration(proxyBeanMethods = false)
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration {
@Bean
@Primary
@Override
public RequestMappingHandlerMapping requestMappingHandlerMapping(...) {
RequestMappingHandlerMapping mapping = super.requestMappingHandlerMapping(...);
mapping.setOrder(0); // 最高优先级
return mapping;
}
}
// BeanNameUrlHandlerMapping 的默认 order
public class BeanNameUrlHandlerMapping extends AbstractUrlHandlerMapping {
// 构造器中设置 order = 2
public BeanNameUrlHandlerMapping() {
setOrder(2);
}
}DispatcherServlet.doDispatch() 中的查找:
// DispatcherServlet.doDispatch()
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) {
HttpServletRequest processedRequest = request;
HandlerExecutionChain mappedHandler = null;
// 遍历所有 HandlerMapping 查找匹配的处理器
mappedHandler = getHandler(processedRequest);
// 未找到 → 抛出 404
if (mappedHandler == null) {
noHandlerFound(processedRequest, response);
return;
}
// 查找适配的 HandlerAdapter
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
// ...
}
// 从 HandlerMapping 列表中查找处理器
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
// 遍历 handlerMappings(按 @Order 排序后的列表)
for (HandlerMapping mapping : this.handlerMappings) {
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler; // 返回第一个匹配的
}
}
return null;
}查找策略:按 order 值升序遍历,返回第一个匹配的 HandlerMapping,短路优先。
2. AbstractHandlerMethodMapping.registerMapping() 注册 @RequestMapping
AbstractHandlerMethodMapping 是所有基于方法级别的 HandlerMapping 的基类,负责将 @RequestMapping 注解的方法注册到映射注册表中。
public abstract class AbstractHandlerMethodMapping<T> implements HandlerMapping {
// 内部映射注册表
private final MappingRegistry mappingRegistry = new MappingRegistry();
// 检测并注册所有处理器 Bean 中的映射方法
@Override
public void afterPropertiesSet() {
initHandlerMethods(); // 扫描所有 Bean → 检测 @RequestMapping → 注册
}
// 扫描所有 Bean,查找映射方法
protected void initHandlerMethods() {
// 1. 获取容器中所有的 Bean 名称
String[] beanNames = obtainApplicationContext()
.getBeanNamesForType(Object.class);
for (String beanName : beanNames) {
// 2. 检查 Bean 中是否包含映射方法(@RequestMapping)
if (isHandler(getBeanType(beanName))) {
// 3. 注册该 Bean 的所有映射方法
detectHandlerMethods(beanName);
}
}
}
// 检测并注册单个 Bean 中的映射方法
protected void detectHandlerMethods(Object handler) {
// 1. 获取 Bean 的 Class
Class<?> handlerType = getHandlerType(handler);
// 2. 选中所有带有 @RequestMapping 的方法
Map<Method, T> methods = MethodIntrospector.selectMethods(handlerType,
(MethodIntrospector.MetadataLookup<T>) method -> getMappingForMethod(method, handlerType));
// 3. 注册每个映射
methods.forEach((method, mapping) -> {
// 创建 HandlerMethod(包装了 Bean 和方法)
Method invocableMethod = AopUtils.selectInvocableMethod(method, handlerType);
registerHandlerMethod(handler, invocableMethod, mapping);
});
}
// 注册到 MappingRegistry
protected void registerHandlerMethod(Object handler, Method method, T mapping) {
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
this.mappingRegistry.register(mapping, handlerMethod, directHandlerMethod, beanName);
}
}MappingRegistry 的内部结构:
class MappingRegistry {
// 注册表:RequestMappingInfo → HandlerMethod 的映射
private final Map<T, MappingRegistration<T>> registry = new HashMap<>();
// URL 查找表:URL 路径 → 对应的 RequestMappingInfo 集合
private final MultiValueMap<String, T> urlLookup = new LinkedMultiValueMap<>();
// 名称查找表:HandlerMethod 名称 → RequestMappingInfo
private final Map<String, List<HandlerMethod>> nameLookup = new ConcurrentHashMap<>();
// CORS 查找表:URL → CorsConfiguration
private final Map<String, CorsConfiguration> corsLookup = new ConcurrentHashMap<>();
// 注册一个映射
public void register(T mapping, HandlerMethod handlerMethod,
Method directHandlerMethod, String beanName) {
// 1. 添加到 registry
this.registry.put(mapping,
new MappingRegistration<>(mapping, handlerMethod, directHandlerMethod, beanName));
// 2. 添加到 urlLookup(提取 URL 路径模式)
for (String path : getMappingPathPatterns(mapping)) {
this.urlLookup.add(path, mapping);
}
// 3. 添加到 nameLookup(用于跨控制器 URL 引用)
String name = handlerMethod.getBeanName() + "#" + handlerMethod.getMethod().getName();
this.nameLookup.computeIfAbsent(name, k -> new ArrayList<>()).add(handlerMethod);
// 4. 添加到 corsLookup
CorsConfiguration corsConfig = getCorsConfiguration(handlerMethod);
if (corsConfig != null) {
for (String path : getMappingPathPatterns(mapping)) {
this.corsLookup.put(path, corsConfig);
}
}
}
}注册流程:
@RequestMapping("/users") + @GetMapping("/{id}")
↓
detectHandlerMethods(UserController.class)
↓
getMappingForMethod() → 创建 RequestMappingInfo
↓
registerHandlerMethod()
↓
MappingRegistry.register()
↓
├── registry.put(info, registration) ← 主注册表
├── urlLookup.add("/users/{id}", info) ← URL 索引
├── nameLookup.add("userController#getUser", method) ← 名称索引
└── corsLookup.put("/users/{id}", config) ← CORS 配置3. RequestMappingInfo 的 6 个条件
RequestMappingInfo 封装了 @RequestMapping 注解的所有条件,负责与 HTTP 请求进行匹配。
public final class RequestMappingInfo implements RequestCondition<RequestMappingInfo> {
// 6 个匹配条件
private final PatternsRequestCondition patternsCondition; // 路径模式
private final RequestMethodsRequestCondition methodsCondition; // HTTP 方法
private final ParamsRequestCondition paramsCondition; // 请求参数
private final HeadersRequestCondition headersCondition; // 请求头
private final ConsumesRequestCondition consumesCondition; // 请求体类型(Content-Type)
private final ProducesRequestCondition producesCondition; // 响应体类型(Accept)
@Override
public RequestMappingInfo getMatchingCondition(HttpServletRequest request) {
// 1. 匹配路径
PatternsRequestCondition patterns = this.patternsCondition.getMatchingCondition(request);
if (patterns == null) return null; // 路径不匹配
// 2. 匹配 HTTP 方法
RequestMethodsRequestCondition methods = this.methodsCondition.getMatchingCondition(request);
if (methods == null) return null; // 方法不匹配
// 3. 匹配请求参数
ParamsRequestCondition params = this.paramsCondition.getMatchingCondition(request);
if (params == null) return null; // 参数不匹配
// 4. 匹配请求头
HeadersRequestCondition headers = this.headersCondition.getMatchingCondition(request);
if (headers == null) return null; // 头不匹配
// 5. 匹配 Content-Type
ConsumesRequestCondition consumes = this.consumesCondition.getMatchingCondition(request);
if (consumes == null) return null; // Content-Type 不匹配
// 6. 匹配 Accept
ProducesRequestCondition produces = this.producesCondition.getMatchingCondition(request);
if (produces == null) return null; // Accept 不匹配
return new RequestMappingInfo(patterns, methods, params, headers, consumes, produces,
this.name, this.customCondition);
}
// 比较两个匹配结果的优先级(越精确优先级越高)
@Override
public int compareTo(RequestMappingInfo other, HttpServletRequest request) {
int result = patternsCondition.compareTo(other.patternsCondition, request);
if (result != 0) return result;
result = paramsCondition.compareTo(other.paramsCondition, request);
if (result != 0) return result;
result = headersCondition.compareTo(other.headersCondition, request);
if (result != 0) return result;
result = consumesCondition.compareTo(other.consumesCondition, request);
if (result != 0) return result;
result = producesCondition.compareTo(other.producesCondition, request);
if (result != 0) return result;
result = methodsCondition.compareTo(other.methodsCondition, request);
return result;
}
}6 个条件匹配的注解来源:
| 条件 | 注解属性 | 示例 |
|---|---|---|
patternsCondition | @RequestMapping("/users/{id}") | /users/123 匹配 |
methodsCondition | @GetMapping / @RequestMapping(method=GET) | GET 请求匹配 |
paramsCondition | @RequestMapping(params="action=create") | ?action=create 匹配 |
headersCondition | @RequestMapping(headers="X-API-Version=1") | 请求头包含匹配 |
consumesCondition | @PostMapping(consumes="application/json") | Content-Type: application/json 匹配 |
producesCondition | @GetMapping(produces="application/json") | Accept: application/json 匹配 |
路径匹配优先级:
① /user/{id}/detail ← 精确路径(最高)
② /user/{id}/* ← 通配符
③ /user/{id} ← 路径变量
④ /user/** ← 双通配符
⑤ /** ← 全匹配(最低)4. HandlerExecutionChain 的拦截器链
HandlerExecutionChain 包装了处理器和拦截器链,提供三阶段拦截能力。
public class HandlerExecutionChain {
private final Object handler; // 处理器(HandlerMethod / Controller)
private HandlerInterceptor[] interceptors; // 拦截器数组
private List<HandlerInterceptor> interceptorList; // 拦截器列表
private int interceptorIndex = -1; // 已执行 preHandle 的索引
// 第一阶段:前置处理(在 handler 执行前调用)
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response)
throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (interceptors == null) return true;
for (int i = 0; i < interceptors.length; i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(request, response, this.handler)) {
// preHandle 返回 false → 触发已执行拦截器的 afterCompletion
triggerAfterCompletion(request, response, null);
return false; // 请求终止
}
this.interceptorIndex = i; // 记录已执行的索引
}
return true; // 所有拦截器通过 → 继续执行
}
// 第二阶段:后置处理(在 handler 执行后、视图渲染前调用)
void applyPostHandle(HttpServletRequest request, HttpServletResponse response,
@Nullable ModelAndView mv) throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (interceptors == null) return;
// 逆序遍历
for (int i = interceptors.length - 1; i >= 0; i--) {
interceptors[i].postHandle(request, response, this.handler, mv);
}
}
// 第三阶段:完成处理(无论是否异常,在视图渲染后调用)
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response,
@Nullable Exception ex) {
HandlerInterceptor[] interceptors = getInterceptors();
if (interceptors == null) return;
// 逆序执行(只执行 preHandle 通过的拦截器)
for (int i = this.interceptorIndex; i >= 0; i--) {
interceptors[i].afterCompletion(request, response, this.handler, ex);
}
}
}三阶段调用时序:
① applyPreHandle()
for (i=0; i<n; i++) interceptors[i].preHandle()
任一返回 false → 请求终止,triggerAfterCompletion()
↓ 全部通过
② handler.handle(request, response) ← 执行 Controller 方法
↓ 执行完成
③ applyPostHandle()
for (i=n-1; i>=0; i--) interceptors[i].postHandle()
↓ 视图渲染
④ triggerAfterCompletion()
for (i=interceptorIndex; i>=0; i--) interceptors[i].afterCompletion()interceptorIndex 的作用:确保只有已通过 preHandle 的拦截器才会执行 afterCompletion(未触发 preHandle 或 preHandle 返回 false 的拦截器不会执行 afterCompletion)。
5. HandlerAdapter.supports() 的匹配逻辑
HandlerAdapter 负责调用不同类型处理器,supports() 方法判断适配器是否能处理给定的处理器。
public interface HandlerAdapter {
// 判断是否支持指定的 handler
boolean supports(Object handler);
// 调用处理器并返回 ModelAndView
@Nullable
ModelAndView handle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception;
}
// DispatcherServlet 中查找适配的 HandlerAdapter
private HandlerAdapter getHandlerAdapter(Object handler) {
// 遍历所有 HandlerAdapter
for (HandlerAdapter adapter : this.handlerAdapters) {
if (adapter.supports(handler)) {
return adapter; // 返回第一个匹配的
}
}
throw new ServletException("No adapter for handler [" + handler + "]");
}4 个内置 HandlerAdapter 的匹配规则:
| HandlerAdapter | supports() 判断 | 说明 |
|---|---|---|
RequestMappingHandlerAdapter | handler instanceof HandlerMethod | 处理 @RequestMapping 注解方法 |
SimpleControllerHandlerAdapter | handler instanceof Controller | 处理实现 Controller 接口的类 |
HttpRequestHandlerAdapter | handler instanceof HttpRequestHandler | 处理 HttpRequestHandler(资源请求) |
SimpleServletHandlerAdapter | handler instanceof Servlet | 处理 Servlet 实例 |
// RequestMappingHandlerAdapter
public class RequestMappingHandlerAdapter extends AbstractHandlerMethodAdapter {
@Override
protected boolean supportsInternal(HandlerMethod handlerMethod) {
return true; // 所有 HandlerMethod 都支持
}
}
// SimpleControllerHandlerAdapter
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
@Override
public boolean supports(Object handler) {
return (handler instanceof Controller); // 必须是 Controller 接口实现
}
@Override
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
return ((Controller) handler).handleRequest(request, response);
}
}
// HttpRequestHandlerAdapter
public class HttpRequestHandlerAdapter implements HandlerAdapter {
@Override
public boolean supports(Object handler) {
return (handler instanceof HttpRequestHandler);
}
}6. InvocableHandlerMethod.invokeForRequest() 参数解析
InvocableHandlerMethod 负责调用 Controller 方法并解析方法参数。
public class InvocableHandlerMethod extends HandlerMethod {
private HandlerMethodArgumentResolverComposite argumentResolvers;
@Nullable
public Object invokeForRequest(HttpServletRequest request,
ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
// 1. 解析所有方法参数
Object[] args = getMethodArgumentValues(request, mavContainer, providedArgs);
// 2. 调用目标方法
return doInvoke(args);
}
// 解析方法参数
protected Object[] getMethodArgumentValues(HttpServletRequest request,
ModelAndViewContainer mavContainer, Object... providedArgs) throws Exception {
// 1. 获取方法参数数组
MethodParameter[] parameters = getMethodParameters();
Object[] args = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++) {
MethodParameter parameter = parameters[i];
// 2. 检查是否由调用者显式提供(providedArgs)
args[i] = findProvidedArgument(parameter, providedArgs);
if (args[i] != null) continue;
// 3. 遍历参数解析器链
if (this.argumentResolvers.supportsParameter(parameter)) {
try {
// 4. 使用匹配的解析器解析参数
args[i] = this.argumentResolvers.resolveArgument(
parameter, mavContainer, request, this.argumentResolvers);
} catch (Exception ex) {
// 参数解析失败
throw new MessagingException("Could not resolve parameter " +
parameter.getParameterIndex(), ex);
}
}
}
return args;
}
}ServletInvocableHandlerMethod——InvocableHandlerMethod 的子类:
public class ServletInvocableHandlerMethod extends InvocableHandlerMethod {
private HandlerMethodReturnValueHandlerComposite returnValueHandlers;
@Override
public void invokeAndHandle(ServletWebRequest webRequest,
ModelAndViewContainer mavContainer,
Object... providedArgs) throws Exception {
// 1. 调用父类的 invokeForRequest → 解析参数 + 执行方法
Object returnValue = invokeForRequest(webRequest, mavContainer, providedArgs);
// 2. 处理返回值
this.returnValueHandlers.handleReturnValue(
returnValue, getReturnValueType(returnValue), mavContainer, webRequest);
}
}参数解析流程:
Controller 方法: public User getUser(@PathVariable Long id, @RequestParam String name)
↓
getMethodArgumentValues()
↓
参数 0: @PathVariable Long id
├── argumentResolvers.supportsParameter(param0) → true
└── argumentResolvers.resolveArgument(param0)
→ PathVariableMethodArgumentResolver.resolveArgument()
→ 从 URL 路径中提取 id 值
↓
参数 1: @RequestParam String name
├── argumentResolvers.supportsParameter(param1) → true
└── argumentResolvers.resolveArgument(param1)
→ RequestParamMethodArgumentResolver.resolveArgument()
→ 从请求参数中提取 name 值
↓
args = [123L, "张三"]
↓
doInvoke(args) → getUser(123L, "张三")7. HandlerMethodArgumentResolver 的 25+ 种实现
HandlerMethodArgumentResolver 是参数解析的核心 SPI,Spring MVC 内置了 25+ 种实现。
public interface HandlerMethodArgumentResolver {
// 判断是否支持解析指定的参数
boolean supportsParameter(MethodParameter parameter);
// 解析参数值
@Nullable
Object resolveArgument(MethodParameter parameter,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory) throws Exception;
}分类一览:
| 类别 | 实现类 | 支持注解/类型 |
|---|---|---|
| 请求参数 | RequestParamMethodArgumentResolver | @RequestParam、@RequestPart、简单类型 |
| 路径变量 | PathVariableMethodArgumentResolver | @PathVariable |
| 请求头 | RequestHeaderMethodArgumentResolver | @RequestHeader |
| Cookie | CookieValueMethodArgumentResolver | @CookieValue |
| 矩阵变量 | MatrixVariableMethodArgumentResolver | @MatrixVariable |
| 请求体 | RequestResponseBodyMethodProcessor | @RequestBody |
| 模型属性 | ModelAttributeMethodProcessor | @ModelAttribute |
| 错误信息 | ErrorsMethodArgumentResolver | Errors、BindingResult |
| Session | SessionStatusMethodArgumentResolver | SessionStatus |
| URI 信息 | UriComponentsBuilderMethodArgumentResolver | UriComponentsBuilder |
| Principal | AuthenticationPrincipalArgumentResolver | @AuthenticationPrincipal |
| Session 属性 | SessionAttributeMethodArgumentResolver | @SessionAttribute |
| 请求属性 | RequestAttributeMethodArgumentResolver | @RequestAttribute |
| 重定向属性 | RedirectAttributesMethodArgumentResolver | RedirectAttributes |
| 时区 | ZoneIdMethodArgumentResolver | ZoneId、TimeZone |
| Locale | LocaleContextMethodArgumentResolver | Locale |
| Reader/Stream | RequestPartMethodArgumentResolver | MultipartFile、Part |
| CompletableFuture | AsyncTaskMethodArgumentResolver | Callable、WebAsyncTask |
关键实现的 supportsParameter() 逻辑:
// PathVariableMethodArgumentResolver
public class PathVariableMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
// 检查参数上是否有 @PathVariable 注解
if (!parameter.hasParameterAnnotation(PathVariable.class)) {
return false;
}
// 不支持 Map(有专门的 Map 处理方式)
if (Map.class.isAssignableFrom(parameter.nestedIfOptional().getNestedParameterType())) {
PathVariable ann = parameter.getParameterAnnotation(PathVariable.class);
return ann != null && !StringUtils.hasText(ann.value());
}
return true;
}
}
// RequestResponseBodyMethodProcessor(处理 @RequestBody + 处理 @ResponseBody 返回值)
public class RequestResponseBodyMethodProcessor
extends AbstractMessageConverterMethodProcessor {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(RequestBody.class);
}
}
// RequestParamMethodArgumentResolver
public class RequestParamMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
// 1. 有 @RequestParam 注解
if (parameter.hasParameterAnnotation(RequestParam.class)) return true;
// 2. 有多部分文件注解
if (parameter.hasParameterAnnotation(RequestPart.class)) return false;
// 3. 简单类型(int、String、Long 等)且无其他注解 → 也处理
if (parameter.nestedIfOptional().getNestedParameterType() == MultipartFile.class) return true;
return BeanUtils.isSimpleProperty(parameter.nestedIfOptional().getNestedParameterType());
}
}解析器链的匹配过程:
public class HandlerMethodArgumentResolverComposite
implements HandlerMethodArgumentResolver {
private final List<HandlerMethodArgumentResolver> argumentResolvers;
@Override
public Object resolveArgument(MethodParameter parameter, ...) throws Exception {
// 查找匹配的解析器
HandlerMethodArgumentResolver resolver = getArgumentResolver(parameter);
if (resolver == null) {
throw new IllegalArgumentException("不支持参数类型 [" +
parameter.getParameterType().getName() + "]");
}
return resolver.resolveArgument(parameter, mavContainer, webRequest, binderFactory);
}
private HandlerMethodArgumentResolver getArgumentResolver(MethodParameter parameter) {
// 遍历解析器列表,返回第一个 supportsParameter 返回 true 的
for (HandlerMethodArgumentResolver resolver : this.argumentResolvers) {
if (resolver.supportsParameter(parameter)) {
return resolver;
}
}
return null;
}
}8. HandlerMethodReturnValueHandler 的 10+ 种实现
HandlerMethodReturnValueHandler 负责处理 Controller 方法的返回值。
public interface HandlerMethodReturnValueHandler {
// 判断是否支持处理该返回值类型
boolean supportsReturnType(MethodParameter returnType);
// 处理返回值
void handleReturnValue(@Nullable Object returnValue,
MethodParameter returnType,
ModelAndViewContainer mavContainer,
NativeWebRequest webRequest) throws Exception;
}内置 10+ 种实现:
| ReturnValueHandler | supportsReturnType() | 处理方式 |
|---|---|---|
ModelAndViewMethodReturnValueHandler | ModelAndView.class | 设置 ModelAndViewContainer.setViewName() |
ModelMethodProcessor | Model.class | 将返回值添加到 Model |
ViewMethodReturnValueHandler | View.class | 设置 View 对象 |
ResponseBodyHandlerMethodReturnValueHandler | @ResponseBody | 使用 HttpMessageConverter 写入响应体 |
ViewNameMethodReturnValueHandler | String.class / void.class | 字符串作为视图名 |
MapMethodProcessor | Map.class | 添加到 Model 的属性映射 |
ModelAttributeMethodProcessor | @ModelAttribute | 添加到 Model |
StreamingResponseBodyReturnValueHandler | StreamingResponseBody.class | 异步流式写入 |
ResponseEntityHandlerMethodReturnValueHandler | ResponseEntity.class | 写入 HTTP 状态 + 头 + 体 |
DeferredResultMethodReturnValueHandler | DeferredResult.class | 异步 DeferredResult |
CallableMethodReturnValueHandler | Callable.class | 异步 Callable |
HttpHeadersReturnValueHandler | HttpHeaders.class | 仅写入响应头 |
ResponseBodyHandlerMethodReturnValueHandler 的核心实现:
public class ResponseBodyHandlerMethodReturnValueHandler
extends AbstractMessageConverterMethodProcessor {
@Override
public boolean supportsReturnType(MethodParameter returnType) {
return (returnType.hasMethodAnnotation(ResponseBody.class) ||
returnType.hasMethodAnnotation(ResponseEntity.class));
}
@Override
public void handleReturnValue(@Nullable Object returnValue,
MethodParameter returnType, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest) throws Exception {
// 1. 标记请求已处理完毕(跳过视图渲染)
mavContainer.setRequestHandled(true);
// 2. 空值检查
if (returnValue == null) return;
// 3. 使用 HttpMessageConverter 写入响应
try (ServerHttpResponse outputMessage = createOutputMessage(webRequest)) {
writeWithMessageConverters(returnValue, returnType, outputMessage);
}
}
}ServletInvocableHandlerMethod 中返回值处理流程:
Controller 执行完成 → 返回 Object
↓
returnValueHandlers.handleReturnValue(returnValue, returnType, mavContainer, webRequest)
↓
遍历所有 ReturnValueHandler,找到 supportsReturnType 返回 true 的
↓
① 如果是 @ResponseBody → ResponseBodyHandlerMethodReturnValueHandler
→ mavContainer.setRequestHandled(true)
→ writeWithMessageConverters(returnValue)
↓
② 如果是 String → ViewNameMethodReturnValueHandler
→ mavContainer.setViewName(returnValue)
↓
③ 如果是 ModelAndView → ModelAndViewMethodReturnValueHandler
→ mavContainer.setViewName(mav.getViewName())
→ mavContainer.addAllAttributes(mav.getModel())
↓
④ 如果是 ResponseEntity → ResponseEntityHandlerMethodReturnValueHandler
→ 设置 status / headers / body
→ writeWithMessageConverters(body)9. WelcomePageHandlerMapping 的 /** 映射
WelcomePageHandlerMapping 是 Spring Boot 特有的 HandlerMapping,负责将首页请求映射到 index.html。
public class WelcomePageHandlerMapping extends AbstractUrlHandlerMapping {
private static final List<String> STATIC_CONTENT_LOCATIONS =
List.of("/", "/static/", "/public/", "/resources/", "/META-INF/resources/");
public WelcomePageHandlerMapping(TemplateAvailabilityProviders templateAvailabilityProviders,
ApplicationContext applicationContext,
ResourceLoader resourceLoader,
String staticPathPattern) {
// 1. 查找欢迎页
String welcomePage = getWelcomePage(applicationContext, resourceLoader, templateAvailabilityProviders);
if (welcomePage != null) {
// 2. 注册 /** 映射到 ParameterizableViewController
ParameterizableViewController controller = new ParameterizableViewController();
controller.setViewName(welcomePage);
// 3. 设置 order = 1(仅次于 RequestMappingHandlerMapping)
setOrder(1);
// 4. 注册映射路径
registerHandler("/", controller); // 映射 / → index.html
registerHandler("/index.html", controller);
}
}
private String getWelcomePage(ApplicationContext context, ResourceLoader loader,
TemplateAvailabilityProviders templateProviders) {
// 1. 检查模板引擎(Thymeleaf 等)
for (String location : STATIC_CONTENT_LOCATIONS) {
TemplateAvailabilityProvider provider = templateProviders.getProvider(
location + "index", context);
if (provider != null) return "index";
}
// 2. 检查静态资源目录下的 index.html
for (String location : STATIC_CONTENT_LOCATIONS) {
Resource resource = loader.getResource("classpath:" + location + "index.html");
if (resource.exists()) {
return "forward:" + location + "index.html";
}
}
return null;
}
}执行流程:
GET http://localhost:8080/
↓
DispatcherServlet.getHandler()
↓
① RequestMappingHandlerMapping(order=0) → 没有匹配(无 @RequestMapping("/"))
↓
② WelcomePageHandlerMapping(order=1) → 匹配 / → handler = ParameterizableViewController
↓
③ HandlerAdapter.handle() → ParameterizableViewController.handleRequest()
↓
④ 返回 ModelAndView(viewName="forward:/static/index.html")
↓
⑤ 视图解析 → 渲染 index.html优先级设计:WelcomePageHandlerMapping(order=1) 低于 RequestMappingHandlerMapping(order=0),确保用户显式定义的 @RequestMapping("/") 优先级更高。
10. SimpleControllerHandlerAdapter 处理 Controller 类
SimpleControllerHandlerAdapter 适配实现 Controller 接口的传统控制器。
@FunctionalInterface
public interface Controller {
// 处理请求并返回 ModelAndView
@Nullable
ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
throws Exception;
}SimpleControllerHandlerAdapter 的工作方式:
public class SimpleControllerHandlerAdapter implements HandlerAdapter {
@Override
public boolean supports(Object handler) {
// 仅支持实现了 Controller 接口的处理器
return (handler instanceof Controller);
}
@Override
@Nullable
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
// 直接调用 Controller.handleRequest()
return ((Controller) handler).handleRequest(request, response);
}
}对比:传统 Controller 接口 vs @RequestMapping 方法:
// 传统方式:实现 Controller 接口(一个类处理一个 URL)
public class OldSchoolController implements Controller {
@Override
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) {
// 手动处理请求
String name = request.getParameter("name");
Map<String, Object> model = new HashMap<>();
model.put("message", "Hello " + name);
return new ModelAndView("greeting", model);
}
}
// 现代方式:@RequestMapping 注解(一个类处理多个 URL)
@Controller
public class ModernController {
@GetMapping("/greeting")
public String greeting(@RequestParam String name, Model model) {
model.addAttribute("message", "Hello " + name);
return "greeting";
}
@GetMapping("/users")
@ResponseBody
public List<User> listUsers() {
return userService.findAll();
}
}适配器模式在 Spring MVC 中的应用:
DispatcherServlet → 查找 HandlerAdapter → 调用 handle()
不同处理器需要不同的适配器:
HandlerMethod (@RequestMapping) ──→ RequestMappingHandlerAdapter
Controller 接口实现 ──→ SimpleControllerHandlerAdapter
HttpRequestHandler (资源请求) ──→ HttpRequestHandlerAdapter
Servlet 实例 ──→ SimpleServletHandlerAdapter总结
HandlerMapping / HandlerAdapter / Interceptor 族的 10 个细节点总结如下:
| # | 细节点 | 核心类/机制 |
|---|---|---|
| ① | HandlerMapping 的 5 个实现 | BeanNameUrlHandlerMapping(最低)→ SimpleUrlHandlerMapping → WelcomePageHandlerMapping → RouterFunctionMapping → RequestMappingHandlerMapping(最高) |
| ② | AbstractHandlerMethodMapping.registerMapping() 注册 | HandlerMethod 包装 → MappingRegistry.register() → urlLookup / nameLookup / corsLookup |
| ③ | RequestMappingInfo 的 6 个条件 | patternsCondition / methodsCondition / paramsCondition / headersCondition / consumesCondition / producesCondition |
| ④ | HandlerExecutionChain 的拦截器链 | applyPreHandle() → 执行 handler → applyPostHandle() → triggerAfterCompletion() 三阶段 |
| ⑤ | HandlerAdapter.supports() 的匹配逻辑 | RequestMappingHandlerAdapter → instanceof HandlerMethod;SimpleControllerHandlerAdapter → instanceof Controller |
| ⑥ | InvocableHandlerMethod.invokeForRequest() 参数解析 | getMethodArgumentValues() → argumentResolvers.supportsParameter() + resolveArgument() |
| ⑦ | HandlerMethodArgumentResolver 的 25+ 种实现 | PathVariableMethodArgumentResolver / RequestParamMethodArgumentResolver / RequestResponseBodyMethodProcessor 等 |
| ⑧ | HandlerMethodReturnValueHandler 的 10+ 种实现 | ResponseBodyHandlerMethodReturnValueHandler / ViewNameMethodReturnValueHandler / ModelAndViewMethodReturnValueHandler 等 |
| ⑨ | WelcomePageHandlerMapping 的 /** 映射 | Spring Boot 自动将 index.html 映射到 /,order=1 仅次于 @RequestMapping |
| ⑩ | SimpleControllerHandlerAdapter 处理 Controller 类 | Controller.handleRequest() → ModelAndView 返回,适配器模式 |