欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

SpringMVC源码解读之HandlerMapping - AbstractUrlHandlerMapping系列request分发

程序员文章站 2024-03-08 19:52:16
abstracthandlermapping实现handlermapping接口定的gethandler   1. 提供gethandlerinternal模板方法给...

abstracthandlermapping实现handlermapping接口定的gethandler

  1. 提供gethandlerinternal模板方法给子类实现

      2. 如果没有获取handler,则使用默认的defaulthandler

  3. 如果handler是string类型,从context获取实例

  4. 通过gethandlerexecutionchain封装handler,添加interceptor

// 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
*/
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);
}
return gethandlerexecutionchain(handler, request);
} 
// abstracthandlermapping
/**
* build a handlerexecutionchain for the given handler, including applicable interceptors.
* <p>the default implementation simply builds a standard handlerexecutionchain with
* the given handler, the handler mapping's common interceptors, and any {@link mappedinterceptor}s
* matching to the current request url. 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
* handlerexecutionchain. this method should handle those two cases explicitly,
* either building a new handlerexecutionchain or extending the existing chain.
* <p>for simply adding an interceptor, consider calling {@code super.gethandlerexecutionchain}
* 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);
chain.addinterceptors(getadaptedinterceptors());
string lookuppath = urlpathhelper.getlookuppathforrequest(request);
for (mappedinterceptor mappedinterceptor : mappedinterceptors) {
if (mappedinterceptor.matches(lookuppath, pathmatcher)) {
chain.addinterceptor(mappedinterceptor.getinterceptor());
}
}
return chain;
}

接下来看看abstracturlhandlermapping实现的gethandlerinternal

// abstracturlhandlermapping
/**
* look up a handler for the url path of the given request.
* @param request current http request
* @return the handler instance, or {@code null} if none found
*/
@override
protected object gethandlerinternal(httpservletrequest request) throws exception {
// 根据request获取url
string lookuppath = geturlpathhelper().getlookuppathforrequest(request);
// 根据url查找handler
object handler = lookuphandler(lookuppath, request);
if (handler == null) {
// 如果没有匹配到handler需要查找默认的,下面需要将path_within_handler_mapping_attribute缓存到request
// we need to care for the default handler directly, since we need to
// expose the path_within_handler_mapping_attribute for it as well.
object rawhandler = null;
if ("/".equals(lookuppath)) {
rawhandler = getroothandler();
}
if (rawhandler == null) {
rawhandler = getdefaulthandler();
}
if (rawhandler != null) {
// bean name or resolved handler?
if (rawhandler instanceof string) {
string handlername = (string) rawhandler;
rawhandler = getapplicationcontext().getbean(handlername);
}
// 预留的校验handler模板方法,没有使用
validatehandler(rawhandler, request);
// 添加expose属性到request的拦截器
handler = buildpathexposinghandler(rawhandler, lookuppath, lookuppath, null);
}
}
if (handler != null && logger.isdebugenabled()) {
logger.debug("mapping [" + lookuppath + "] to " + handler);
}
else if (handler == null && logger.istraceenabled()) {
logger.trace("no handler mapping found for [" + lookuppath + "]");
}
return handler;
} 
// abstracturlhandlermapping
/**
* look up a handler instance for the given url path.
* <p>supports direct matches, e.g. a registered "/test" matches "/test",
* and various ant-style pattern matches, e.g. a registered "/t*" matches
* both "/test" and "/team". for details, see the antpathmatcher class.
* <p>looks for the most exact pattern, where most exact is defined as
* the longest path pattern.
* @param urlpath url the bean is mapped to
* @param request current http request (to expose the path within the mapping to)
* @return the associated handler instance, or {@code null} if not found
* @see #exposepathwithinmapping
* @see org.springframework.util.antpathmatcher
*/
protected object lookuphandler(string urlpath, httpservletrequest request) throws exception {
// direct match? 直接根据url进行查找handler
object handler = this.handlermap.get(urlpath);
if (handler != null) {
// bean name or resolved handler?
if (handler instanceof string) {
string handlername = (string) handler;
handler = getapplicationcontext().getbean(handlername);
}
validatehandler(handler, request);
return buildpathexposinghandler(handler, urlpath, urlpath, null);
}
// pattern match? 通过表达式进行匹配具体通过antpathmatcher实现,具体后面分析
list<string> matchingpatterns = new arraylist<string>();
for (string registeredpattern : this.handlermap.keyset()) {
if (getpathmatcher().match(registeredpattern, urlpath)) {
matchingpatterns.add(registeredpattern);
}
}
string bestpatternmatch = null;
comparator<string> patterncomparator = getpathmatcher().getpatterncomparator(urlpath);
if (!matchingpatterns.isempty()) {
collections.sort(matchingpatterns, patterncomparator);
if (logger.isdebugenabled()) {
logger.debug("matching patterns for request [" + urlpath + "] are " + matchingpatterns);
}
// order序号最小的优先级最高
bestpatternmatch = matchingpatterns.get();
}
if (bestpatternmatch != null) {
handler = this.handlermap.get(bestpatternmatch);
// bean name or resolved handler?
if (handler instanceof string) {
string handlername = (string) handler;
handler = getapplicationcontext().getbean(handlername);
}
validatehandler(handler, request);
string pathwithinmapping = getpathmatcher().extractpathwithinpattern(bestpatternmatch, urlpath);
// there might be multiple 'best patterns', let's make sure we have the correct uri template variables
// for all of them
map<string, string> uritemplatevariables = new linkedhashmap<string, string>();
for (string matchingpattern : matchingpatterns) {
if (patterncomparator.compare(bestpatternmatch, matchingpattern) == ) {
map<string, string> vars = getpathmatcher().extracturitemplatevariables(matchingpattern, urlpath);
map<string, string> decodedvars = geturlpathhelper().decodepathvariables(request, vars);
uritemplatevariables.putall(decodedvars);
}
}
if (logger.isdebugenabled()) {
logger.debug("uri template variables for request [" + urlpath + "] are " + uritemplatevariables);
}
return buildpathexposinghandler(handler, bestpatternmatch, pathwithinmapping, uritemplatevariables);
}
// no handler found...
return null;
}

设计用于校验handler,实际什么都没做,包括子类.

/**
* validate the given handler against the current request.
* <p>the default implementation is empty. can be overridden in subclasses,
* for example to enforce specific preconditions expressed in url mappings.
* @param handler the handler object to validate
* @param request current http request
* @throws exception if validation failed
*/
protected void validatehandler(object handler, httpservletrequest request) throws exception {
}

封装handler为handlerexecutionchain,并添加pathexposinghandlerinterceptor和uritemplatevariableshandlerinterceptor拦截器.

/**
* build a handler object for the given raw handler, exposing the actual
* handler, the {@link #path_within_handler_mapping_attribute}, as well as
* the {@link #uri_template_variables_attribute} before executing the handler.
* <p>the default implementation builds a {@link handlerexecutionchain}
* with a special interceptor that exposes the path attribute and uri template variables
* @param rawhandler the raw handler to expose
* @param pathwithinmapping the path to expose before executing the handler
* @param uritemplatevariables the uri template variables, can be {@code null} if no variables found
* @return the final handler object
*/
protected object buildpathexposinghandler(object rawhandler, string bestmatchingpattern,
string pathwithinmapping, map<string, string> uritemplatevariables) {
handlerexecutionchain chain = new handlerexecutionchain(rawhandler);
chain.addinterceptor(new pathexposinghandlerinterceptor(bestmatchingpattern, pathwithinmapping));
if (!collectionutils.isempty(uritemplatevariables)) {
chain.addinterceptor(new uritemplatevariableshandlerinterceptor(uritemplatevariables));
}
return chain;
}

以上内容是小编给大家介绍的springmvc源码解读之handlermapping - abstracturlhandlermapping系列request分发的相关知识,希望对大家有所帮助!