zoukankan      html  css  js  c++  java
  • Spring MVC的handlermapping之请求分发如何找到正确的Handler(BeanNameUrlHandlerMapping,SimpleUrlHandlerMapping)

    本文讲的是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,并且添加了拦截器
  • 相关阅读:
    k8s dashboard 配置使用kubeconfig文件登录
    Spring Cloud 专题之七:Sleuth 服务跟踪
    Spring Cloud 专题之六:bus 消息总线
    Spring Cloud专题之五:config 配置中心
    Docker Storage Driver:存储驱动
    Docker引擎升级教程
    Docker介绍及安装详解
    Autowired和Resource的区别和联系
    OLTP与OLAP
    转载-JAVA 关于JNI本地库加载
  • 原文地址:https://www.cnblogs.com/haoerlv/p/8670003.html
Copyright © 2011-2022 走看看