DispatcherServlet ——Spring MVC 的大心脏


  Spring MVC 的工作流程讲解遍地开花,本篇主要记录 DispatherServlet 的处理机制。这是深入了解 Spring MVC 框架工作机理的关键。

Spring MVC 的心脏

  DispatcherServlet 是 Spring MVC 的心脏,它负责接收 HTTP 请求并协调 Spring MVC 的各个组件完成请求处理的工作。DispatcherServlet 本质也是一个 Servlet,用户必须在 web.xml 中配置。

DispatcherServlet 处理机制

  DispatcherServlet 细分之后,可以整理出三个功能:

  • 截获 HTTP 请求,并交由 Spring MVC 框架处理
  • 处理控制层、业务层、持久层之间的调用关系
  • 初始化并装配 Spring MVC 的各个组件

配置 DispatcherServlet

  在 web.xml 中配置一个 Servlet,并通过 < servlet-mapping> 指定其处理的 URL。

<!-- 1. 加载所有的配置文件 -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/config/**/applicationContext-*.xml</param-value>
</context-param>

<!-- 1. 配置Spring监听 -->
<listener>
    <listener-class>
        org.springframework.web.context.ContextLoaderListener
    </listener-class>
</listener>

<!-- 2. 声明 DispatcherServlet-->
<servlet>
    <servlet-name>springMVC</servlet-name>
    <servlet-class>
        org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>

<!-- 3. DispatcherServlet 匹配的 URL 模式-->
<servlet-mapping>
    <servlet-name>springMVC</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>复制代码

  在 1. 处,通过 contextConfigLocation 参数制定业务层和持久层的 Spring 容器的配置文件(此处加载了全部配置文件),可以加载单个,也可以加载多个(以“,”分隔)。ContextLoaderListener 是一个 ServletContextListener,它通过 contextConfigLoaction 参数所指定的 Spring 配置文件启动业务层和持久层的 Spring 容器。

  在 2. 处配置了名为 springMVC 的 DispatcherServlet,它默认自动加载 /WEB-INF/springMVC-servlet.xml(即 < servlet-name>-servlet.xml) 的 Spring 配置文件,启动“控制层”的 Spring 容器。

  当然,也可以显示的指定 Spring 配置文件,如此一来,配置文件的名称可不必遵守 < servlet-name>-servlet.xml 的命名规则:

<!-- 2. 声明 DispatcherServlet-->
<servlet>
    <servlet-name>springMVC</servlet-name>
    <servlet-class>
        org.springframework.web.servlet.DispatcherServlet
    </servlet-class>

    <!-- 显示指定 “控制层” 的 Spring 配置文件-->
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/config/springmvc/applicationContext-mvc.xml
        </param-value>
    </init-param>

    <load-on-startup>1</load-on-startup>
</servlet>复制代码

  一个 web.xml 可以配置多个 DispatcherServlet,要保证 < servlet-name> 不同,通过其 < servlet-mapping> 的配置,让每个 DispatcherServlet 处理不同的请求。

截获 HTTP 请求

  在 3. 处通过 < servlet-mapping> 指定 DispatcherServlet 处理所有的 HTTP 请求,这里的“/”表示浏览器中的 URL 都会被 DispatcherServlet 接收。大多数情况,我们都会让 DispatcherServlet 处理以某种特定的 URL,比如以 .html 为后缀的 HTTP 请求:

<servlet-mapping>
    <servlet-name>springMVC</servlet-name>
    <url-pattern>*.html</url-pattern>
</servlet-mapping>复制代码

层级之间的调用

  多个 Spring 容器之间可以设置(通过 IOC)为父子级的关系,实现良好的解耦。在这里,“控制层” Spring 容器将作为“业务层” Spring 容器的子容器,即“控制层”容器可以引用“业务层”容器的 Bean,而“业务层”容器的却访问不到“控制层”容器的 Bean,“持久层”亦同。

装配 Spring MVC 组件

  在此之前,关于 DispatcherServlet 的了解都只停留在配置文件的层面,配置文件中只涉及了加载Spring配置文件,以及截获 HTTP 请求。如果要想知道其他关于 DispatcherServlet 的知识——初始化并装配 Spring MVC 组件,就必须查看源码了。正所谓:不入虎穴,焉得虎子?

  IDE 提前安装【源码查看】插件,以下是 org.springframework.web.servlet.DispatcherServletinitStrategies() 的代码(注释是我添加的):

    protected void initStrategies(ApplicationContext context)
    {
        initMultipartResolver(context); // 初始化上传文件解析器
        initLocaleResolver(context); // 初始化本地化解析器
        initThemeResolver(context); // 初始化主题解析器
        initHandlerMappings(context); // 初始化处理器映射器
        initHandlerAdapters(context); // 初始化处理器适配器
        initHandlerExceptionResolvers(context); // 初始化处理器异常解析器
        initRequestToViewNameTranslator(context); // 初始化请求到视图名翻译器
        initViewResolvers(context); // 初始化视图解析器
        initFlashMapManager(context); // 初始化 Flash 管理器
    }复制代码

  一开始其实我不知道该定位到哪个方法或者说哪部分代码,但是我看到关键字 init,以及参数 ApplicationContext context 大概知道这应该是初始化方法了,而且该方法内调用了其他以 init 开头的方法,而且方法名都是平常熟悉的词汇,这些就是组件了,八九不离十。最后我通过直译和找资料给上述代码添加了注释。

  initStrategies() 方法将在 WebApplicationContext 初始化后自动执行,此时 Spring 上下文中的 Bean 已经初始化完毕。该方法的工作是通过反射机制查找并装配 Spring 容器中用户显示自定义的组件 Bean,如果找不到再装配默认的组件实例。

小结

  要想深入 Spring MVC 框架的工作机理,必须先了解以下三个问题:

  • DispatcherServlet 如何截获 HTTP 请求
  • 控制层、业务层和持久层之间的调用关系
  • 如何初始化 Spring MVC 的各个组件,并将其装配到 DispatcherServlet 中

我的博客地址:DispatcherServlet——Spring MVC 的大心脏

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值