要使用Sping MVC,只需要在 web.xml 中配置一个 DispatcherServlet :

<servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>
        org.springframework.web.servlet.DispatcherServlet
    </servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>
再定义一个 dispatcherServlet-servlet.xml 配置文件:

<beans>
  <!-- 定义Mapping -->
  <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandler-Mapping">
    <property name="mappings">
      <props>
        <prop key="demo.html">demo</prop>
      </props>
    </property>
    <property name="interceptors">
      <list>
        <ref bean="interceptor" />
      </list>
    </property>
  </bean>
  <bean id="interceptor" class="org.springframework.web.servlet.theme.ThemeChangeInterceptor"/>
  <!-- 定义View -->
  <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResource-ViewResolver">
    <property name="viewClass">
      <value>org.springframework.web.servlet.view.InternalResource-View</value>
    </property>
  </bean>
  <!-- 定义Control -->
  <bean id="demo" class="com.yb.mvc.demo">
    <property name="viewPage">
      <value>/demo.html</valus>
    </property>
  </bean>
</beans>

这样一个简单的基于Spring MVC 的应用就创建完成了。

Spring MVC 的使用非常简单,如上述代码所示我们只要扩展一个路径映射关系;定义一个视图解析器;在定义一个业务逻辑的处理流程规划,Spring MVC 就能够帮我们完成所有的MVC功能了。

DispatcherServlet 类相关结构图:


DispatcherServlet 类继承了 HttpServlet,在 Servlet 的 init 方法调用时 DispatcherServlet 执行 Spring MVC 的初始化工作。DispatcherServlet 初始化什么,可以在其 initStrategies 方法中知道,如图所示:

initMultipartResolver:初始化 MultipartResolver ,用于处理文件上传服务,如果有文件上传,那么会将当前的 HttpServletRequest包装成 DefaultMultipartHttpServletRequest ,并且将每个上传的内容封装成 CommonsMultipartFile 对象。

initLocaleResolver:用于处理应用的国际化问题,通过解析请求的 Locale 和设置响应的 Locale 来控制应用中的字符编码问题。

initThemeResolver:用于定义一个主题,例如,可以根据用户的喜好来设置用户访问页面的样式,可以将这个样式作为一个 Theme Name 保存,保存在用于请求来的Cookie 中或者保存在服务端的 Session 中,以后每次请求根据这个 Theme Name 返回特定的内容。

initHandlerMappings:用于定义用户设置的请求映射关系,例如,前面示例中的 SimpleUrlHandlerMapping 把用于用户请求的 URL 映射成一个个 Handler 实例。对 HandlerMapping 必须定义,如果没有定义,将获取 DispatcherServlet.properties 文件中默认的两个 HandlerMapping,分别是 BeanNameUrlHandlerMapping 和DefaultAnnotationHandlerMapping。

initHandlerAdapters:用于根据 Handler 的类型定义不同的处理规则,例如,定义 SimpleControllerHandlerAdapter 处理所有的 Controller 实例对象,在 HandlerMapping 中将 URL 映射成一个 Controller 实例,那么 Spring MVC在解析时 SimpleControllerHandlerAdapter 就会调用这个 Controller 实例。同样对HandlerAdapters 也必须定义,如果没有定义,将获取 DispatcherServlet.properties 文件中默认的4个 HandlerAdapters,分别是 HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter、ThrowawayControllerHandlerAdapter和AnnotationMethodHandlerAdapter。

initHandlerExceptionResolvers:当 Handler 处理出错时,会通过这个 Handler 来统一处理,默认的实现类是 SimpleMappingExceptionResolver,将错误日志记录在log文件中,并且转到默认的错误页面。

initRequestToViewNameTranslator:将指定的 ViewName 按照定义的 RequestToViewNameTranslator 替换成想要的格式,如加上前缀或者后缀等。

initViewResolvers:用于将 view 解析成页面,在 viewResolvers 中可以设置多个解析策略,如可以根据 JSP 来解析,或者按照 Velocity 模板解析。默认的解析策略是InternalResourceViewResolver,按照 JSP 页面来解析。

从上面的初始化策略可以看出,在一个请求中可能需要我们来扩展的地方都定义了扩展点,只要实现相关的接口类,并创建一个 Spring Bean 就能扩展 Spring MVC 框架。

在 Spring MVC 框架中,有3个组件是用户必须要定义和扩展的:定义 URL 映射规则、实现业务逻辑的 Handler 实例对象、渲染模板资源。而连接 Handler 实例对象和模板渲染的纽带就是 Model 模型了。

下面看看 DispatcherServlet 在启动时都做了哪些事情?

HttpServlet 初始化调用了 HttpServletBean 的init() 方法,该方法的作用是获取 Servlet 中的 init 参数,并创建一个 BeanWrapper 对象,然后由子类处真正执行 BeanWrapper 的初始化工作。但是 HttpServletBean 的子类 FrameworkServlet 和 DispatcherServlet 都没有覆盖其 initBeanWrapper(bw) 方法,所以创建的 BeanWrapper 对象没有任何作用,Spring 容器也不是通过 BeanWrapper 来创建的。

Spring 容器的创建是在 FrameworkServlet 的 initServletBean() 方法中完成的,这个方法会创建 WebApplicationContext 对象,并调用其 refresh() 方法来完成配置文件的加载,配置文件的加载同样先是查找 Servlet 的init-param 参数中设置的路径,如果没有,会根据namespace+Servlet 的名称来查找 XML 文件。Spring 容器在加载时会调用 DispatcherServlet 的 initStrategies 方法来完成在 DispatcherServlet 中定义的初始化工作。在 initStrategies 方法中会初始化 Spring MVC 框架需要的8个组件,这8个组件对应的8个 Bean 对象都保存在 DispatcherServlet 类中。

Spring MVC初始化时序图如图所示:


这时 DispatcherServlet 已经初始化完成,Spring MVC 也已经初始化完成,可以接受HTTP请求了。


--《深入分析Java Web技术内幕修订版》 Page 365-Page 369



Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐