3 HandlerMapping 组件源码分析
3 HandlerMapping 组件源码分析
java_sheng 发表于2个月前
3 HandlerMapping 组件源码分析
  • 发表于 2个月前
  • 阅读 0
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云 十分钟定制你的第一个小程序>>>   


AbstractHandlerMapping 抽象类

主要是通过request找到handler 和 interceptors

继承了WebApplicationObjectSupport

    @Override
    protected void initApplicationContext() throws BeansException {
        //模板方法 暂时还没用
        extendInterceptors(this.interceptors);
        //从spring的容器中获取MappedInterceptor的类型放入集合中
        detectMappedInterceptors(this.adaptedInterceptors);
        //初始化拦截器
        initInterceptors();
    }

    //保存我们自定义的拦截器 
    //然后放到对应的adaptedInterceptors和mappedInterceptors
    interceptors
    //此类拦截器不需要匹配
    adaptedInterceptors
    //此类的拦截器需要和url进行匹配,
    //匹配成功后放入集合
    mappedInterceptors
    
----------------------------------------------------------------------
@Override
    public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        //模板方法 子类覆盖
        Object handler = getHandlerInternal(request);
        if (handler == null) {
            //如果没有 就找默认的handler
            handler = getDefaultHandler();
        }
        if (handler == null) {
            return null;
        }
        // string类型的 从容器中查找
        if (handler instanceof String) {
            String handlerName = (String) handler;
            handler = getApplicationContext().getBean(handlerName);
        }
        
        //添加相应的拦截器
        HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
        //这个是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;
    }    
    
------------------------------------------------------------------------------------------    
第一种类型的 HandlerMapping

根据url查找handler的抽象类


AbstractUrlHandlerMapping

@Override
    protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
        //根据request查找到 handler对应的url
        String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
        //从map集合中找到lookupPath所对应的handler
        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)) {
                //跟路径的handler
                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;
    }
    
    
还有一个重要的方法是registerHandler 

//主要是通过子类handlerMap添加handler
protected void registerHandler(String urlPath, Object handler) throws BeansException, IllegalStateException {
        Object resolvedHandler = handler;

        // 判断是不是懒加载的
        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) {
            //如果取出来的hander和resolvedHandler 不相同 就是有问题的
            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));
                }
                //跟路径的handler
                setRootHandler(resolvedHandler);
            }
            else if (urlPath.equals("/*")) {
                if (logger.isInfoEnabled()) {
                    logger.info("Default mapping to " + getHandlerDescription(handler));
                }
                //默认的handler
                setDefaultHandler(resolvedHandler);
            }
            else {
                this.handlerMap.put(urlPath, resolvedHandler);
                if (logger.isInfoEnabled()) {
                    logger.info("Mapped URL path [" + urlPath + "] onto " + getHandlerDescription(handler));
                }
            }
        }
    }    
    
    
-----------------------------------------------------------------------------------------
AbstractUrlHandlerMapping 下面有2个子类

SimpleUrlHandlerMapping     把url和handler的对应关系 注册到父类中

    @Override
    //重写父类的方法 把 urlmap 注册到父类中
    public void initApplicationContext() throws BeansException {
        super.initApplicationContext();
        registerHandlers(this.urlMap);
    }
    
    
AbstractDetectingUrlHandlerMapping 把bean拿出来 按照规则 注册到父类中

protected void detectHandlers() throws BeansException {
        if (logger.isDebugEnabled()) {
            logger.debug("Looking for URL mappings in application context: " + getApplicationContext());
        }
        //获取容器中所有的bean
        String[] beanNames = (this.detectHandlersInAncestorContexts ?
                BeanFactoryUtils.beanNamesForTypeIncludingAncestors(getApplicationContext(), Object.class) :
                getApplicationContext().getBeanNamesForType(Object.class));

        // Take any bean name that we can determine URLs for.
        for (String beanName : beanNames) {
            // 模板方法 具体的url规则由子类确定
            String[] urls = determineUrlsForHandler(beanName);
            if (!ObjectUtils.isEmpty(urls)) {
                //注册到父类中
                registerHandler(urls, beanName);
            }
            else {
                if (logger.isDebugEnabled()) {
                    logger.debug("Rejected bean name '" + beanName + "': no URL paths identified");
                }
            }
        }
    }


----------------------------------------------------------------------------------------------------------
第二种类型的 HandlerMapping

AbstractHandlerMethodMapping 将method作为handler来用
这也是我们经常使用的 @RequestMapping 注解

这个抽象类也是继承了AbstractHandlerMapping
重写父类getHandlerInternal

protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {
    //根据request查找到url
        String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
        if (logger.isDebugEnabled()) {
            logger.debug("Looking up handler method for path " + lookupPath);
        }
        //获取读锁 这个地方为什么要上锁 欢迎指导
        this.mappingRegistry.acquireReadLock();
        try {
            //获取具体的method
            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);
        }
        finally {
            this.mappingRegistry.releaseReadLock();
        }
    }
    
------------------------------------------------------------------------------------------    
    
RequestMappingInfoHandlerMapping

他重写了父类的很多方法
    @Override
    protected boolean isHandler(Class<?> beanType) {
        //判断方法是否有 注解  
        return ((AnnotationUtils.findAnnotation(beanType, Controller.class) != null) ||
                (AnnotationUtils.findAnnotation(beanType, RequestMapping.class) != null));
    }

核心的方法还是在AbstractHandlerMethodMapping中


 

共有 人打赏支持
粉丝 0
博文 5
码字总数 3376
×
java_sheng
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: