Spring MVC的handlermapping之请求分发如何找到正确的Handler(BeanNameUrlHandlerMapping,SimpleUrlHandlerMapping)
2018-03-29 15:20
561 查看
本文讲的是Spring MVC如何找到正确的handler, 前面请求具体怎么进入到下面的方法,不再细说。
大概就是Spring mvc通过servlet拦截请求,实现doService方法,然后进入doDispatch()方法,这个是完成请求的方法.
今天我们只分析:mappedHandler = this.getHandler(processedRequest, false); 这一个方法;
protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { Iterator i$ = this.handlerMappings.iterator();//handlerMapping 是初始化的时候就保存好的,如果多个的话已经排序好了 HandlerExecutionChain handler; //实际上返回的handler是一个 handler链,包含了处理器和拦截器 do { if (!i$.hasNext()) { return null; } //这块发现实际上就是取第一个就好了 HandlerMapping hm = (HandlerMapping)i$.next(); if (this.logger.isTraceEnabled()) { this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name '" + this.getServletName() + "'"); } handler = hm.getHandler(request); //然后调用具体处理器的getHandler方法 } while(handler == null); return handler; }
现在以BeanNameUrlHandlerMapping为例:
这个类的继承关系前面几篇文章已经介绍过了。实际上父类AbstractHandlerMapping实现了gethandler方法,还记得这个类初始化的时候做的是初始化拦截器,然后让子类重写方法initApplicationContext进行处理注册
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception { Object handler = this.getHandlerInternal(request);//钩子方法,让子类自己去实现,查找处理器的逻辑 if (handler == null) { handler = this.getDefaultHandler(); } if (handler == null) { return null; } else { if (handler instanceof String) { String handlerName = (String)handler; handler = this.getApplicationContext().getBean(handlerName); } return this.getHandlerExecutionChain(handler, request);//封装 处理器链 } }
getHandlerInternal是由AbstractUrlHandlerMapping实现的, 他是BeanNameUrlHandlerMapping和SimpleUrlHandlerMapping的父类,所以,两个映射器都是通过这个方法查找的,
protected Object getHandlerInternal(HttpServletRequest request) throws Exception { String lookupPath = this.getUrlPathHelper().getLookupPathForRequest(request); //从请求中获取URL Object handler = this.lookupHandler(lookupPath, request); //查找handler if (handler == null) { //如果没找到 给一个默认的处理器 Object rawHandler = null; if ("/".equals(lookupPath)) { rawHandler = this.getRootHandler(); } if (rawHandler == null) { rawHandler = this.getDefaultHandler(); } if (rawHandler != null) { if (rawHandler instanceof String) { String handlerName = (String)rawHandler; rawHandler = this.getApplicationContext().getBean(handlerName); } this.validateHandler(rawHandler, request); handler = this.buildPathExposingHandler(rawHandler, lookupPath, lookupPath, (Map)null);//添加两个拦截器,作用? } } if (handler != null && this.logger.isDebugEnabled()) { this.logger.debug("Mapping [" + lookupPath + "] to " + handler); } else if (handler == null && this.logger.isTraceEnabled()) { this.logger.trace("No handler mapping found for [" + lookupPath + "]"); } return handler; }
protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception { Object handler = this.handlerMap.get(urlPath); //直接从map中获取 if (handler != null) { if (handler instanceof String) { String handlerName = (String)handler; handler = this.getApplicationContext().getBean(handlerName); } this.validateHandler(handler, request); return this.buildPathExposingHandler(handler, urlPath, urlPath, (Map)null);//添加拦截器 } else { List<String> matchingPatterns = new ArrayList(); //如果没找到就遍历所有的map的url,进行匹配 Iterator i$ = this.handlerMap.keySet().iterator(); while(i$.hasNext()) { String registeredPattern = (String)i$.next(); if (this.getPathMatcher().match(registeredPattern, urlPath)) { matchingPatterns.add(registeredPattern); } } String bestPatternMatch = null; Comparator<String> patternComparator = this.getPathMatcher().getPatternComparator(urlPath); if (!matchingPatterns.isEmpty()) { Collections.sort(matchingPatterns, patternComparator); if (this.logger.isDebugEnabled()) { this.logger.debug("Matching patterns for request [" + urlPath + "] are " + matchingPatterns); } bestPatternMatch = (String)matchingPatterns.get(0); //如果有匹配的上的,取第一个 } if (bestPatternMatch != null) { handler = this.handlerMap.get(bestPatternMatch); String pathWithinMapping; if (handler instanceof String) { pathWithinMapping = (String)handler; handler = this.getApplicationContext().getBean(pathWithinMapping); } this.validateHandler(handler, request); pathWithinMapping = this.getPathMatcher().extractPathWithinPattern(bestPatternMatch, urlPath); Map<String, String> uriTemplateVariables = new LinkedHashMap(); Iterator i$ = matchingPatterns.iterator(); while(i$.hasNext()) { String matchingPattern = (String)i$.next(); if (patternComparator.compare(bestPatternMatch, matchingPattern) == 0) { Map<String, String> vars = this.getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath); Map<String, String> decodedVars = this.getUrlPathHelper().decodePathVariables(request, vars); uriTemplateVariables.putAll(decodedVars); } } if (this.logger.isDebugEnabled()) { this.logger.debug("URI Template variables for request [" + urlPath + "] are " + uriTemplateVariables); } return this.buildPathExposingHandler(handler, bestPatternMatch, pathWithinMapping, uriTemplateVariables); } else { return null; } } }
到此为止就找到了handler,并且添加了拦截器
相关文章推荐
- Spring MVC的handlermapping之请求分发如何找到正确的Handler(RequestMappingHandlerMapping)
- spring mvc的HandlerMapping的使用之--BeanNameUrlHandlerMapping
- HandlerMapping和BeanNameUrlHandlerMapping的使用
- Spring MVC的handlermapping之SimpleUrlHandlerMapping初始化
- Spring Web MVC 的HandlerMapping的使用之-------BeanNameUrlHandlerMapping
- HandlerMapping和BeanNameUrlHandlerMapping的使用
- Spring MVC-处理程序映射(Handler Mapping)-Bean名称Url处理程序映射(Bean Name Url Handler Mapping)示例(转载实践)
- HandlerMapping和BeanNameUrlHandlerMapping的使用
- Error creating bean with name 'simpleUrlHandlerMapping' defined in ServletContext resource [/WEB-IN
- Spring Web MVC 的HandlerMapping的使用之-------BeanNameUrlHandlerMapping
- Spring MVC: step by step 5-BeanNameUrlHandlerMapping(我的最爱)
- spring mvc基础篇(五):映射处理器之BeanNameUrlHandlerMapping
- spring mvc问题之为何多注入了一个BeanNameUrlHandlerMapping?
- HandlerMapping和BeanNameUrlHandlerMapping的使用
- Spring MVC BeanNameUrlHandlerMapping example
- Spring mvc (五) [ControllerClassNameHandlerMapping根据Controller类名匹配,解决了bean的递增配置问题]
- spring MVC关于org.springframework.web.servlet.handler.SimpleUrlHandlerMapping的使用
- Spring MVC中用SimpleUrlHandlerMapping实现单纯的页面跳转
- Spring MVC-处理程序映射(Handler Mapping)-简单的Url处理程序映射(Simple Url Handler Mapping)示例(转载实践)
- SpringMVC默认依赖Bean:BeanNameUrlHandlerMapping