SimpleUrlHandlerMapping的配置

SimpleUrlHandlerMapping 

<bean id="loginUrlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <!-- 第一种方法 -->
    <property name="mappings">
        <props>
            <prop key="/base/login.htm">loginController</prop>
            <prop key="/base/login.htm?method=doLogin">loginController</prop>            
        </props>
    </property>    
    <!-- 第二种方法 -->
    <property name="urlMap">     
        <map>     
            <entry key="/base/login.htm" value-ref="loginController"/>     
        </map>     
    </property>
    <!-- 第三种方法 -->
    <property name="mappings">     
        <bean class="org.springframework.beans.factory.config.PropertiesFactoryBean">     
            <property name="location">     
                <value>urlMap.properties</value> <!-- 此时urlMap.properties文件应放在WebRoot目录下! -->     
            </property>     
        </bean>     
    </property>    
</bean>
<!--第四种-->

<bean id="rechargeNotifyParamResolver" class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver">
    <property name="mappings">
        <props>
            <prop key="/app/gateway/recharge/ccb/notify.htm">index</prop>
        </props>
    </property>
</bean>
<bean id="rechargeNotifyController" class="com.ciispay.site.controller.gateway.RechargeNotifyController" parent="baseController">
    <property name="methodNameResolver">
        <ref bean="rechargeNotifyParamResolver" />
    </property>
      <property name= "rechargeAppService" ref= "rechargeAppService"/>
</bean>

<!--在父类org.springframework.web.servlet.mvc.multiaction.MultiActionController中有个set方法-->
public final void setMethodNameResolver(MethodNameResolver methodNameResolver) {
    this.methodNameResolver = methodNameResolver;
}
 

 SimpleUrlHandlerMapping中的setMappings和setUrlMap方法

/**
 * Map URL paths to handler bean names.
 * This is the typical way of configuring this HandlerMapping.
 * <p>Supports direct URL matches and Ant-style pattern matches. For syntax
 * details, see the {@link org.springframework.util.AntPathMatcher} javadoc.
 * @param mappings properties with URLs as keys and bean names as values
 * @see #setUrlMap
 */
public void setMappings(Properties mappings) {
    CollectionUtils.mergePropertiesIntoMap(mappings, this.urlMap);
}
/**
 * Set a Map with URL paths as keys and handler beans (or handler bean names)
 * as values. Convenient for population with bean references.
 * <p>Supports direct URL matches and Ant-style pattern matches. For syntax
 * details, see the {@link org.springframework.util.AntPathMatcher} javadoc.
 * @param urlMap map with URLs as keys and beans as values
 * @see #setMappings
 */
public void setUrlMap(Map<String, ?> urlMap) {
    this.urlMap.putAll(urlMap);
}

然后把这些对应的信息注册到Handler,SimpleUrlHandlerMapping就是将请求的url作为key,然后找到对应的Handler。

initApplicationContext()中registerHandlers()。在registerHandlers()方法中调用父类AbstractUrlHandlerMapping的registerHandler()方法。

/**
 * Calls the {@link #registerHandlers} method in addition to the
 * superclass's initialization.
 */
@Override
public void initApplicationContext() throws BeansException {
    super.initApplicationContext();
    registerHandlers(this.urlMap);
}

/**
 * Register all handlers specified in the URL map for the corresponding paths.
 * 注册配置在urlMap中的响应路径
 * @param urlMap Map with URL paths as keys and handler beans or bean names as values
 * @throws BeansException if a handler couldn't be registered
 * @throws IllegalStateException if there is a conflicting handler registered
 */
protected void registerHandlers(Map<String, Object> urlMap) throws BeansException {
    if (urlMap.isEmpty()) {
        logger.warn("Neither 'urlMap' nor 'mappings' set on SimpleUrlHandlerMapping");
    }
    else {
        for (Map.Entry<String, Object> entry : urlMap.entrySet()) {
            String url = entry.getKey();
            Object handler = entry.getValue();
            // Prepend with slash if not already present.
            if (!url.startsWith("/")) {
                url = "/" + url;
            }
            // Remove whitespace from handler bean name.
            if (handler instanceof String) {
                handler = ((String) handler).trim();
            }
            registerHandler(url, handler);//调用父类AbstractUrlHandlerMapping中的registerHandler()方法
        }
    }
}

AbstractUrlHandlerMapping
/** * Register the specified handler for the given URL path. * @param urlPath the URL the bean should be mapped to * @param handler the handler instance or handler bean name String * (a bean name will automatically be resolved into the corresponding handler bean) * @throws BeansException if the handler couldn't be registered * @throws IllegalStateException if there is a conflicting handler registered */ protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException { Assert.notNull(urlPath, "URL path must not be null"); Assert.notNull(handler, "Handler object must not be null"); Object resolvedHandler = handler; // Eagerly resolve handler if referencing singleton via name. if (!this.lazyInitHandlers && handler instanceof String) { String handlerName = (String) handler; if (getApplicationContext().isSingleton(handlerName)) { resolvedHandler = getApplicationContext().getBean(handlerName); } } Object mappedHandler = this.handlerMap.get(urlPath); if (mappedHandler != null) { if (mappedHandler != resolvedHandler) { throw new IllegalStateException( "Cannot map " + getHandlerDescription(handler) + " to URL path [" + urlPath + "]: There is already " + getHandlerDescription(mappedHandler) + " mapped."); } } else { if (urlPath.equals("/")) { if (logger.isInfoEnabled()) { logger.info("Root mapping to " + getHandlerDescription(handler)); } setRootHandler(resolvedHandler); } else if (urlPath.equals("/*")) { if (logger.isInfoEnabled()) { logger.info("Default mapping to " + getHandlerDescription(handler)); } setDefaultHandler(resolvedHandler); } else { this.handlerMap.put(urlPath, resolvedHandler); if (logger.isInfoEnabled()) { logger.info("Mapped URL path [" + urlPath + "] onto " + getHandlerDescription(handler)); } } } }

然后看下Spring是如何取出来的

在DispatcherServlet中的doDispatch()方法中
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
  ...
  mappedHandler = getHandler(processedRequest, false);
  ...
}

/**
 * Return the HandlerExecutionChain for this request. Try all handler mappings in order.
 * @param request current HTTP request
 * @param cache whether to cache the HandlerExecutionChain in a request attribute
 * @return the HandlerExecutionChain, or {@code null} if no handler could be found
 * @deprecated as of Spring 3.0.4, in favor of {@link #getHandler(javax.servlet.http.HttpServletRequest)},
 * with this method's cache attribute now effectively getting ignored
 */
@Deprecated
protected HandlerExecutionChain getHandler(HttpServletRequest request, boolean cache) throws Exception {
    return getHandler(request);
}

/**
 * Return the HandlerExecutionChain for this request.
 * <p>Tries all handler mappings in order.
 * @param request current HTTP request
 * @return the HandlerExecutionChain, or {@code null} if no handler could be found
 */
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
    for (HandlerMapping hm : this.handlerMappings) {
        if (logger.isTraceEnabled()) {
            logger.trace(
                    "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'");
        }
        HandlerExecutionChain handler = hm.getHandler(request);
        if (handler != null) {
            return handler;
        }
    }
    return null;
}
我们主要看: HandlerExecutionChain handler
= hm.getHandler(request); 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); } AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping,并且在AbstractHandlerMethodMapping中重写了AbstractHandlerMapping中的getHandlerInternal方法 方法:
@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; } 再看下lookupHandlerMethod()方法 protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception { List<Match> matches = new ArrayList<Match>(); 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); } }
原文地址:https://www.cnblogs.com/lemon-now/p/5553510.html