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*/@Overrideprotected Object getHandlerInternal(HttpServletRequest request) throws Exception {// 根据request获取urlString lookupPath = getUrlPathHelper().getLookupPathForRequest(request);// 根据url查找handlerObject 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进行查找handlerObject 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 themMap<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分发的相关知识,希望对大家有所帮助!
新闻热点
疑难解答