资讯专栏INFORMATION COLUMN

SpringMVC之源码分析--HandlerMapping(一)

ralap / 3353人阅读

摘要:接口接口作用是将请求映射到处理程序,以及预处理和处理后的拦截器列表,映射是基于一些标准的,其中的细节因不同的实现而不相同。该参数是类型,作用是检查所有的映射解析器或使用或为的,默认为,即从上下文中检查所有的。

概述

在Spring MVC启动章节https://segmentfault.com/a/1190000014674239,介绍到了DispatcherServlet的onRefresh方法调用initStrategies方法,初始Spring MVC九大策略解析器,本章在此基础上分析初始化HandlerMapping组件过程,本系列文章是基于Spring5.0.5RELEASE。

接口

HandlerMapping接口作用是将请求映射到处理程序,以及预处理和处理后的拦截器列表,映射是基于一些标准的,其中的细节因不同的实现而不相同。这是官方文档上一段描述,该接口只有一个方法getHandler(request),返回一个HandlerExecutionChain对象,接口本身很简单,源码如下:

public interface HandlerMapping {

    省略属性...

    // 返回请求的一个处理程序handler和拦截器interceptors
    @Nullable
    HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
}
初始化

初始化HandlerMapping的入口方法是DispatcherServlet的initHandlerMappings(ApplicationContext context)方法,该方法源码如下:

private void initHandlerMappings(ApplicationContext context) {
    this.handlerMappings = null;
    // detectAllHandlerMappings默认为true,可通过DispatcherServlet的init-param参数进行设置
    if (this.detectAllHandlerMappings) {
        // 在ApplicationContext中找到所有的handlerMapping,包括父上下文。
        Map matchingBeans =
                BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
        if (!matchingBeans.isEmpty()) {
            this.handlerMappings = new ArrayList<>(matchingBeans.values());
            // 对handlerMapping排序,可通过指定order属性进行设置,order的值为int型,数越小优先级越高
            AnnotationAwareOrderComparator.sort(this.handlerMappings);
        }
    }
    // detectAllHandlerMappings=false时
    else { 
        try {
            // 从ApplicationContext上下文中取id(或name)="handlerMapping"的bean
            HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
            // 将hm转换成list,并赋值给属性handlerMappings
            this.handlerMappings = Collections.singletonList(hm);
        }
        catch (NoSuchBeanDefinitionException ex) {
            // Ignore, we"ll add a default HandlerMapping later.
        }
    }

    // 从context上下文中定义HandlerMapping时,Spring MVC将使用默认HandlerMapping,默认的HandlerMapping在DispatcherServlet.properties属性文件中定义,
    // 该文件是在DispatcherServlet的static静态代码块中加载的
    // 默认的是:BeanNameUrlHandlerMapping和RequestMappingHandlerMapping
    if (this.handlerMappings == null) {
        this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
        if (logger.isDebugEnabled()) {
            logger.debug("No HandlerMappings found in servlet "" + getServletName() + "": using default");
        }
    }
}

至此,我们基本分析了HandlerMapping的初始化过程,接下来针对分析中提到的点进行验证,以检验我们的分析是正确的。

实战

项目结构

代码分析

pom配置文件

引入Spring MVC支持,代码如下:


    org.springframework
    spring-webmvc
    5.0.5.RELEASE

spring配置文件

spring-servlet.xml是Spring MVC的配置文件,在验证过程中会修改此文件内容,内容根据验证目的会有改变,具体参见验证场景的配置。

web配置文件

web.xml是部署描述文件,主要配置了Spring MVC的DispatcherServlet,代码如下:


    
    dispatcher
    
    org.springframework.web.servlet.DispatcherServlet
    
    
        contextConfigLocation
        classpath:spring-servlet.xml
    
    
    1
    true



    
    dispatcher
    
    /

Controller控制器

本例使用的是SimpleUrlHandlerMapping映射处理器,所以我们的Controller会继承org.springframework.web.servlet.mvc.Controller类,并实现handlerRequest方法,代码如下:

public class DemoController implements Controller{

    @Nullable
    @Override
    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
        request.getServletContext().log("进入Controller(Handler)处理器。。。");
        return null;
    }
}

验证

默认映射处理器

在我们没有对HandlerMapping进行配置时,Spring会使用默认的HandlerMapping策略,此时我们的Spring配置文件(spring-servlet.xml)没有任何内容,此时我们启动应用,通过断点方式验证,结果如下:

Spring MVC默认配置为:

从结果可知,在未进行任何配置HandlerMapping时,系统使用(支持)默认的BeanNameUrlHandlerMapping和RequestMappingHandlerMapping映射解析器。

detectAllHandlerMappings

该参数是boolean类型,作用是检查所有的HandlerMappings映射解析器或使用id或name为"handlerMappping"的bean,默认为true,即从context上下文中检查所有的HandlerMapping。

我们先通过修改此参数为false,即在web.xml配置DispatcherServlet时,设置init-param参数,代码如下:



    detectAllHandlerMappings
    false

在Spring配置文件spring-servlet.xml中定义映射处理器,以SimpleUrlHandlerMapping为例,代码如下:



    
        
            demoController
        
    
    
    



打上断点,以debug模式启动服务,结果如下:

从结果可知,Spring取到了我们配置的HandlerMapping(SimpleUrlHandlerMapping)并转换为List赋值给属性参数handlerMappings。

加载所有映射处理器

此场景需要我们配置多个映射处理器,Spring配置文件代码如下:


    
        
            demoController
        
    
    



    

注意将web.xml配置的DispatcherServlet的detectAllHandlerMappings注释掉或设置为true

打上断点,以debug模式启动服务,结果如下:

从两种截图中可知,Spring取出了我们配置的所有的映射解析器,对比两种图,可知经过排序,Spring实现了我们指定的解析器的order。

总结

本小节分析了HandlerMapping的初始化,过程主要以SimpleUrlHandlerMapping实现类为例,替换成其他的实现类,启动过程也是一样的,后续会对实现类逐个进行分析,希望本章对大家能有帮助。

最后创建了qq群方便大家交流,可扫描加入,共同学习、共同进步,谢谢!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/69396.html

相关文章

  • SpringMVC源码分析--HandlerMapping(五)

    摘要:概述通过前三章的分析,我们简要分析了和,但对拦截器部分做详细的分析,拦截器的加载和初始化是三个相同的部分。 概述 通过前三章的分析,我们简要分析了SimpleUrlHandlerMapping、BeanNameUrlHandlerMapping和RequestMappingHandlerMapping,但对拦截器部分做详细的分析,拦截器的加载和初始化是三个HandlerMapping相...

    nanchen2251 评论0 收藏0
  • SpringMVC源码分析--HandlerMapping(三)

    摘要:与类图对比,类继承自抽象类,其又继承自抽象类,再往上继承关系与一致。创建初始化上一章我们分析了的创建初始化过程,的创建初始化过程与一样,方法的入口在抽象类中的方法。至此,代码编写完毕。 概述 本节我们继续分析HandlerMapping另一个实现类BeanNameUrlHandlerMapping,从类的名字可知,该类会根据请求的url与spring容器中定义的bean的name属性值...

    fsmStudy 评论0 收藏0
  • SpringMVC源码分析--HandlerMapping(六)

    摘要:概述上一节我们分析了的初始化过程,即创建并注册,本章我们分析下的请求处理过程,即查找。本系列文章是基于。最后创建了群方便大家交流,可扫描加入,同时也可加我,共同学习共同进步,谢谢 概述 上一节我们分析了RequestMappingHandlerMapping的初始化过程,即创建并注册HandlerMehtod,本章我们分析下RequestMappingHandlerMapping的请求...

    BDEEFE 评论0 收藏0
  • SpringMVC源码分析--HandlerMapping(二)

    摘要:由于抽象类重写了父类的方法,所以此时会调用的方法,在该方法中通过调用父类的方法,该方法通过模板方法模式最终调到类的方法。分析该类间接实现了接口,直接实现该接口的是抽象类,映射与请求。 概述 在前一章https://segmentfault.com/a/1190000014901736的基础上继续分析,主要完成SimpleUrlHandlerMapping类的原理。 本系列文章是基于Sp...

    Imfan 评论0 收藏0
  • SpringMVC源码分析--HandlerMapping(四)

    摘要:默认支持该策略。以上是对的宏观分析,下面我们进行内部细节分析。整体流程一通过实现接口,完成拦截器相关组件的初始化调用类的方法。总结本文主要分析了的初始化过程,希望对大家有帮助。随着学习的深入,后面有时间在分析下期中涉及的关键,比如等等。 概述 本节我们继续分析HandlerMapping另一个实现类ReqeustMappingHandlerMapping,该类是我们日常开发中使用最多的...

    imccl 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<