org.springframework.web.servlet.DispatcherServlet-doDispatch-getHandler方法

    技术2023-03-27  114

    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { /** * 声明变量 HttpServletRequest HandlerExecutionChain Handler执行链包含和最扣执行的Handler */ HttpServletRequest processedRequest = request; HandlerExecutionChain mappedHandler = null; //是不是一个多组件请求 boolean multipartRequestParsed = false; //异步管理器 WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request); try { //视图 ModelAndView mv = null; //异常 Exception dispatchException = null; try { /** * 1.检查是否上传请求 */ processedRequest = checkMultipart(request); multipartRequestParsed = (processedRequest != request); // Determine handler for the current request. /** * 2.根据processedRequest获取映射的Handler执行链 HandlerExecutionChain * 有当前请求的Handler和Inteceptor */ mappedHandler = getHandler(processedRequest);

    getHandler方法

    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { if (this.handlerMappings != null) { /** * 遍历handlerMappings 映射器 */ for (HandlerMapping mapping : this.handlerMappings) { //根据请求获取HandlerExecutionChain HandlerExecutionChain handler = mapping.getHandler(request); if (handler != null) { return handler; } } } return null; }

    request中有请求的url

    org.springframework.web.servlet.handler.AbstractHandlerMapping#getHandler

    public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { /** * 根据请求获取Handler */ 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); } /** * 获取HandlerExecutionChain */ 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()); } /** * 跨域配置 */ 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; }

    org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#getHandlerInternal方法

    protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception { /** * 获取请求的url如 /demo/handler01 */ String lookupPath = getUrlPathHelper().getLookupPathForRequest(request); this.mappingRegistry.acquireReadLock(); try { /** * 查询和url reqeust匹配的HandlerMthod */ HandlerMethod handlerMethod = lookupHandlerMethod(lookupPath, request); //返回 return (handlerMethod != null ? handlerMethod.createWithResolvedBean() : null); } finally { this.mappingRegistry.releaseReadLock(); } }

    org.springframework.web.servlet.handler.AbstractHandlerMethodMapping#lookupHandlerMethod方法

    protected HandlerMethod lookupHandlerMethod(String lookupPath, HttpServletRequest request) throws Exception { List<Match> matches = new ArrayList<>(); /** * 根据URL获取匹配 ,可以匹配到多个 * 通过uri直接在注册的RequestMapping中获取对应的RequestMappingInfo列表,需要注意的是, * 这里进行查找的方式只是通过url进行查找,但是具体哪些RequestMappingInfo是匹配的,还需要进一步过滤 */ List<T> directPathMatches = this.mappingRegistry.getMappingsByUrl(lookupPath); if (directPathMatches != null) { /** * 如果匹配的就添到上面的集合中 */ addMatchingMappings(directPathMatches, matches, request); } if (matches.isEmpty()) { // 如果无法通过uri进行直接匹配,则对所有的注册的RequestMapping进行匹配,这里无法通过uri // 匹配的情况主要有三种: // ①在RequestMapping中定义的是PathVariable,如/user/detail/{id}; // ②在RequestMapping中定义了问号表达式,如/user/?etail; // ③在RequestMapping中定义了*或**匹配,如/user/detail/** // 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); /** * 会判断前两个是否相似度是一样的,如果是一样的,则直接抛出异常,如果不相同, */ 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); //这里主要是对匹配结果的一个处理,主要包含对传入参数和返回的MediaType的处理 handleMatch(bestMatch.mapping, lookupPath, request); return bestMatch.handlerMethod; } else { return handleNoMatch(this.mappingRegistry.getMappings().keySet(), lookupPath, request); } }

    这里对于结果的匹配,首先会通过uri进行直接匹配,如果能匹配到,则在匹配结果中尝试进行RequestMethod,Consumes和Produces等配置的匹配;如果通过uri不能匹配到,则直接对所有定义的RequestMapping进行匹配,这里主要是进行正则匹配,如果能匹配到。如果能够匹配到,则对匹配结果按照相似度进行排序,并且对前两个结果相似度进行比较,如果相似度一样,则抛出异常,如果不一样,则返回相似度最高的一个匹配结果。如果无法获取到匹配结果,则对所有的匹配结果进行遍历,判断当前request具体是哪一部分参数无法匹配到结果。对于匹配结果的获取,主要在addMatchingMappings()方法中

    addMatchingMappings方法

    private void addMatchingMappings(Collection<T> mappings, List<Match> matches, HttpServletRequest request) { for (T mapping : mappings) { T match = getMatchingMapping(mapping, request); if (match != null) { matches.add(new Match(match, this.mappingRegistry.getMappings().get(mapping))); } } }

    Processed: 0.013, SQL: 9