目录
推荐博客
给大家推荐个靠谱的公众号程序员探索之路,大家一起加油
引言
主要介绍一下HandlerMapping的作用以及继承关系,之前也介绍过DispatcherServlet会进行HandlerMapping的初始化,之后会详细的介绍每一种源码
上一篇
SpringMVC(六)-----拦截器调用时机
https://blog.csdn.net/yueloveme/article/details/89843985
HandlerMapping
HandlerMapping的作用就是为每个请求找到合适的处理器Handler,简单的理解就是维护了一个url到Controller关系的map结构,在代码层面看到的结果就是请求获得执行链(HandlerExecutionChain),接口中只有一个方法获取执行链
/**
* Return a handler and any interceptors for this request. The choice may be made
* on request URL, session state, or any factor the implementing class chooses.
* <p>The returned HandlerExecutionChain contains a handler Object, rather than
* even a tag interface, so that handlers are not constrained in any way.
* For example, a HandlerAdapter could be written to allow another framework's
* handler objects to be used.
* <p>Returns {@code null} if no match was found. This is not an error.
* The DispatcherServlet will query all registered HandlerMapping beans to find
* a match, and only decide there is an error if none can find a handler.
* @param request current HTTP request
* @return a HandlerExecutionChain instance containing handler object and
* any interceptors, or {@code null} if no mapping found
* @throws Exception if there is an internal error
*/
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
类关系图
AbstractHandlerMapping
/**
* Look up a handler for the given request, falling back to the default
* handler if no specific one is found.
* @param request current HTTP request
* @return the corresponding handler instance, or the default handler
* @see #getHandlerInternal
*/
实现getHandler方法
@Override
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws
Exception {
Object handler = getHandlerInternal(request);
if (handler == null) {
handler = getDefaultHandler();
}
if (handler == null) {
return null;
}
// Bean name or resolved handler?
if (handler instanceof String) {
String handlerName = (String) handler;
handler = getApplicationContext().getBean(handlerName);
}
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler,
request);
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;
}
/**
* Build a {@link HandlerExecutionChain} for the given handler, including
* applicable interceptors.
* <p>The default implementation builds a standard {@link HandlerExecutionChain}
* with the given handler, the handler mapping's common interceptors, and any
* {@link MappedInterceptor}s matching to the current request URL. Interceptors
* are added in the order they were registered. Subclasses may override this
* in order to extend/rearrange the list of interceptors.
* <p><b>NOTE:</b> The passed-in handler object may be a raw handler or a
* pre-built {@link HandlerExecutionChain}. This method should handle those
* two cases explicitly, either building a new {@link HandlerExecutionChain}
* or extending the existing chain.
* <p>For simply adding an interceptor in a custom subclass, consider calling
* {@code super.getHandlerExecutionChain(handler, request)} and invoking
* {@link HandlerExecutionChain#addInterceptor} on the returned chain object.
* @param handler the resolved handler instance (never {@code null})
* @param request current HTTP request
* @return the HandlerExecutionChain (never {@code null})
* @see #getAdaptedInterceptors()
*/
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;
}
从handlermapping的类关系图中可以看到AbstractHandlerMapping有两个实现类
AbstractUrlHandlerMapping
通过url来进行匹配,将url和对应的handler保存在一个map中
AbstractHandlerMethodMapping
将具体的method作为handler来使用,比如经常使用的@RequestMapping所注释的方法就是这种handler,这种handler是HandlerMethod