zoukankan      html  css  js  c++  java
  • SpringMVC源码解读

    AbstractHandlerMapping实现HandlerMapping接口定的getHandler

      1. 提供getHandlerInternal模板方法给子类实现

      2. 如果没有获取Handler,则使用默认的defaultHandler

      3. 如果handler是string类型,从context获取实例

      4. 通过getHandlerExecutionChain封装handler,添加interceptor

    // AbstractHandlerMapping

     1     /**
     2      * Look up a handler for the given request, falling back to the default
     3      * handler if no specific one is found.
     4      * @param request current HTTP request
     5      * @return the corresponding handler instance, or the default handler
     6      * @see #getHandlerInternal
     7      */
     8     public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
     9         Object handler = getHandlerInternal(request);
    10         if (handler == null) {
    11             handler = getDefaultHandler();
    12         }
    13         if (handler == null) {
    14             return null;
    15         }
    16         // Bean name or resolved handler?
    17         if (handler instanceof String) {
    18             String handlerName = (String) handler;
    19             handler = getApplicationContext().getBean(handlerName);
    20         }
    21         return getHandlerExecutionChain(handler, request);
    22     }

    // AbstractHandlerMapping

     1     /**
     2      * Build a HandlerExecutionChain for the given handler, including applicable interceptors.
     3      * <p>The default implementation simply builds a standard HandlerExecutionChain with
     4      * the given handler, the handler mapping's common interceptors, and any {@link MappedInterceptor}s
     5      * matching to the current request URL. Subclasses may
     6      * override this in order to extend/rearrange the list of interceptors.
     7      * <p><b>NOTE:</b> The passed-in handler object may be a raw handler or a pre-built
     8      * HandlerExecutionChain. This method should handle those two cases explicitly,
     9      * either building a new HandlerExecutionChain or extending the existing chain.
    10      * <p>For simply adding an interceptor, consider calling {@code super.getHandlerExecutionChain}
    11      * and invoking {@link HandlerExecutionChain#addInterceptor} on the returned chain object.
    12      * @param handler the resolved handler instance (never {@code null})
    13      * @param request current HTTP request
    14      * @return the HandlerExecutionChain (never {@code null})
    15      * @see #getAdaptedInterceptors()
    16      */
    17     protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
    18         HandlerExecutionChain chain =
    19             (handler instanceof HandlerExecutionChain) ?
    20                 (HandlerExecutionChain) handler : new HandlerExecutionChain(handler);
    21 
    22         chain.addInterceptors(getAdaptedInterceptors());
    23 
    24         String lookupPath = urlPathHelper.getLookupPathForRequest(request);
    25         for (MappedInterceptor mappedInterceptor : mappedInterceptors) {
    26             if (mappedInterceptor.matches(lookupPath, pathMatcher)) {
    27                 chain.addInterceptor(mappedInterceptor.getInterceptor());
    28             }
    29         }
    30 
    31         return chain;
    32     }

    接下来看看AbstractUrlHandlerMapping实现的getHandlerInternal

    // AbstractUrlHandlerMapping

     1     /**
     2      * Look up a handler for the URL path of the given request.
     3      * @param request current HTTP request
     4      * @return the handler instance, or {@code null} if none found
     5      */
     6     @Override
     7     protected Object getHandlerInternal(HttpServletRequest request) throws Exception {
     8         // 根据request获取url
     9         String lookupPath = getUrlPathHelper().getLookupPathForRequest(request);
    10         // 根据url查找handler
    11         Object handler = lookupHandler(lookupPath, request);
    12         if (handler == null) {
    13             // 如果没有匹配到handler需要查找默认的,下面需要将PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE缓存到request
    14             // We need to care for the default handler directly, since we need to
    15             // expose the PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE for it as well.
    16             Object rawHandler = null;
    17             if ("/".equals(lookupPath)) {
    18                 rawHandler = getRootHandler();
    19             }
    20             if (rawHandler == null) {
    21                 rawHandler = getDefaultHandler();
    22             }
    23             if (rawHandler != null) {
    24                 // Bean name or resolved handler?
    25                 if (rawHandler instanceof String) {
    26                     String handlerName = (String) rawHandler;
    27                     rawHandler = getApplicationContext().getBean(handlerName);
    28                 }
    29                 // 预留的校验handler模板方法,没有使用
    30                 validateHandler(rawHandler, request);
    31                 // 添加expose属性到request的拦截器
    32                 handler = buildPathExposingHandler(rawHandler, lookupPath, lookupPath, null);
    33             }
    34         }
    35         if (handler != null && logger.isDebugEnabled()) {
    36             logger.debug("Mapping [" + lookupPath + "] to " + handler);
    37         }
    38         else if (handler == null && logger.isTraceEnabled()) {
    39             logger.trace("No handler mapping found for [" + lookupPath + "]");
    40         }
    41         return handler;
    42     }

    // AbstractUrlHandlerMapping

     1     /**
     2      * Look up a handler instance for the given URL path.
     3      * <p>Supports direct matches, e.g. a registered "/test" matches "/test",
     4      * and various Ant-style pattern matches, e.g. a registered "/t*" matches
     5      * both "/test" and "/team". For details, see the AntPathMatcher class.
     6      * <p>Looks for the most exact pattern, where most exact is defined as
     7      * the longest path pattern.
     8      * @param urlPath URL the bean is mapped to
     9      * @param request current HTTP request (to expose the path within the mapping to)
    10      * @return the associated handler instance, or {@code null} if not found
    11      * @see #exposePathWithinMapping
    12      * @see org.springframework.util.AntPathMatcher
    13      */
    14     protected Object lookupHandler(String urlPath, HttpServletRequest request) throws Exception {
    15         // Direct match? 直接根据url进行查找handler
    16         Object handler = this.handlerMap.get(urlPath);
    17         if (handler != null) {
    18             // Bean name or resolved handler?
    19             if (handler instanceof String) {
    20                 String handlerName = (String) handler;
    21                 handler = getApplicationContext().getBean(handlerName);
    22             }
    23             validateHandler(handler, request);
    24             return buildPathExposingHandler(handler, urlPath, urlPath, null);
    25         }
    26         // Pattern match? 通过表达式进行匹配具体通过AntPathMatcher实现,具体后面分析
    27         List<String> matchingPatterns = new ArrayList<String>();
    28         for (String registeredPattern : this.handlerMap.keySet()) {
    29             if (getPathMatcher().match(registeredPattern, urlPath)) {
    30                 matchingPatterns.add(registeredPattern);
    31             }
    32         }
    33         String bestPatternMatch = null;
    34         Comparator<String> patternComparator = getPathMatcher().getPatternComparator(urlPath);
    35         if (!matchingPatterns.isEmpty()) {
    36             Collections.sort(matchingPatterns, patternComparator);
    37             if (logger.isDebugEnabled()) {
    38                 logger.debug("Matching patterns for request [" + urlPath + "] are " + matchingPatterns);
    39             }
    40             // order序号最小的优先级最高
    41             bestPatternMatch = matchingPatterns.get(0);
    42         }
    43         if (bestPatternMatch != null) {
    44             handler = this.handlerMap.get(bestPatternMatch);
    45             // Bean name or resolved handler?
    46             if (handler instanceof String) {
    47                 String handlerName = (String) handler;
    48                 handler = getApplicationContext().getBean(handlerName);
    49             }
    50             validateHandler(handler, request);
    51             String pathWithinMapping = getPathMatcher().extractPathWithinPattern(bestPatternMatch, urlPath);
    52 
    53             // There might be multiple 'best patterns', let's make sure we have the correct URI template variables
    54             // for all of them
    55             Map<String, String> uriTemplateVariables = new LinkedHashMap<String, String>();
    56             for (String matchingPattern : matchingPatterns) {
    57                 if (patternComparator.compare(bestPatternMatch, matchingPattern) == 0) {
    58                     Map<String, String> vars = getPathMatcher().extractUriTemplateVariables(matchingPattern, urlPath);
    59                     Map<String, String> decodedVars = getUrlPathHelper().decodePathVariables(request, vars);
    60                     uriTemplateVariables.putAll(decodedVars);
    61                 }
    62             }
    63             if (logger.isDebugEnabled()) {
    64                 logger.debug("URI Template variables for request [" + urlPath + "] are " + uriTemplateVariables);
    65             }
    66             return buildPathExposingHandler(handler, bestPatternMatch, pathWithinMapping, uriTemplateVariables);
    67         }
    68         // No handler found...
    69         return null;
    70     }

    设计用于校验Handler,实际什么都没做,包括子类.

     1     /**
     2      * Validate the given handler against the current request.
     3      * <p>The default implementation is empty. Can be overridden in subclasses,
     4      * for example to enforce specific preconditions expressed in URL mappings.
     5      * @param handler the handler object to validate
     6      * @param request current HTTP request
     7      * @throws Exception if validation failed
     8      */
     9     protected void validateHandler(Object handler, HttpServletRequest request) throws Exception {
    10     }

    封装handler为HandlerExecutionChain,并添加PathExposingHandlerInterceptor和UriTemplateVariablesHandlerInterceptor拦截器.

     1     /**
     2      * Build a handler object for the given raw handler, exposing the actual
     3      * handler, the {@link #PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE}, as well as
     4      * the {@link #URI_TEMPLATE_VARIABLES_ATTRIBUTE} before executing the handler.
     5      * <p>The default implementation builds a {@link HandlerExecutionChain}
     6      * with a special interceptor that exposes the path attribute and uri template variables
     7      * @param rawHandler the raw handler to expose
     8      * @param pathWithinMapping the path to expose before executing the handler
     9      * @param uriTemplateVariables the URI template variables, can be {@code null} if no variables found
    10      * @return the final handler object
    11      */
    12     protected Object buildPathExposingHandler(Object rawHandler, String bestMatchingPattern,
    13             String pathWithinMapping, Map<String, String> uriTemplateVariables) {
    14 
    15         HandlerExecutionChain chain = new HandlerExecutionChain(rawHandler);
    16         chain.addInterceptor(new PathExposingHandlerInterceptor(bestMatchingPattern, pathWithinMapping));
    17         if (!CollectionUtils.isEmpty(uriTemplateVariables)) {
    18             chain.addInterceptor(new UriTemplateVariablesHandlerInterceptor(uriTemplateVariables));
    19         }
    20         return chain;
    21     }
  • 相关阅读:
    Android应用之个人应用软件开发(2)【签到功能和记账】
    抽象类判断日期能否被2整除
    Android应用之个人应用软件开发(3)【SQLite数据库及理财功能实现】
    移动终端网页游戏移植研发框架【服务器及客户端交互处理】
    DirectX学习资料
    列宁的故事
    Managed DirectX +C# 开发(入门篇)(七)
    Managed DirectX +C# 开发(入门篇)(六)
    Managed DirectX +C# 开发(入门篇)(三)
    C#不同窗口类中的变量相互调用
  • 原文地址:https://www.cnblogs.com/leftthen/p/5208376.html
Copyright © 2011-2022 走看看