::: warning 知识点总结 , getHandler方法的主要作用体现在以下几点:
- 首先 , 从当前Request中拿到请求的 URL
- 然后 , 从映射关系中拿到 HandlerMethod对象
- 接着 , 把 HandlerMethod对象封装到 HandlerExecutionChain执行链中
- 最后 , 在 HandlerExecutionChain执行链的创建过程中会拿到整个容器中所有的拦截器(实现 HandlerInterceptor接口的拦截器) , 和当前请求的 URL进行匹配 , 如果匹配成功的话 , 就会把拦截器放到 HandlerExecutionChain的数组中 。:::
进入 getHandler方法
所在类:org.springframework.web.servlet. DispatcherServlet
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {// handlerMappering 实例容器不为空if (this.handlerMappings != null) {for (HandlerMapping mapping : this.handlerMappings) {// 获取 HandlerMethod 和过滤器链的包装类HandlerExecutionChain handler = mapping.getHandler(request);if (handler != null) {return handler;}}}return null;}
进入 getHandler方法
所在类:org.springframework.web.servlet.handler. AbstractHandlerMapping
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {// 根据请求的 URL 拿到对应的 HandlerMethod 对象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);}// 获取 HandlerMethod 和过滤器链的包装类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());}// 是否是跨域请求,就是查看 request 请求头中是否有 Origin 属性if (CorsUtils.isCorsRequest(request)) {CorsConfiguration globalConfig = this.corsConfigurationSource.getCorsConfiguration(request);CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);executionChain = getCorsHandlerExecutionChain(request, executionChain, config);}return executionChain;}
进入 getHandlerInternal方法
所在类:org.springframework.web.servlet.handler. AbstractHandlerMethodMapping
protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception {// 从request对象中获取 URL , /common/query2String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);this.mappingRegistry.acquireReadLock();try {// 根据 URL 从映射关系中找到对应的 HandlerMethod 对象HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request);// 执行beanFactory.getBean的过程 , 获取Controller实例return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null);}finally {this.mappingRegistry.releaseReadLock();}}
::: warning 知识点lookupHandlerMethod方法之所以可以从映射关系中拿到 HandlerMethod对象 , 是因为 AbstractHandlerMethodMapping类实现了 InitializingBean接口 , 在 afterPropertiesSet方法里建立好了映射关系 。:::
进入 lookupHandlerMethod方法
所在类:org.springframework.web.servlet.handler. AbstractHandlerMethodMapping
protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception {List<Match> matches = new ArrayList<>();List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath);if (directPathMatches != null) {// 匹配过程 , 是否符合 RequestMappingInfo 里的属性值addMatchingMappings(directPathMatches, matches, request);}if (matches.isEmpty()) {// No choice but to go through all mappings...addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request);}if (!matches.isEmpty()) {Comparator<Match> comparator = new MatchComparator(getMappingComparator(request));matches.sort(comparator);Match bestMatch = matches.get(0);if (matches.size() > 1) {if (logger.isTraceEnabled()) {logger.trace(matches.size() + " matching mappings: " + matches);}if (CorsUtils.isPreFlightRequest(request)) {return PREFLIGHT_AMBIGUOUS_MATCH;}Match secondBestMatch = matches.get(1);// 如果两个 RequestMappinginfo 什么都相同 , 报错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.getMappings().keySet(), lookupPath, request);}}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Spring Security 中如何细化权限粒度?
- springcloud微服务架构开发实战:分布式消息总线
- 怎么理解Laravel的核心架构
- 原来这才是Spring Boot使用AOP的正确姿势
- 使用spring cache让我的接口性能瞬间提升了100倍
- Springboot 实现数据库备份还原
- 微服务架构图
- 全网最全一篇数据库MVCC详解,不全你打我
- SpringCloud开发框架入门知识
- SpringMVC:进阶