本文讲的是Spring MVC如何找到正确的handler, 前面请求具体怎么进入到下面的方法,不再细说。
大概就是Spring mvc通过servlet拦截请求,实现doService方法,然后进入doDispatch()方法,这个是完成请求的方法.
今天我们只分析:mappedHandler = this.getHandler(processedRequest, false); 这一个方法;
1 protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { 2 Iterator i$ = this.handlerMappings.iterator();//handlerMapping 是初始化的时候就保存好的,如果多个的话已经排序好了 3 4 HandlerExecutionChain handler; //实际上返回的handler是一个 handler链,包含了处理器和拦截器 5 do { 6 if (!i$.hasNext()) { 7 return null; 8 } 9 //这块发现实际上就是取第一个就好了 10 HandlerMapping hm = (HandlerMapping)i$.next(); 11 if (this.logger.isTraceEnabled()) { 12 this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name '" + this.getServletName() + "'"); 13 } 14 15 handler = hm.getHandler(request); //然后调用具体处理器的getHandler方法 16 } while(handler == null); 17 18 return handler; 19 }
现在以BeanNameUrlHandlerMapping为例:
这个类的继承关系前面几篇文章已经介绍过了。实际上父类AbstractHandlerMapping实现了gethandler方法,还记得这个类初始化的时候做的是初始化拦截器,然后让子类重写方法initApplicationContext进行处理注册
1 public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { 2 Object handler = this.getHandlerInternal(request);//钩子方法,让子类自己去实现,查找处理器的逻辑 3 if (handler == null) { 4 handler = this.getDefaultHandler(); 5 } 6 7 if (handler == null) { 8 return null; 9 } else { 10 if (handler instanceof String) { 11 String handlerName = (String)handler; 12 handler = this.getApplicationContext().getBean(handlerName); 13 } 14 15 return this.getHandlerExecutionChain(handler, request);//封装 处理器链 16 } 17 }
getHandlerInternal是由AbstractUrlHandlerMapping实现的, 他是BeanNameUrlHandlerMapping和SimpleUrlHandlerMapping的父类,所以,两个映射器都是通过这个方法查找的,
1 protected Object getHandlerInternal(HttpServletRequest request) throws Exception { 2 String lookupPath = this.getUrlPathHelper().getLookupPathForRequest(request); //从请求中获取URL 3 Object handler = this.lookupHandler(lookupPath, request); //查找handler 4 if (handler == null) { //如果没找到 给一个默认的处理器 5 Object rawHandler = null; 6 if ("/".equals(lookupPath)) { 7 rawHandler = this.getRootHandler(); 8 } 9 10 if (rawHandler == null) { 11 rawHandler = this.getDefaultHandler(); 12 } 13 14 if (rawHandler != null) { 15 if (rawHandler instanceof String) { 16 String handlerName = (String)rawHandler; 17 rawHandler = this.getApplicationContext().getBean(handlerName); 18 } 19 20 this.validateHandler(rawHandler, request); 21 handler = this.buildPathExposingHandler(rawHandler, lookupPath, lookupPath, (Map)null);//添加两个拦截器,作用? 22 } 23 } 24 25 if (handler != null && this.logger.isDebugEnabled()) { 26 this.logger.debug("Mapping [" + lookupPath + "] to " + handler); 27 } else if (handler == null && this.logger.isTraceEnabled()) { 28 this.logger.trace("No handler mapping found for [" + lookupPath + "]"); 29 } 30 31 return handler; 32 }
1 protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception { 2 Object handler = this.handlerMap.get(urlPath); //直接从map中获取 3 if (handler != null) { 4 if (handler instanceof String) { 5 String handlerName = (String)handler; 6 handler = this.getApplicationContext().getBean(handlerName); 7 } 8 9 this.validateHandler(handler, request); 10 return this.buildPathExposingHandler(handler, urlPath, urlPath, (Map)null);//添加拦截器 11 } else { 12 List<String> matchingPatterns = new ArrayList(); //如果没找到就遍历所有的map的url,进行匹配 13 Iterator i$ = this.handlerMap.keySet().iterator(); 14 15 while(i$.hasNext()) { 16 String registeredPattern = (String)i$.next(); 17 if (this.getPathMatcher().match(registeredPattern, urlPath)) { 18 matchingPatterns.add(registeredPattern); 19 } 20 } 21 22 String bestPatternMatch = null; 23 Comparator<String> patternComparator = this.getPathMatcher().getPatternComparator(urlPath); 24 if (!matchingPatterns.isEmpty()) { 25 Collections.sort(matchingPatterns, patternComparator); 26 if (this.logger.isDebugEnabled()) { 27 this.logger.debug("Matching patterns for request [" + urlPath + "] are " + matchingPatterns); 28 } 29 30 bestPatternMatch = (String)matchingPatterns.get(0); //如果有匹配的上的,取第一个 31 } 32 33 if (bestPatternMatch != null) { 34 handler = this.handlerMap.get(bestPatternMatch); 35 String pathWithinMapping; 36 if (handler instanceof String) { 37 pathWithinMapping = (String)handler; 38 handler = this.getApplicationContext().getBean(pathWithinMapping); 39 } 40 41 this.validateHandler(handler, request); 42 pathWithinMapping = this.getPathMatcher().extractPathWithinPattern(bestPatternMatch, urlPath); 43 Map<String, String> uriTemplateVariables = new LinkedHashMap(); 44 Iterator i$ = matchingPatterns.iterator(); 45 46 while(i$.hasNext()) { 47 String matchingPattern = (String)i$.next(); 48 if (patternComparator.compare(bestPatternMatch, matchingPattern) == 0) { 49 Map<String, String> vars = this.getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath); 50 Map<String, String> decodedVars = this.getUrlPathHelper().decodePathVariables(request, vars); 51 uriTemplateVariables.putAll(decodedVars); 52 } 53 } 54 55 if (this.logger.isDebugEnabled()) { 56 this.logger.debug("URI Template variables for request [" + urlPath + "] are " + uriTemplateVariables); 57 } 58 59 return this.buildPathExposingHandler(handler, bestPatternMatch, pathWithinMapping, uriTemplateVariables); 60 } else { 61 return null; 62 } 63 } 64 }
到此为止就找到了handler,并且添加了拦截器