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