学习一种知识,我喜欢看看源码是怎么进行它们类之间的关系以及方法的调用,是怎么实现的。这样我才感觉踏实。

既然现在谈到HandlerMapping,我们先知道HandlerMapping的作用:HandlerMapping的作用就是解析请求链接,然后根据请求链接找到执行这个请求的类(HandlerMapping所说的handler,也就是我们写的Controller或是Action)。

现在我们来了解HandlerMapping的继承体系图:

至于我们在配置文件中配置的BeanNameUrlHandlerMapping或者是SimpleUrlHandlerMapping,他们的目的是一样的,只是通过请求链接来找handler的方式不一样。

我们再来看看更详细的继承关系:

HandlerMapping的使用主要分为两步:注册和查找。

注册是根据配置文件中的配置将一个字符串和一个Controller类以<key,value>的形式存入到Map中,这个key就是对应的url中的某个字段。

查找就是HandlerMapping根据url中的的某个字段,在Map中以这个字段为key值对应的Controller类,并将Controller类封装成一个HandlerExecutionChain对象,HandlerExecutionChain中除了有Controller对象外,还有一组拦截器。

现在我简单以SimpleUrlHandlerMapping为例子来分析HandlerMapping是如何根据请求链接找到Controller类的。

1.注册

    <!--  SpringMVC中的HandlerMapping配置    配置映射器 -->
    <bean id="" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
    <property name="mappings">
    <props>
    <prop key="/*.do">helloword</prop>
    </props>
    </property>
    </bean>
    <!--配置处理器  -->

    <bean id="helloword" class="cn.controller.HelloController">
    <property name="methodNameResolver" ref="nameResolver">

    </property>
    </bean>

当我们第一次访问服务器的时候IOC容器会根据配置文件中的红色的部分生成一个Map<String, Object>,这个map里面的值就是{/*.do=/helloworld}。

SimpleUrlHandlerMapping的作用就是获取这个集合,然后根据这个集合里的value找到对应的bean,这样就可以把url中的某个字段和我们写的处理器对应起来。下面是SimpleUrlHandlerMapping中的关键源码

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

我们来看看HandlerMapping的父类

但是在这个类中没有initApplicationContext()方法,我们就再来看看AbstractUrlHandlerMapping的父类

的确,在这个类中有了我们想要的initApplicationContext()方法。

/**
     * Initializes the interceptors.
     * @see #extendInterceptors(java.util.List)
     * @see #initInterceptors()
     */
    @Override
    protected void initApplicationContext() throws BeansException {
        extendInterceptors(this.interceptors);
        detectMappedInterceptors(this.adaptedInterceptors);
        initInterceptors();
    }

这个方法就是初始化SpringMVC容器,并对handler进行注册,urlMap中的值根据上面的配置文件就是{/*.do=/helloWorld}的

现在我们一起来看registerHandlers方法,

/**
     * Register all handlers specified in the URL map for the corresponding paths.
     * @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);
            }
        }
    }

主要是对urlMap中的key值进行了一些处理,要是没有“/”的就加上"/",去掉空格等处理。这个方法中的重点是调用了registerHandler(url, handler)这个方法,在这个方法是它的父类AbstractUrlHandlerMapping中的方法。

我们来看看AbstractUrlHandlerMapping中的registerHandler(url, handler)的方法

/**
     * 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));
                }
            }
        }

看registerHandler方法红色的部分大家,可以看出是根据SimpleUrlHandlerMapping中的urlMap中的value值在ioc容器中找到对应的bean,并将url的某个字段作为key值,bean作为value存入到AbstractUrlHandlerMapping的urlMap属性中去,这样就达到url的某个字段对应到具体的controller了的目的,当遇到有请求访问服务器的时候,就可以根据url找到具体的controller去执行这个请求了。

2.查找

在Dispatcher类中,根据配置文件对handlerMapping进行注册,即对handlerMapping的初始化。

  protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
<span style="color:#ff0000;">initHandlerMappings(context);</span>
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context); 
 private void initHandlerMappings(ApplicationContext context) {
this.handlerMappings = null;  

if (this.detectAllHandlerMappings) {
    // Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
    <span style="color:#ff0000;">Map<String, HandlerMapping> matchingBeans =
            BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);</span>
    if (!matchingBeans.isEmpty()) {
        <span style="color:#ff0000;">this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values());</span>
        // We keep HandlerMappings in sorted order.
        OrderComparator.sort(this.handlerMappings);
    }
}
else {
    try {
        HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
        this.handlerMappings = Collections.singletonList(hm);
    }
    catch (NoSuchBeanDefinitionException ex) {
        // Ignore, we'll add a default HandlerMapping later.
    }
}  

于在配置文件中有两种不同类型的handlerMapping,所以从ioc容器中读取出来的handlerMapping有两个,然后将这两个handlerMapping的实例放入Dodispatcher中的handlerMappings属性中。

下面一步就是真正的根据url中的某个字段到已经注册好了的Map<urlString,Controller>中找出执行这个url请求的Controller,用户的请求在被Dispatcher拦截后,会交给Dispatcher的doDispatch执行。在doDispatch方法中主要看红色标记的getHandler方法

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;
        HandlerExecutionChain mappedHandler = null;
        ;  

        try {
            ModelAndView mv;
            boolean errorView = false;  

            try {
                processedRequest = checkMultipart(request);  

                // Determine handler for the current request.
                <span style="color:#ff0000;">mappedHandler = getHandler(processedRequest, false);</span>
                if (mappedHandler == null || mappedHandler.getHandler() == null) {
                    noHandlerFound(processedRequest, response);
                    return;
                }  

                // Determine handler adapter for the current request.
                HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());  

                // Process last-modified header, if supported by the handler.
                String method = request.getMethod();
                boolean isGet = "GET".equals(method);
                if (isGet || "HEAD".equals(method)) {
                    long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                    if (logger.isDebugEnabled()) {
                        String requestUri = urlPathHelper.getRequestUri(request);
                        logger.debug("Last-Modified value for [" + requestUri + "] is: " + lastModified);
                    }
                    if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                        return;
                    }
                }  

                // Apply preHandle methods of registered interceptors.
                HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();
                if (interceptors != null) {
                    ; i < interceptors.length; i++) {
                        HandlerInterceptor interceptor = interceptors[i];
                        if (!interceptor.preHandle(processedRequest, response, mappedHandler.getHandler())) {
                            triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
                            return;
                        }
                        interceptorIndex = i;
                    }
                }  

                // Actually invoke the handler.
                mv = ha.handle(processedRequest, response, mappedHandler.getHandler());  

                // Do we need view name translation?
                if (mv != null && !mv.hasView()) {
                    mv.setViewName(getDefaultViewName(request));
                }  

                // Apply postHandle methods of registered interceptors.
                if (interceptors != null) {
                    ; i >= ; i--) {
                        HandlerInterceptor interceptor = interceptors[i];
                        interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv);
                    }
                }
            }
            catch (ModelAndViewDefiningException ex) {
                logger.debug("ModelAndViewDefiningException encountered", ex);
                mv = ex.getModelAndView();
            }
            catch (Exception ex) {
                Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
                mv = processHandlerException(processedRequest, response, handler, ex);
                errorView = (mv != null);
            }  

            // Did the handler return a view to render?
            if (mv != null && !mv.wasCleared()) {
                render(mv, processedRequest, response);
                if (errorView) {
                    WebUtils.clearErrorRequestAttributes(request);
                }
            }
            else {
                if (logger.isDebugEnabled()) {
                    logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + getServletName() +
                            "': assuming HandlerAdapter completed request handling");
                }
            }  

            // Trigger after-completion for successful outcome.
            triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
        }  

getHandler方法主要会调用已经注册好了的handlerMapping中的getHandler方法

DispatcherServlet中的getHandler方法

/**
     * 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;
    }

现在再来看看HandlerMapping的getHandler方法,可以看到HandlerMapping接口中只有一个getHandler方法

public interface HandlerMapping {

    /**
     * Name of the {@link HttpServletRequest} attribute that contains the path
     * within the handler mapping, in case of a pattern match, or the full
     * relevant URI (typically within the DispatcherServlet's mapping) else.
     * <p>Note: This attribute is not required to be supported by all
     * HandlerMapping implementations. URL-based HandlerMappings will
     * typically support it, but handlers should not necessarily expect
     * this request attribute to be present in all scenarios.
     */
    String PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE = HandlerMapping.class.getName() + ".pathWithinHandlerMapping";

    /**
     * Name of the {@link HttpServletRequest} attribute that contains the
     * best matching pattern within the handler mapping.
     * <p>Note: This attribute is not required to be supported by all
     * HandlerMapping implementations. URL-based HandlerMappings will
     * typically support it, but handlers should not necessarily expect
     * this request attribute to be present in all scenarios.
     */
    String BEST_MATCHING_PATTERN_ATTRIBUTE = HandlerMapping.class.getName() + ".bestMatchingPattern";

    /**
     * Name of the boolean {@link HttpServletRequest} attribute that indicates
     * whether type-level mappings should be inspected.
     * <p>Note: This attribute is not required to be supported by all
     * HandlerMapping implementations.
     */
    String INTROSPECT_TYPE_LEVEL_MAPPING = HandlerMapping.class.getName() + ".introspectTypeLevelMapping";

    /**
     * Name of the {@link HttpServletRequest} attribute that contains the URI
     * templates map, mapping variable names to values.
     * <p>Note: This attribute is not required to be supported by all
     * HandlerMapping implementations. URL-based HandlerMappings will
     * typically support it, but handlers should not necessarily expect
     * this request attribute to be present in all scenarios.
     */
    String URI_TEMPLATE_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".uriTemplateVariables";

    /**
     * Name of the {@link HttpServletRequest} attribute that contains a map with
     * URI matrix variables.
     * <p>Note: This attribute is not required to be supported by all
     * HandlerMapping implementations and may also not be present depending on
     * whether the HandlerMapping is configured to keep matrix variable content
     * in the request URI.
     */
    String MATRIX_VARIABLES_ATTRIBUTE = HandlerMapping.class.getName() + ".matrixVariables";

    /**
     * Name of the {@link HttpServletRequest} attribute that contains the set of
     * producible MediaTypes applicable to the mapped handler.
     * <p>Note: This attribute is not required to be supported by all
     * HandlerMapping implementations. Handlers should not necessarily expect
     * this request attribute to be present in all scenarios.
     */
    String PRODUCIBLE_MEDIA_TYPES_ATTRIBUTE = HandlerMapping.class.getName() + ".producibleMediaTypes";

    /**
     * Return a handler and any interceptors for this request. The choice may be made
     * on request URL, session state, or any factor the implementing class chooses.
     * <p>The returned HandlerExecutionChain contains a handler Object, rather than
     * even a tag interface, so that handlers are not constrained in any way.
     * For example, a HandlerAdapter could be written to allow another framework's
     * handler objects to be used.
     * <p>Returns {@code null} if no match was found. This is not an error.
     * The DispatcherServlet will query all registered HandlerMapping beans to find
     * a match, and only decide there is an error if none can find a handler.
     * @param request current HTTP request
     * @return a HandlerExecutionChain instance containing handler object and
     * any interceptors, or {@code null} if no mapping found
     * @throws Exception if there is an internal error
     */
    HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;

}

再看看实现了HandlerMapping的AbstractHandlerMapping抽象类,AbstractHandlerMapping中的getHandler方法,这个方法的主要作用是根据url找到controller后,并将controller封装成一个HandlerExecutionChain对象

@Override
    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);
        }

        HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
        if (CorsUtils.isCorsRequest(request)) {
            CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request);
            CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
            CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
            executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
        }
        return executionChain;
    }

AbstractHandlerMapping的getHandlerInternal方法是个抽象方法,由AbstractHandlerMapping的子类AbstractUrlHandlerMapping实现

/**
     * Look up a handler for the given request, returning {@code null} if no
     * specific one is found. This method is called by {@link #getHandler};
     * a {@code null} return value will lead to the default handler, if one is set.
     * <p>On CORS pre-flight requests this method should return a match not for
     * the pre-flight request but for the expected actual request based on the URL
     * path, the HTTP methods from the "Access-Control-Request-Method" header, and
     * the headers from the "Access-Control-Request-Headers" header thus allowing
     * the CORS configuration to be obtained via {@link #getCorsConfigurations},
     * <p>Note: This method may also return a pre-built {@link HandlerExecutionChain},
     * combining a handler object with dynamically determined interceptors.
     * Statically specified interceptors will get merged into such an existing chain.
     * @param request current HTTP request
     * @return the corresponding handler instance, or {@code null} if none found
     * @throws Exception if there is an internal error
     */
    protected abstract Object getHandlerInternal(HttpServletRequest request) throws Exception;

AbstractUrlHandlerMapping实现类里面的getHandlerInternal方法

/**
     * 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;
    }

getLookupPathForRequest方法主要是截取url中对应controller的那一部分,lookupHandler方法根据截取的url字段找到对应的controller,看到红色的部分就和我们注册handlerMapping的那一步相关了,我们早早的就将url的部分字段所对应的controller放到了AbstractUrlHandlerMapping中的handlerMap属性中了,现在就能根据url找到对应的controller了

/**
     * 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);
            }
            else if (useTrailingSlashMatch()) {
                if (!registeredPattern.endsWith("/") && 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.);
        }
        if (bestPatternMatch != null) {
            handler = this.handlerMap.get(bestPatternMatch);
            if (handler == null) {
                Assert.isTrue(bestPatternMatch.endsWith("/"));
                handler = , bestPatternMatch.length() - ));
            }
            // 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) {
                ) {
                    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;
    }

到这里算是完了。但是大家可能感觉有点蒙,所以还总结了,方便记忆和理解

就对源码中是如何根据url找到对应的controller进行总结

1.SimpleUrlHandlerMapping根据配置文件中的SimpleUrlHandlerMapping的配置,获得一个map集合,map中存储的是{urlString=beanId}。SimpleUrlHandlerMapping调用父类
AbstractUrlHandlerMapping的registerHandler方法。

2.AbstractUrlHandlerMapping的registerHandler方法有SimpleUrlHandlerMapping传入的map中的urlString和beanId,并根据beanId找到对应的bean即controller,将urlString和urlString对应的controller放入AbstractUrlHandlerMapping的handlerMap中。

3.Dispatcher获取IOC容器中已经初始化好的HandlerMapping,再由HandlerMapping调用自己的getHandler方法根据请求返回HandlerExecutionChain对象。AbstractHandlerMapping方法实现了HandlerMapping接口的getHandler方法。AbstractHandlerMapping中的getHandler方法的主要作用是找到controller,并对controller进行封装成HandlerExecutionChain对象,HandlerExecutionChain中除了controller对象外,还有拦截器对象的集合。

4.AbstractHandlerMapping的getHandler方法中又 调用了AbstractHandlerMapping子类的AbstractUrlHandlerMapping getHandlerInternal方法。getHandlerInternal方法就是截取url中对应的controller字段,并以这个字段为key值去AbstractUrlHandlerMapping 的handlerMap中找寻对应的value,即controlle。

SpringMVC之HandlerMapping源码剖析(一)的更多相关文章

  1. SpringMVC之HandlerMapping源码分析

    01.doDispatch方法中代码如下:HandlerExecutionChain mappedHandler=this.getHandler(processedRequest) 02.Dispat ...

  2. SpringMVC源码剖析(四)- DispatcherServlet请求转发的实现

    SpringMVC完成初始化流程之后,就进入Servlet标准生命周期的第二个阶段,即“service”阶段.在“service”阶段中,每一次Http请求到来,容器都会启动一个请求线程,通过serv ...

  3. SpringMVC源码剖析(二)- DispatcherServlet的前世今生

    上一篇文章<SpringMVC源码剖析(一)- 从抽象和接口说起>中,我介绍了一次典型的SpringMVC请求处理过程中,相继粉墨登场的各种核心类和接口.我刻意忽略了源码中的处理细节,只列 ...

  4. SpringMVC源码剖析1——执行流程

    SpringMVC源码剖析1——执行流程 00.SpringMVC执行流程file:///C:/Users/WANGGA~1/AppData/Local/Temp/enhtmlclip/Image.p ...

  5. jQuery之Deferred源码剖析

    一.前言 大约在夏季,我们谈过ES6的Promise(详见here),其实在ES6前jQuery早就有了Promise,也就是我们所知道的Deferred对象,宗旨当然也和ES6的Promise一样, ...

  6. Nodejs事件引擎libuv源码剖析之:高效线程池(threadpool)的实现

    声明:本文为原创博文,转载请注明出处. Nodejs编程是全异步的,这就意味着我们不必每次都阻塞等待该次操作的结果,而事件完成(就绪)时会主动回调通知我们.在网络编程中,一般都是基于Reactor线程 ...

  7. Apache Spark源码剖析

    Apache Spark源码剖析(全面系统介绍Spark源码,提供分析源码的实用技巧和合理的阅读顺序,充分了解Spark的设计思想和运行机理) 许鹏 著   ISBN 978-7-121-25420- ...

  8. 基于mybatis-generator-core 1.3.5项目的修订版以及源码剖析

    项目简单说明 mybatis-generator,是根据数据库表.字段反向生成实体类等代码文件.我在国庆时候,没事剖析了mybatis-generator-core源码,写了相当详细的中文注释,可以去 ...

  9. STL"源码"剖析-重点知识总结

    STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点略多 :) 1.STL概述 STL提供六大组件,彼此可以组合 ...

随机推荐

  1. ionic第一坑——ion-slide-box坑(ion-slide分两页的坑)

    ionic.views.Slider = ionic.views.View.inherit({ initialize: function (options) { . . . function setu ...

  2. Jexus Web Server 完全傻瓜化图文配置教程(基于Ubuntu 12.04.3 64位)[内含Hyper-v 2012虚拟机镜像下载地址]

    1. 前言 近日有感许多新朋友想尝试使用Jexus,不过绝大多数都困惑徘徊在Linux如何安装啊,如何编译Mono啊,如何配置Jexus啊...等等基础问题,于是昨日向宇内流云兄提议,不如搞几个配置好 ...

  3. .NET跨平台之旅:在生产环境中上线第一个运行于Linux上的ASP.NET Core站点

    2016年7月10日,我们在生产环境中上线了第一个运行于Linux上的ASP.NET Core站点,这是一个简单的提供后端服务的ASP.NET Core Web API站点. 项目是在Windows上 ...

  4. Windows 7 上安装Visual Studio 2015 失败解决方案

    安装之前先要看看自己的系统支不支持,具体的可以看:https://www.visualstudio.com/en-us/visual-studio-2015-system-requirements-v ...

  5. Spring6:基于注解的Spring MVC(上篇)

    什么是Spring MVC Spring MVC框架是一个MVC框架,通过实现Model-View-Controller模式来很好地将数据.业务与展现进行分离.从这样一个角度来说,Spring MVC ...

  6. .NET基础拾遗(1)类型语法基础和内存管理基础

    Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开发基 ...

  7. java太low,又舍不得jvm平台的丰富资源?试试kotlin吧(一)

    尝试kotlin的起因 因为各种原因(版权,人员招聘),公司的技术体系从c#转到了java,我花了大概两周的时间来上手java,发现java的语法还是非常简单的,基本看着代码就知道什么意思.学习jav ...

  8. Direct3D Draw函数 异步调用原理解析

    概述 在D3D10中,一个基本的渲染流程可分为以下步骤: 清理帧缓存: 执行若干次的绘制: 通过Device API创建所需Buffer: 通过Map/Unmap填充数据到Buffer中: 将Buff ...

  9. Entity Framework 6 Recipes 2nd Edition(13-6)译 -> 自动编译的LINQ查询

    问题 你想为多次用到的查询提高性能,而且你不想添加额外的编码或配置. 解决方案 假设你有如Figure 13-8 所示的模型 Figure 13-8. A model with an Associat ...

  10. Html5 Json应用

    本文主要说明Json的基本概念,和一个在Html中使用Json给元素赋值的小例子,属于基础性信息 什么是 JSON ? JSON 指的是 JavaScript 对象表示法(JavaScript Obj ...