• 你见到过孩子们的捕鼠器游戏吗?这真是一个疯狂的游戏,它的目标 是发送一个小钢球,让它经过一系列稀奇古怪的装置,最后触发捕鼠器。
  • 小钢球穿过各种复杂的配件,从一个斜坡上滚下来,被跷跷板弹 起,绕过一个微型摩天轮,然后被橡胶靴从桶中踢出去。经过这些后,小钢球会对那只可怜又无辜的橡胶老鼠进行捕获。
  • 乍看上去,你会认为Spring MVC框架与捕鼠器有些类似。Spring将请 求在调度Servlet、处理器映射 (handler mapping) 、控制器以及视图 解析器 (view resolver ) 之间移动,而捕鼠器中的钢球则会在各种斜 坡、跷跷板以及摩天轮之间滚动。但是,不要将Spring MVC与Rube Goldberg-esque捕鼠器游戏做过多比较。每一个Spring MVC中的组件都有特定的目的,并且它也没有那么复杂。
  • 让我们看一下请求是如何从客户端发起,经过Spring MVC中的组件, 最终再返回到客户端的。

1.5.1 跟踪Spring MVC的请求

  • 每当用户在Web浏览器中点击链接或提交表单的时候,请求就开始工 作了。对请求的工作描述就像是快递投送员。与邮局投递员或FedEx 投送员一样,请求会将信息从一个地方带到另一个地方。
  • 请求是一个十分繁忙的家伙。从离开浏览器开始到获取响应返回,它会经历好多站,在每站都会留下一些信息同时也会带上其他信息。 图 5. 1展示了请求使用Spring MVC所经历的所有站点。 file 图5 . 1 一路上请求会将信息带到很多站点,并生产期望的结果
  • 在请求离开浏览器时,,会带有用户所请求内容的信息,至少会包含 请求的URL。但是还可能带有其他的信息,例如用户提交的表单信息。 1.请求旅程的第一站是Spring的DispatcherServlet。
    - 上述内容描述了Spring MVC中的DispatcherServlet作为前端控制器的角色和功能。
    - 请求旅程的第一站是Spring的DispatcherServlet。
    - Spring MVC采用前端控制器模式,其中所有的请求都会通过一个前端控制器Servlet进行处理。
    - 前端控制器是常见的Web应用程序模式,它将请求委托给应用程序的其他组件来执行实际的处理。
    - 在Spring MVC中,DispatcherServlet就是前端控制器的实现。
  •    DispatcherServlet作为单实例的Servlet,负责接收所有的请求,并将它们分发给相应的处理组件来执行具体的处理逻辑。
  •    总结起来,DispatcherServlet在Spring MVC中充当了前端控制器的角色(可以理解为忠诚的哨兵),负责接收和分发请求,将其委托给其他组件来执行实际的.
  • 上述内容描述了DispatcherServlet在Spring MVC中的任务和工作流程。
  •   - 1.DispatcherServlet的任务是将请求发送给Spring MVC控制器。
      - 2.控制器是用于处理请求的Spring组件,一个应用程序可能有多个控制器。
      - 3.DispatcherServlet通过查询一个或多个处理器映射来确定请求应该发送给哪个控制器,处理器映射根据请求的URL信息进行决策。
      - 4.一旦选择了合适的控制器,DispatcherServlet将请求发送给选中的控制器。
      - 5.控制器负责处理请求的负载(用户提交的信息),通常将业务逻辑委托给一个或多个服务对象进行处理。
      - 6.控制器在完成逻辑处理后,产生模型数据需要返回给用户并在浏览器上显示。
      - 7.模型是包含要返回给用户的信息的数据对象。
      - 8.为了以用户友好的方式格式化信息(通常是HTML),模型需要发送给一个视图。
      - 9.视图通常是JSP,控制器将模型数据打包,并标识用于渲染输出的视图名。
      - 10.控制器将请求连同模型和视图名发送回DispatcherServlet。
      - 11.视图名并不直接表示特定的JSP,它只是一个逻辑名称,用于查找真正的视图
      - 12.DispatcherServlet使用视图解析器将逻辑视图名匹配为特定的视图实现,最终将渲染的输出结果通过响应对象传递给客户端。视图解析器和视图实现之间的配合完成了请求的任务。
    

 - 总结起来,DispatcherServlet负责将请求发送给合适的控制器,控制器处理请求的负载并生成模型数据,最后将模型数据和视图名发送回DispatcherServlet。视图名只是一个逻辑名称,用于查找真正的视图进行渲染输出。
 - 辅助记忆顺口溜
```java
DispatcherServlet任务重,控制器接请求。
处理器映射决策,选定控制器处理。
负载处理业务逻辑,模型数据返回用户视。
视图格式化信息,JSP展现视觉美。
视图解析器配合,响应结果传客户。
顺口溜帮记忆,Spring MVC流程清。
  • 可以看到,请求要经过很多的步骤,最终才能形成返回给客户端的响 应。大多数的步骤都是在Spring框架内部完成的,也就是图5. 1所示的组件中。尽管本章的主要内容都关注于如何编写控制器,但在此之前 我们首先看一下如何搭建Spring MVC的基础组件。

1.5.2 搭建Spring MVC

  • 配置DispatcherServlet
  • DispatcherServlet是Spring MVC的核心。在这里请求会第一次 接触到框架,它要负责将请求路由到其他的组件之中。
  • 按照传统方式,需要在web.xml文件中配置DispatcherServlet,并将其放在应用的WAR包中。然而,现在有了更多灵活的配置方法,不再局限于传统方式。
  • 我们会使用Java将DispatcherServlet配置在Servlet容器中,而不会再使用web.xml文件。如下的程序清单展示了所需的Java类。 程序清单5.1 配置DispatcherServlet
package com.spring.mvc;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

/**
 * @author huyang
 */
public class SpittrWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[0];
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[0];
    }

    @Override
    protected String[] getServletMappings() {
        return new String[0];
    }
}
    • 要理解程序清单5. 1是如何工作的,我们可能只需要知道扩展AbstractAnnotation-
  • ConfigDispatcherServletInitializer的任意类都会自动地 配置Dispatcher-Servlet和Spring应用上下文,Spring的应用上下 文会位于应用程序的Servlet上下文之中。
  • AbstractAnnotation-ConfigDispatcherServletInitializer剖析。
 *  1.Servlet 3.0容器在类路径中查找实现javax.servlet.ServletContainerInitializer接口的类。
    - 2.如果找到,容器会使用它来配置Servlet容器。
    - 3.Spring提供了这个接口的实现,名为SpringServletContainerInitializer。
    - 4.SpringServletContainerInitializer会查找实现WebApplicationInitializer接口的类,并将配置的任务交给它们来完成。
    - 5.Spring 3.2引入了一个便利的WebApplicationInitializer基础实现,即AbstractAnnotationConfig—DispatcherServletInitializer。
    - 6.Spittr-WebAppInitializer扩展了AbstractAnnotationConfig-DispatcherServletInitializer,同时也实现了WebApplicationInitializer接口。
    - 7.当部署到Servlet 3.0容器中时,容器会自动发现Spittr-WebAppInitializer,并用它来配置Servlet上下文。 
  • 尽管它的名字很长,但是AbstractAnnotationConfigDispatcherServlet- Initializer使用起来很简便。
    - 1.SpittrWebAppInitializer在程序清单5.1中重写了三个方法。 
    - 2. 第一个方法是getServletMappings(),它将一个或多个路径映射到DispatcherServlet上。在本例中,它映射的是"/",表示它是应用的默认Servlet,处理进入应用的所有请求。 
    - 3. 为了理解其他两个方法,需要理解DispatcherServlet和一个Servlet监听器(ContextLoaderListener)之间的关系。 
    - 4. DispatcherServlet启动时,会创建Spring应用上下文,并加载配置文件或配置类中声明的bean。 
    - 5. 在getServletConfigClasses()方法中,要求DispatcherServlet加载WebConfig配置类中定义的bean。
    - 6. 在Spring Web应用中,通常还会有另外一个应用上下文,由ContextLoaderListener创建。 
    - 7. DispatcherServlet加载包含Web组件的bean,如控制器、视图解析器和处理器映射。 
    - 8. ContextLoaderListener加载应用中的其他bean,通常是驱动应用后端的中间层和数据层组件。 
    - 9. AbstractAnnotationConfigDispatcherServletInitializer会同时创建DispatcherServlet和ContextLoaderListener。 
    - 10. getServletConfigClasses()方法返回带有@Configuration注解的类,用于定义DispatcherServlet应用上下文中的bean。 
    - 11. getRootConfigClasses()方法返回带有@Configuration注解的类,用于配置ContextLoaderListener创建的应用上下文中的bean。
  • 根配置与DispatcherServlet配置声明
    - 1. 在本例中,根配置定义在RootConfig中,DispatcherServlet的配置声明在WebConfig中。
    - 2. 通过AbstractAnnotationConfigDispatcherServletInitializer来配置DispatcherServlet是传统web.xml方式的替代方案。
    - 3. 可以同时包含web.xml和AbstractAnnotationConfigDispatcherServletInitializer,但这并不是必需的。
    - 4. 如果按照这种方式配置DispatcherServlet,而不是使用web.xml,唯一的问题是它只能部署到支持Servlet 3.0的服务器中才能正常工作,如Tomcat 7或更高版本。
    - 5. Servlet 3.0规范在2009年12月发布,因此有可能将应用部署到支持Servlet 3.0的Servlet容器中
  • 总结:在本例中,我们使用RootConfig和WebConfig来定义根配置和DispatcherServlet的配置。通过AbstractAnnotationConfigDispatcherServletInitializer来配置DispatcherServlet,替代了传统的web.xml方式。

  • 需要注意的是,这种方式仅适用于部署到支持Servlet 3.0的服务器,如Tomcat 7或更高版本。Servlet 3.0规范已于2009年发布。

  • 如果你还没有使用支持Servlet 3.0的服务器,那么在AbstractAnnotation-ConfigDispatcherServletInitializer子类中配置DispatcherServlet的方法就不适合你了。你别无选择,只能使用web.xml了。

本文由博客一文多发平台 OpenWrite 发布!