BeanNameUrlHandlerMapping运行原理

本文详细描述了SpringMVC中DispatcherServlet如何获取并处理请求,包括Handler的查找、HandlerExecutionChain的构建,以及跨域(CORS)配置的过程。
org.springframework.web.servlet.DispatcherServlet.doDispatch{
    // 根据请求对象获取能处理这个请求的Handler,可能是一个HandlerMethod对象,也可能是一个Handler类,它实现了Controller接口等等
   HandlerExecutionChain mappedHandler = getHandler(processedRequest);{
        if (this.handlerMappings != null) {
            // 遍历我们初始化的HandlerMapping,如果不自定义,默认就是提供了三个
            for (HandlerMapping mapping : this.handlerMappings) {
                HandlerExecutionChain handler = mapping.getHandler(request);{
                    // 返回Object是因为getHandlerInternal是一个抽象方法
                    // 处理请求的Handler可能是一个beanName->Bean,也可能是一个实现了Controller接口的对象,等等
                    Object handler = getHandlerInternal(request);{
                        String lookupPath = initLookupPath(request);
                        Object handler = lookupHandler(lookupPath, request);{
                            Object handler = getDirectMatch(lookupPath, request);{
                                // 这个就是在BeanNameUrlHandlerMapping保存的映射信息的map,直接从那里面获取
                                Object handler = this.handlerMap.get(urlPath);
                                if (handler != null) {
                                    if (handler instanceof String) {
                                        String handlerName = (String) handler;
                                        handler = obtainApplicationContext().getBean(handlerName);
                                    }
                                    // 校验handler,空实现
                                	validateHandler(handler, request);
                                	return buildPathExposingHandler(handler, urlPath, urlPath, null);{
                                	    // 通过handler构建HandlerExecutionChain对象
                                	    HandlerExecutionChain chain = new HandlerExecutionChain(rawHandler);
                                	    // 添加一个拦截器,这个拦截器是在请求之前,在request存入一些东西
                                	    // exposePathWithinMapping(this.bestMatchingPattern, this.pathWithinMapping, request);
                                        // request.setAttribute(BEST_MATCHING_HANDLER_ATTRIBUTE, handler);
                                        // request.setAttribute(INTROSPECT_TYPE_LEVEL_MAPPING, supportsTypeLevelMappings());
                                	    chain.addInterceptor(new PathExposingHandlerInterceptor(bestMatchingPattern, pathWithinMapping));
                                	    // 如果beanName存在路径变量,但是这个方法传递的实null,表明不可以有路径变量
                                        if (!CollectionUtils.isEmpty(uriTemplateVariables)) {
                                             // 还要单独添加一个拦截器来处理
                                             // 设置路径变量到请求域中
                                             // request.setAttribute(URI_TEMPLATE_VARIABLES_ATTRIBUTE, uriTemplateVariables);
                                             chain.addInterceptor(new UriTemplateVariablesHandlerInterceptor(uriTemplateVariables));
                                        }
                                	}
                               }
                            }
                            if (handler != null) {
                            	return handler;
                            }
                        }

                    }
                    // 找了很多资料,没有找到可能成立的情况,可能是兼容老版本的配置,因为上面的Handler都会判断如果为string就从spring容器获取
                    if (handler instanceof String) {
                        String handlerName = (String) handler;
                        handler = obtainApplicationContext().getBean(handlerName);
                    }
                    // 将handler以及拦截器封装成一个HandlerExecutionChain对象
                    HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);{
                        HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ? (HandlerExecutionChain) handler : new HandlerExecutionChain(handler));
                        for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
                            // 如果是MappedInterceptor这种蓝接触器
                            if (interceptor instanceof MappedInterceptor) {
                                MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
                                // 判断这个拦截器是否可以作用当前请求
                                if (mappedInterceptor.matches(request)) {
                                    // 添加进去拦截器
                                    chain.addInterceptor(mappedInterceptor.getInterceptor());
                                    return;
                                }
                            }
                           chain.addInterceptor(interceptor);
                        }
                        return chain;
                    }
                    // 是否有跨域配置
                    if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
                        CorsConfiguration config = getCorsConfiguration(handler, request);
                        config.validateAllowCredentials();
                        // 添加一个跨域拦截器
                        executionChain = getCorsHandlerExecutionChain(request, executionChain, config);{
                            chain.addInterceptor(0, new CorsInterceptor(config));
                        }
                    }
                    return executionChain;
                }
                // 返回handler
                if (handler != null) {
                    return handler;
                }
            }
        }
   }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值