源码剖析-【获取handler及HandlerAdapter】
1.getHandler方法以及HandlerExecutionChain简析
/**
* 返回当前请求的HandlerExecutionChain
*
* Return the HandlerExecutionChain for this request.
* <p>Tries all handler mappings in order.
* @param request current HTTP request
* @return the HandlerExecutionChain, or {@code null} if no handler could be found
*/
@Nullable
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
if (this.handlerMappings != null) {
for (HandlerMapping mapping : this.handlerMappings) {
HandlerExecutionChain handler = mapping.getHandler(request);
if (handler != null) {
return handler;
}
}
}
return null;
}
该方法并没有返回一个具体的Handler,而是返回了HandlerExecutionChain对象。HandlerExecutionChain是Handler执行链,包括Handler本身和HandlerInterceptor拦截器。其在HandlerExecutionChain中的定义如下:
// Controller本身实例
private final Object handler;
// 拦截器数组
@Nullable
private HandlerInterceptor[] interceptors;
// 拦截器集合
@Nullable
private List<HandlerInterceptor> interceptorList;
其中handler即Controller本身实例,HandlerInterceptor是一个拦截器,其可以在SpringMVC的请求过过程中在不同的时机回调不同的接口。HandlerInterceptor接口的定义如下:
public interface HandlerInterceptor {
/**
* 拦截处理程序的执行。在HandlerMapping确定适当的处理程序对象之后调用,但在HandlerAdapter调用处理程序之前调用。
*
* DispatcherServlet在执行链中处理一个处理程序,该处理程序由任意数量的拦截器组成,处理程序本身位于执行链的末端。
* 使用此方法,每个拦截器可以决定中止执行链,通常是发送HTTP错误或编写自定义响应。
*
* 异步请求处理需要特殊考虑。 默认返回true
*
* 如果执行链应该继续下一个拦截器或处理程序本身,则返回@return {@code true}。
* 否则,DispatcherServlet假设这个拦截器已经处理了响应本身。
*
*/
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
return true;
}
/**
* 拦截处理程序的执行。在HandlerAdapter实际调用处理程序之后调用,但在DispatcherServlet呈现视图之前调用。
* 可以通过给定的ModelAndView向视图公开其他模型对象。
*/
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable ModelAndView modelAndView) throws Exception {
}
/**
* 请求处理完成后的回调,即呈现视图后的回调。将在处理程序执行的任何结果上调用,因此允许吗
*/
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
@Nullable Exception ex) throws Exception {
}
}
2.getHandler方法详解
通过上面的分析,已经了解了HandlerExecutionChain的组成。接下来看具体的获取HandlerExecutionChain的过程。Spring会循环所有注册的HandlerMapping并返回第一个匹配的HandlerExecutionChain的。
下面以AbstractHandlerMapping为例来分析一下其具体的获取过程:
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
// 1.获取当前请求对应的handler
Object handler = getHandlerInternal(request);
// 未能获取到对应的handler,则使用默认的defaultHandler
if (handler == null) {
handler = getDefaultHandler();
}
// 两者同时未找到,则返回null
if (handler == null) {
return null;
}
// Bean name or resolved handler?
// 2.如果获取到的handler是String类型,则以handler为beanName,从IOC容器中获取其实例
if (handler instanceof String) {
String handlerName = (String) handler;
handler = obtainApplicationContext().getBean(handlerName);
}
// 3.根据handler和request获取对应的HandlerExecutionChain实例
// 会将handler封装到HandlerExecutionChain对象中,
// 并将系统和自定义的拦截器加入到HandlerExecutionChain中
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (logger.isTraceEnabled()) {
logger.trace("Mapped to " + handler);
}
else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) {
logger.debug("Mapped to " + executionChain.getHandler());
}
if (CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}
来看其比较核心的方法:
2.1 getHandlerInternal
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
// 解析请求路径
String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
// 加只读锁
this.mappingRegistry.acquireReadLock();
try {
// 根据请求路径和当前请求对象,获取最佳匹配的HandlerMethod
HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
// 获取当前Controller的实例,并将获取到的实例封装至HandlerMethod对象中
return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
}
finally {
// 释放只读锁
this.mappingRegistry.releaseReadLock();
}
}
如果该方法未能获取到HandlerMethod,则使用默认的Handler。注意:defaultHandler默认为空,需要自己去配置。
2.2 getHandlerExecutionChain
protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
if (interceptor instanceof MappedInterceptor) {
MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
chain.addInterceptor(mappedInterceptor.getInterceptor());
}
}
else {
chain.addInterceptor(interceptor);
}
}
return chain;
}
将上一步获取到的handler转化为HandlerExecutionChain对象,并循环所有注册的HandlerInterceptor并将其加入到HandlerExecutionChain链中。
3.getHandlerAdapter 获取HandlerAdapter
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 [" + handler +
"]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
}
4.applyPreHandle 应用前置拦截器
/**
* 调用注册的HandlerInterceptor拦截器中的preHandle方法
*
* 1.preHandle:HandlerMapping确定适当的处理程序对象之后,在HandlerAdapter调用处理程序之前调用
* 2.preHandle默认返回true,如果返回true,则DispatcherServlet假设这个拦截器已经处理了响应本身。
*
* Apply preHandle methods of registered interceptors.
* @return {@code true} if the execution chain should proceed with the
* next interceptor or the handler itself. Else, DispatcherServlet assumes
* that this interceptor has already dealt with the response itself.
*/
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
HandlerInterceptor[] interceptors = getInterceptors();
if (!ObjectUtils.isEmpty(interceptors)) {
for (int i = 0; i < interceptors.length; i++) {
HandlerInterceptor interceptor = interceptors[i];
if (!interceptor.preHandle(request, response, this.handler)) {
triggerAfterCompletion(request, response, null);
return false;
}
this.interceptorIndex = i;
}
}
return true;
}
这里要注意一下applyPreHandle的返回值,如果为true的话则表示DispatcherServlet已经完成了本次请求处理。
程序再往下执行就要真正开始开始处理Controller了