SpringMVC框架的Handler查找

对于springmvc框架的基本执行逻辑包含以下几步

  1. 查找能够处理http请求的Handler(通过HandlerMapping来查找)
  2. 查询能处理Handler的适配器HandlerAdapter
  3. 执行HandlerAdapter得到ModelAndView
  4. 根据ModelAndView得到对应的View
  5. 执行View的渲染方法进行客户端的响应

那么本章节主要讲解其查找Handler的过程。

在DispatcherServlet初始化的时候会通过以下代码来初始化HandlerMappings

public class DispatcherServlet extends FrameworkServlet {
    /**
     * Initialize the HandlerMappings used by this class.
     * <p>If no HandlerMapping beans are defined in the BeanFactory for this namespace,
     * we default to BeanNameUrlHandlerMapping.
     */
    private void initHandlerMappings(ApplicationContext context) {
        this.handlerMappings = null;

        //判断是否查找所有的HandlerMappings,默认为true
        if (this.detectAllHandlerMappings) {
            // 从ApplicationContext(包括祖先祖先ApplicationContext)中查找所有HandlerMapping类型的Bean
            Map<String, HandlerMapping> matchingBeans =
                    BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
            if (!matchingBeans.isEmpty()) {
                this.handlerMappings = new ArrayList<>(matchingBeans.values());
                // 对查找到的HandlerMapping进行排序
                AnnotationAwareOrderComparator.sort(this.handlerMappings);
            }
        }
        else {
            try {
                //直接从当前的ApplicationContext获取名为handlerMapping,类型为HandlerMapping的bean
                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则使用DispatcherServlet.properties中默认配置的HandlerMapping
        if (this.handlerMappings == null) {
            this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
            if (logger.isTraceEnabled()) {
                logger.trace("No HandlerMappings declared for servlet '" + getServletName() +
                        "': using default strategies from DispatcherServlet.properties");
            }
        }

        for (HandlerMapping mapping : this.handlerMappings) {
            if (mapping.usesPathPatterns()) {
                this.parseRequestPath = true;
                break;
            }
        }
    }
}

在spring-webmvc包中的DispatcherServlet.properties中默认配置了以下的HandlerMapping

org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping,\
    org.springframework.web.servlet.function.support.RouterFunctionMapping

spring-webmvc框架在处理请求时通过以下方法来查找Handler,当然,实际是返回的一个包含了Handler的HandlerExecutionChain

    /**
     * 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
     */
    @Nullable
    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        if (this.handlerMappings != null) {
            for (HandlerMapping mapping : this.handlerMappings) {
                HandlerExecutionChain handler = mapping.getHandler(request);
                if (handler != null) {
                    return handler;
                }
            }
        }
        return null;
    }

从上可见,HandlerMapping的具体实现与Handler的查找息息相关,在讲解HandlerMapping的具体实现前,我们先聊聊会被具体实现继承的抽象类AbstractHandlerMapping

AbstractHandlerMapping
public abstract class AbstractHandlerMapping extends WebApplicationObjectSupport
        implements HandlerMapping, Ordered, BeanNameAware {
    @Nullable
    private Object defaultHandler;

    @Nullable
    private PathPatternParser patternParser;

    private UrlPathHelper urlPathHelper = new UrlPathHelper();

    private PathMatcher pathMatcher = new AntPathMatcher();

    private final List<Object> interceptors = new ArrayList<>();

    private final List<HandlerInterceptor> adaptedInterceptors = new ArrayList<>();

    @Nullable
    private CorsConfigurationSource corsConfigurationSource;

    private CorsProcessor corsProcessor = new DefaultCorsProcessor();

    private int order = Ordered.LOWEST_PRECEDENCE;  // default: same as non-Ordered

    @Nullable
    private String beanName;

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

    /**
     * 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
     */
    @Override
    @Nullable
    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 = obtainApplicationContext().getBean(handlerName);
        }

        //生成Handler的调用链(封装了该Handler所需的拦截器)
        HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);

        if (logger.isTraceEnabled()) {
            logger.trace("Mapped to " + handler);
        }
        else if (logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) {
            logger.debug("Mapped to " + executionChain.getHandler());
        }

        //hasCorsConfigurationSource:如果实际的handler是CorsConfigurationSource类型,
        //或者corsConfigurationSource不为空,这返回true
        if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
            //获取该Handler的跨域配置
            CorsConfiguration config = getCorsConfiguration(handler, request);
            if (getCorsConfigurationSource() != null) {
                CorsConfiguration globalConfig = getCorsConfigurationSource().getCorsConfiguration(request);
                config = (globalConfig != null ? globalConfig.combine(config) : config);
            }
            if (config != null) {
                config.validateAllowCredentials();
            }
            //给executionChain 添加CorsInterceptor拦截器
            executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
        }

        return executionChain;
    }

    //供具体的子类来实现Handler的查找
    @Nullable
    protected abstract Object getHandlerInternal(HttpServletRequest request) throws Exception;

    protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
        HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
                (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));

        //遍历所有的HandlerInterceptor,如果是实现类MappedInterceptor 则判断是否匹配当前的请求,
        //如果匹配则将持有的HandlerInterceptor实例添加到拦截器链中;如果不是MappedInterceptor ,
        //则直接加入到拦截器链中
        for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
            if (interceptor instanceof MappedInterceptor) {
                MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
                if (mappedInterceptor.matches(request)) {
                    chain.addInterceptor(mappedInterceptor.getInterceptor());
                }
            }
            else {
                chain.addInterceptor(interceptor);
            }
        }
        return chain;
    }

    protected HandlerExecutionChain getCorsHandlerExecutionChain(HttpServletRequest request,
            HandlerExecutionChain chain, @Nullable CorsConfiguration config) {

        if (CorsUtils.isPreFlightRequest(request)) {
            HandlerInterceptor[] interceptors = chain.getInterceptors();
            return new HandlerExecutionChain(new PreFlightHandler(config), interceptors);
        }
        else {
            chain.addInterceptor(0, new CorsInterceptor(config));
            return chain;
        }
    }
}

AbstractHandlerMapping中initApplicationContext方法的目的是为了初始化Handler的拦截器(HandlerInterceptor),其会得到ApplicationContext中所有MappedInterceptor类型的Bean(MappedInterceptor是HandlerInterceptor接口的实现类)。MappedInterceptor实例内部持有HandlerInterceptor类型的实例,通过MappedInterceptor的matches方法可以判断某请求是否需要使用该拦截器。

其中的getHandlerInternal方法供子类去实现,不同的子类其查找的策略会不一样,其得到的Handler的类型也不同。

1,BeanNameUrlHandlerMapping

BeanNameUrlHandlerMapping将URL映射到名称以斜杠(“/”)开头的bean。该种查找方式现在用的应该很少了,所以这里就简单的说说。

BeanNameUrlHandlerMapping

在BeanNameUrlHandlerMapping初始化的过程中首先会获取所有名称以斜杠(“/”)开头的bean,当请求到来时再与请求的路径进行匹配,当匹配成功则该bean就是对应的Handler。由于该种查找方式用的不多,这里就不再多缀诉了。

2,RequestMappingHandlerMapping

该对象是目前使用最多的,所以我们先来看看其初始化的过程。其初始化的过程从RequestMappingHandlerMapping的initApplicationContext方法开始

  1. 首先执行继承自AbstractHandlerMapping的initApplicationContext方法。
    该方法的目的是为了初始化Handler的拦截器(HandlerInterceptor),其会得到ApplicationContext中所有MappedInterceptor类型的Bean(MappedInterceptor是HandlerInterceptor接口的实现类)。MappedInterceptor实例内部持有HandlerInterceptor类型的实例,通过MappedInterceptor的matches方法可以判断某请求是否需要使用该拦截器。

2.执行RequestMappingHandlerMapping的afterPropertiesSet方法

  1. 执行父类AbstractHandlerMethodMapping的afterPropertiesSet方法

  2. 执行AbstractHandlerMethodMapping的initHandlerMethods方法
    initHandlerMethods的整体目的是扫描ApplicationContext中的bean,检测并注册handler方法
    -> 首先从ApplicationContext中所以Object类型Bean的名称,然后过滤掉“scopedTarget.”开头的
    -> 遍历所有的名称并从ApplicationContext中获取Bean的Class类型
    -> 判断得到的Class是否为Handler(判断是否有Controller和RequestMapping注解)
    -> 解析Class,得到包含RequestMapping注解的方法
    -> 将方法封装到HandlerMethod,并将其注册到MappingRegistry中

当请求到来时,将会从MappingRegistry中查找最匹配的Handler,此时的Handler本身是个Method。

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 = initLookupPath(request);
        this.mappingRegistry.acquireReadLock();
        try {
            HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);
            return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);
        }
        finally {
            this.mappingRegistry.releaseReadLock();
        }
    }

    /**
     * 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)
     */
    @Nullable
    protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {
        List<Match> matches = new ArrayList<>();
        List<T> directPathMatches = this.mappingRegistry.getMappingsByDirectPath(lookupPath);
        if (directPathMatches != null) {
            addMatchingMappings(directPathMatches, matches, request);
        }
        if (matches.isEmpty()) {
            addMatchingMappings(this.mappingRegistry.getRegistrations().keySet(), matches, request);
        }
        if (!matches.isEmpty()) {
            Match bestMatch = matches.get(0);
            if (matches.size() > 1) {
                Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));
                matches.sort(comparator);
                bestMatch = matches.get(0);
                if (logger.isTraceEnabled()) {
                    logger.trace(matches.size() + " matching mappings: " + matches);
                }
                if (CorsUtils.isPreFlightRequest(request)) {
                    return PREFLIGHT_AMBIGUOUS_MATCH;
                }
                Match secondBestMatch = matches.get(1);
                if (comparator.compare(bestMatch, secondBestMatch) == 0) {
                    Method m1 = bestMatch.handlerMethod.getMethod();
                    Method m2 = secondBestMatch.handlerMethod.getMethod();
                    String uri = request.getRequestURI();
                    throw new IllegalStateException(
                            "Ambiguous handler methods mapped for '" + uri + "': {" + m1 + ", " + m2 + "}");
                }
            }
            request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, bestMatch.handlerMethod);
            handleMatch(bestMatch.mapping, lookupPath, request);
            return bestMatch.handlerMethod;
        }
        else {
            return handleNoMatch(this.mappingRegistry.getRegistrations().keySet(), lookupPath, request);
        }
    }
}
RequestMappingHandlerMapping
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容