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分发的相关知识,希望对大家有所帮助!