SpringMVC之源码分析--HandlerMapping(六)
概述
上一节我们分析了RequestMappingHandlerMapping的初始化过程,即创建并注册HandlerMehtod,本章我们分析下RequestMappingHandlerMapping的请求处理过程,即查找HandlerMethod。
本系列文章是基于Spring5.0.5RELEASE。
总体流程
流程描述:
- 用户请求到达前端控制器DispatcherServlet.doDispatch方法
- 在doDispatch方法中调用本类的getHandler方法
- getHandler方法调用HandlerMapping的getHandler方法
- HandlerMapping.getHandler方法由抽象类AbstractHandlerMapping实现,故最终调用AbstracthandlerMapping.getHandler方法
- 在AbstractHandlerMapping的getHandler方法中调用钩子函数getHandlerInternal方法,该方法由子类AbstractHandlerMethodMapping实现
- 最终由AbstracthandlerMethodMapping.getHandlerInternal返回处理器方法即HandlerMethod
- HandlerMethod代表查找到的处理请求Controller中的方法
- 返回给AbstractHandlerMapping,最终由其将处理器方法和拦截器组装成HandlerExectionChain对象返回
源码分析
- DispatcherServlet
处理用户请求的方法到达doDispatch方法,源码如下:
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { // ... ... //查找请求的处理器 mappedHandler = getHandler(processedRequest); if (mappedHandler == null) { // 未找到处理器时跑异常 noHandlerFound(processedRequest, response); return; } // ... ... } @Nullable protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { if (this.handlerMappings != null) { // 迭代Spring支持的HandlerMapping,即我们配置或默认的HandlerMapping for (HandlerMapping hm : this.handlerMappings) { if (logger.isTraceEnabled()) { logger.trace( "Testing handler map [" + hm + "] in DispatcherServlet with name '" + getServletName() + "'"); } // 查找请求的处理器HandlerExecutionChain,包括请求需要的拦截器 HandlerExecutionChain handler = hm.getHandler(request); if (handler != null) { return handler; } } } return null; }
- AbstractHandlerMethodMapping
提供查出处理器模板方法,具体实现由子类实现getHandlerInternal方法实现,代码如下:
@Override @Nullable public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { // 子类需实现getHandlerInternal方法,本例中由AbstractHandlerMethodMapping实现 Object handler = getHandlerInternal(request); if (handler == null) { handler = getDefaultHandler(); } if (handler == null) { return null; } // 如果handler是bean名字,则根据名字从上下文获取到处理类 if (handler instanceof String) { String handlerName = (String) handler; handler = obtainApplicationContext().getBean(handlerName); } // 返回请求处理的HandlerExecutionChain对象 HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request); // 对跨域的处理 if (CorsUtils.isCorsRequest(request)) { CorsConfiguration globalConfig = this.globalCorsConfigSource.getCorsConfiguration(request); CorsConfiguration handlerConfig = getCorsConfiguration(handler, request); CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig); executionChain = getCorsHandlerExecutionChain(request, executionChain, config); } return executionChain; }
- AbstractHandlerMethodMapping
本类主要提供创建并注册HandlerMethod以及查找HandlerMethod功能,处理用户请求时,源码如下:
/** * 实现父类(AbstractHandlerMapping)的钩子函数 */ @Override protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception { // 使用工具类UrlPathHelper,解析用户请求url String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); if (logger.isDebugEnabled()) { logger.debug("Looking up handler method for path " + lookupPath); } this.mappingRegistry.acquireReadLock(); try { // 查找HandlerMethod核心方法 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(); } } /** * 查找当前请求的处理器方法 */ @Nullable protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception { // 定义匹配到的matches集合,其内存放匹配到的Match对象 List<Match> matches = new ArrayList<>(); // 根据请求url查找出RequestMappingInfo对象 List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath); if (directPathMatches != null) { // 将查找到的RequestMappingInfo和处理器方法封装成Match对象存入到matches数组 addMatchingMappings(directPathMatches, matches, request); } // 为查询到RequestMappingInfo时 if (matches.isEmpty()) { // this.mappingRegistry.getMappings().keySet()--返回已注册所有的RequestMappingInfo // 查找到将RequestMappingInfo和处理器方法封装后存入matches数组 addMatchingMappings(this.mappingRegistry.getMappings().keySet(), matches, request); } // 有匹配对象 if (!matches.isEmpty()) { // 排序处理 Comparator<Match> comparator = new MatchComparator(getMappingComparator(request)); matches.sort(comparator); if (logger.isTraceEnabled()) { logger.trace("Found " + matches.size() + " matching mapping(s) for [" + lookupPath + "] : " + matches); } // 取出Match,其封装了RequestMappingInfo和处理器方法 Match bestMatch = matches.get(0); if (matches.size() > 1) { 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(); throw new IllegalStateException("Ambiguous handler methods mapped for HTTP path '" + request.getRequestURL() + "': {" + m1 + ", " + m2 + "}"); } } // 主要是往Request的Attribute区放了些东西,具体啥用我也不懂 handleMatch(bestMatch.mapping, lookupPath, request); // 返回处理器方法HandlerMethod return bestMatch.handlerMethod; } else { // 未找到处理 return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request); } }
总结
本节对RequestMappingHandlerMapping处理用户请求时的整体流程及核心源码进行了分析,如有问题或建议大家可扫描下方二维码进群反馈,我会知无不言言无不尽,希望对大家有所帮助。
最后创建了qq群方便大家交流,可扫描加入,同时也可加我qq:276420284,共同学习、共同进步,谢谢!
相关推荐
瓜牛呱呱 2020-11-12
柳木木的IT 2020-11-04
yifouhu 2020-11-02
lei0 2020-11-02
源码zanqunet 2020-10-28
源码zanqunet 2020-10-26
一叶梧桐 2020-10-14
码代码的陈同学 2020-10-14
lukezhong 2020-10-14
lzzyok 2020-10-10
anchongnanzi 2020-09-21
clh0 2020-09-18
changcongying 2020-09-17
星辰大海的路上 2020-09-13
abfdada 2020-08-26
mzy000 2020-08-24
shenlanse 2020-08-18
zhujiangtaotaise 2020-08-18
xiemanR 2020-08-17