springMVC(二)HandlerMapping

来源:互联网 发布:ztree 数据undefined 编辑:程序博客网 时间:2024/06/05 03:53

上一节中最后讲到HandlerMapping的第一个实现类AbstractHandlerMapping的getHandler方法中调用了getHandlerInternal抽象方法,来看看它的几个子类对这个方法的重载

直接子类:

public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping
public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean

public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {     /**     * 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 {        String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);        Object handler = lookupHandler(lookupPath, request);        if (handler == null) {            // 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);                }                validateHandler(rawHandler, 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;    }/**     * 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?        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?        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);            }            bestPatternMatch = matchingPatterns.get(0);        }        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) == 0) {                    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;    }}
总体上就是从handlerMap中去取,先全部匹配,然后正则匹配,正则匹配多个,按照一定条件排序找到最好的


public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean {   /**     * Look up a handler method for the given request.     */    @Override    protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {        String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);        if (logger.isDebugEnabled()) {            logger.debug("Looking up handler method for path " + lookupPath);        }        HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);        if (logger.isDebugEnabled()) {            if (handlerMethod != null) {                logger.debug("Returning handler method [" + handlerMethod + "]");            }            else {                logger.debug("Did not find handler method for [" + lookupPath + "]");            }        }        return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);    }/**     * Look up the best-matching handler method for the current request.     * If multiple matches are found, the best match is selected.     * @param lookupPath mapping lookup path within the current servlet mapping     * @param request the current request     * @return the best-matching handler method, or {@code null} if no match     * @see #handleMatch(Object, String, HttpServletRequest)     * @see #handleNoMatch(Set, String, HttpServletRequest)     */    protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {        List<Match> matches = new ArrayList<Match>();             //private final MultiValueMap<String, T> urlMap = new LinkedMultiValueMap<String, T>();        List<T> directPathMatches = this.urlMap.get(lookupPath);        if (directPathMatches != null) {            addMatchingMappings(directPathMatches, matches, request);        }        if (matches.isEmpty()) {            // No choice but to go through all mappings...            addMatchingMappings(this.handlerMethods.keySet(), matches, request);        }        if (!matches.isEmpty()) {            Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));            Collections.sort(matches, comparator);            if (logger.isTraceEnabled()) {                logger.trace("Found " + matches.size() + " matching mapping(s) for [" + lookupPath + "] : " + matches);            }            Match bestMatch = matches.get(0);            if (matches.size() > 1) {                Match secondBestMatch = matches.get(1);                if (comparator.compare(bestMatch, secondBestMatch) == 0) {                    Method m1 = bestMatch.handlerMethod.getMethod();                    Method m2 = secondBestMatch.handlerMethod.getMethod();                    throw new IllegalStateException(                            "Ambiguous handler methods mapped for HTTP path '" + request.getRequestURL() + "': {" +                            m1 + ", " + m2 + "}");                }            }            handleMatch(bestMatch.mapping, lookupPath, request);            return bestMatch.handlerMethod;        }        else {            return handleNoMatch(handlerMethods.keySet(), lookupPath, request);        }    }      private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) {        for (T mapping : mappings) {            T match = getMatchingMapping(mapping, request);            if (match != null) {                matches.add(new Match(match, this.handlerMethods.get(mapping)));            }        }    }    /**     * Check if a mapping matches the current request and return a (potentially     * new) mapping with conditions relevant to the current request.     * @param mapping the mapping to get a match for     * @param request the current HTTP servlet request     * @return the match, or {@code null} if the mapping doesn't match     */    protected abstract T getMatchingMapping(T mapping, HttpServletRequest request);}


0 0
原创粉丝点击