DefaultAnnotationHandlerMapping详细分析

1. 类图分析

用来处理@Controller类型handler请求的HandlerMapping, 类图如下:
在这里插入图片描述

  • ServletContextAware

作用是通过ServletContextAwareProcessor(BeanPostProcessor)注入ServletContext

public interface ServletContextAware extends Aware {
    void setServletContext(ServletContext var1);
}
  • ApplicationContextAware

注入ApplicationContext同时作为初始化时收集@RequestMapping信息和HandlerInterceptors的入口

public interface ApplicationContextAware extends Aware {
    void setApplicationContext(ApplicationContext var1) throws BeansException;
}
  • HandlerMapping

用来处理具体请求, 其中HandlerExecutionChain包含Handler和Interceptor链, 每次请求生成的HandlerExecutionChain不一样

public interface HandlerMapping {
	HandlerExecutionChain getHandler(HttpServletRequest var1) throws Exception;
}

2. 启动初始化

  • ServletContextAware初始化

作用比较简单, 重点关注下ServletContextAware是因为ServletContextAwareProcessor(BeanPostProcessor)而被初始化, 而ServletContextAwareProcessor是在AbstractRefreshableWebApplicationContext中定义并注入到容器中

protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
        beanFactory.ignoreDependencyInterface(ServletContextAware.class);
        beanFactory.ignoreDependencyInterface(ServletConfigAware.class);
  			//注册request/session/globalSession等scope相关组件到Mvc容器
        WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
  			//将servlet相关组件注册到Mvc容器
        WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
}

  • ApplicationContextAware初始化

参考下面的流程图, 具体可以去看源码, 不再赘述.
其中重点关注: 初始化时如何处理@Controller和@RequestMapping元信息, 以及收集HandlerIntercetors信息

在这里插入图片描述


3. 处理请求

HandlerMapping参与DispatcherServlet的doDispach流程, 主要包括:

  • 根据request获取对应的Handler处理器(即@Controller)
    其中包含校验@RequestMapping中的定义的method/headers/params的check
public @interface RequestMapping {
    String[] value() default {};

    RequestMethod[] method() default {};

    String[] params() default {};

    String[] headers() default {};
    //略
}
  • 获取当前request的HandlerInterceptors过滤器链

3.1 获取Handler

​ 只要有一个满足条件的Handler, 不再进行匹配, 源码如下:

protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        Iterator i$ = this.handlerMappings.iterator();

        HandlerExecutionChain handler;
        do {
            if (!i$.hasNext()) {
                return null;
            }

            HandlerMapping hm = (HandlerMapping)i$.next();
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name '" + this.getServletName() + "'");
            }

            handler = hm.getHandler(request);
        } while(handler == null);

        return handler;
    }

由于初始化时收集了url到Handler的映射handlerMap, 所以直接精确匹配或根据URL匹配最佳的urlPattern, 再获得Handler, 源码如下:

public abstract class AbstractUrlHandlerMapping{
  protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
        Object handler = this.handlerMap.get(urlPath);
        if (handler != null) {
            if (handler instanceof String) {
                String handlerName = (String)handler;
                handler = this.getApplicationContext().getBean(handlerName);
            }

            this.validateHandler(handler, request);
            return this.buildPathExposingHandler(handler, urlPath, urlPath, (Map)null);
        } else {
            List<String> matchingPatterns = new ArrayList();
            Iterator i$ = this.handlerMap.keySet().iterator();

            while(i$.hasNext()) {
                String registeredPattern = (String)i$.next();
                if (this.getPathMatcher().match(registeredPattern, urlPath)) {
                    matchingPatterns.add(registeredPattern);
                }
            }

            String bestPatternMatch = null;
            Comparator<String> patternComparator = this.getPathMatcher().getPatternComparator(urlPath);
            if (!matchingPatterns.isEmpty()) {
                Collections.sort(matchingPatterns, patternComparator);
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Matching patterns for request [" + urlPath + "] are " + matchingPatterns);
                }

                bestPatternMatch = (String)matchingPatterns.get(0);
            }

            if (bestPatternMatch != null) {
                handler = this.handlerMap.get(bestPatternMatch);
                String pathWithinMapping;
                if (handler instanceof String) {
                    pathWithinMapping = (String)handler;
                    handler = this.getApplicationContext().getBean(pathWithinMapping);
                }

                this.validateHandler(handler, request);
                pathWithinMapping = this.getPathMatcher().extractPathWithinPattern(bestPatternMatch, urlPath);
                Map<String, String> uriTemplateVariables = new LinkedHashMap();
                Iterator i$ = matchingPatterns.iterator();

                while(i$.hasNext()) {
                    String matchingPattern = (String)i$.next();
                    if (patternComparator.compare(bestPatternMatch, matchingPattern) == 0) {
                        Map<String, String> vars = this.getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath);
                        Map<String, String> decodedVars = this.getUrlPathHelper().decodePathVariables(request, vars);
                        uriTemplateVariables.putAll(decodedVars);
                    }
                }

                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("URI Template variables for request [" + urlPath + "] are " + uriTemplateVariables);
                }

                return this.buildPathExposingHandler(handler, bestPatternMatch, pathWithinMapping, uriTemplateVariables);
            } else {
                return null;
            }
        }
    }
}

3.2 获取HandlerInterceptors过滤链

获取Handler后, 再获取过滤器链, 最终过滤器链 = (所有adaptedInterceptors过滤器 + 根据url命中的mappedInterceptor过滤器链) , 代码如下. 详细请参考另一篇文章: HandlerInterceptor过滤器详细分析

public abstract class AbstractHandlerMapping{
    protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
        HandlerExecutionChain chain = handler instanceof HandlerExecutionChain ? (HandlerExecutionChain)handler : new HandlerExecutionChain(handler);
        chain.addInterceptors(this.getAdaptedInterceptors());
        String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
        Iterator i$ = this.mappedInterceptors.iterator();

        while(i$.hasNext()) {
            MappedInterceptor mappedInterceptor = (MappedInterceptor)i$.next();
            if (mappedInterceptor.matches(lookupPath, this.pathMatcher)) {
                chain.addInterceptor(mappedInterceptor.getInterceptor());
            }
        }

        return chain;
    }
}    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值