上图表示当客户请求来到时,spring架构作出响应的流程,可以从图中看到看到请求分发的中心就是 DispatcherServlet 类,DispatcherServlet的任务是将请求发送给Spring MVC控制器(controller) 。 控制器是一个用于处理请求的Spring组件。 在典型的应用程序中可能会有多个控制器, DispatcherServlet需要知道应该将请求发送给哪个控制器。 所以DispatcherServlet以会查询一个或多个处理器映射(handler mapping) 来确定请求的下一站在哪里。 处理器映射会根据请求所携带的URL信息来进行决策。

理解 DispatcherServlet 和 ContextLoadListener

DispatcherServlet 需要一个继承自ApplicationContext 的 WebApplicationContext 作为参数来配置自己。WebApplicationContext 是 ServletContext 和 Servlet 的关联者,对于很多应用,一个 WebApplicationContext 是足够并且可以充分发挥作用的,也有可能当我们有多个DispatcherServlet 并且想共享一下共同的bean 在这个应用中,这样我们可以定义一个root ApplicationContext里面包含所有的共同的bean 和

根WebApplicationContext (root WebApplicationContext )实际上已经包含了通常包含基础的beans ,例如数据存储(data repostitories )和需要被多个Servlet 实例共享的业务服务(business services)。这些beans可以被继承同时可以被重写(overridden)在 特定的Servlet中,或是在包含本地给定Servlet 的 child WebApplicationContext 中。而child WebApplicationContext  就是如下图的 Servlet WebApplicaitonContext .

以下引用参考文章中的解释

Spring's ApplicationContext provides the capability of loading multiple (hierarchical) contexts, allowing each to be focused on one particular layer, such as the web layer of an application or middle-tier services.

One of the canonical examples of using hierarchical ApplicationContext is when we have multiple DispatcherServlets in a web application and we're gonna share some of the common beans such as datasources between them. This way, we can define a root ApplicationContext that contain all the common beans and multiple WebApplicationContexts that inherit the common beans from the root context.

In the Web MVC framework, each DispatcherServlet has its own WebApplicationContext, which inherits all the beans already defined in the root WebApplicationContext. These inherited beans can be overridden in the servlet-specific scope, and you can define new scope-specific beans local to a given Servlet instance

假如项目中只有一个DispatcherServlet , 那么我们可以把原来在 DispatcherServlet  的beans 全部移到父类Root WebApplicationContext中。

下面是一个实现了WebApplicationContext继承者的configuration。

public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] { RootConfig.class };
} @Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] { App1Config.class };
} @Override
protected String[] getServletMappings() {
return new String[] { "/app1/*" };
}
}

假如不需要 application context 是继承关系的(WebApplicationContext 和 child WebApplicationContext 的关系),那么可以返回所有的配置通过 getRootConfigClasses ( ) , getServletConfigClasses( )返回null 就行了。 

在Servlet 3.0环境中, 容器会在类路径中查找实现javax.servlet.ServletContainerInitializer接口的类, 如果能发现的话, 就会用它来配置Servlet容器。Spring提供了这个接口的实现, 名为SpringServletContainerInitializer, 这个类反过来又会查找实现WebApplicationInitializer的类并将配置的任务交给它们来完成。 Spring 3.2引入了一个便利的WebApplicationInitializer基础实现, 也就是AbstractAnnotationConfigDispatcherServletInitializer。 因为我们的 SpittrWebAppInitializer 扩展了AbstractAnnotationConfigDispatcherServletInitializer(同时也就实现了WebApplicationInitializer) , 因此当部署到Servlet 3.0容器中的时候, 容器会自动发现它, 并用它来配置Servlet上下文。(简单地说就是继承了AbstractAnnotationConfigDispatcherServletInitializer,就会形成一个child WebApplicationContext )

我们自己实现的MyWebAppInitializer 和下面用xml文件是同种效果的。

<web-app>

    <listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener> <context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/root-context.xml</param-value>
</context-param> <servlet>
<servlet-name>app1</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/app1-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet> <servlet-mapping>
<servlet-name>app1</servlet-name>
<url-pattern>/app1/*</url-pattern>
</servlet-mapping> </web-app>

同样,假如不需要 application context 是继承关系的(WebApplicationContext 和 child WebApplicationContext 的关系),那么可以返回所有的配置通过 “root context” , 而Servlet 中的参数 contextLocation 返回null 就行了。

实例理解DispatcherServlet

假如我使用Spring MVC, Spring Security 和Spring Data JPA 来构建我的应用,那么我需要知道三个 config files , WebConfig 包含了web 相关的配置, 例如 ViewResolvers , Controllers , ArgumentResolver ,代码如下:

@EnableWebMvc
@Configuration
@ComponentScan(basePackages = "com.so.web")
public class WebConfig extends WebMvcConfigurerAdapter {
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp"); return viewResolver;
} @Override
public void configurePathMatch(PathMatchConfigurer configurer) {
final boolean DO_NOT_USE_SUFFIX_PATTERN_MATCHING = false;
configurer.setUseSuffixPatternMatch(DO_NOT_USE_SUFFIX_PATTERN_MATCHING);
}
}

这里我们定义了一个ViewResolver , 同时我们需要一个RepositoryConfig 配置数据有关的类,例如 DataSource 和 TransactionManager 等等。

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "com.so.repository")
public class RepositoryConfig {
@Bean
public DataSource dataSource() { ... } @Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() { ... } @Bean
public PlatformTransactionManager transactionManager() { ... } }

SecurityConfig 包含了安全相关的成员。

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
@Autowired
protected void configure(AuthenticationManagerBuilder auth) throws Exception { ... } @Override
protected void configure(HttpSecurity http) throws Exception { ... }
}

假如我们只有一个DispatcherServlet 下面我们有两种配置方法:

  1 public class ServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
2 @Override
3 protected Class<?>[] getRootConfigClasses() {
4 return new Class<?>[] { RepositoryConfig.class, SecurityConfig.class };
5 }
6
7 @Override
8 protected Class<?>[] getServletConfigClasses() {
9 return new Class<?>[] { WebConfig.class };
10 }
11
12 @Override
13 protected String[] getServletMappings() {
14 return new String[] { "/" };
15 }
16 }

或者是

  1 public class ServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
2 @Override
3 protected Class<?>[] getRootConfigClasses() {
4 return new Class<?>[] { RepositoryConfig.class, SecurityConfig.class, WebConfig.class };
5 }
6
7 @Override
8 protected Class<?>[] getServletConfigClasses() {
9 return null;
10 }
11
12 @Override
13 protected String[] getServletMappings() {
14 return new String[] { "/" };
15 }
16 }

ContextLoaderListener

引导监听Spring 的 root WebApplicationContext 的启动和关闭,在 Spring 3.1 中,ContextLoaderListener 支持通过 ContextLoaderListener(WebApplicationContext)来初始化 root WebApplicationContext .

特殊的bean

DispatcherServlet 委托给一些特殊的bean去处理请求和返回对应的响应,这些

DispatcherServlet

参考阅读

Spring mvc 中 DispatcherServlet 的学习和理解的更多相关文章

  1. spring mvc中DispatcherServlet如何得到ModelAndView的

    首先看下面这种张图,这张图说明了spring mvc整体的流程. 本文讲的就是如何从DispatcherServlet中得到ModerAndView的过程. 首先看DispatherServlet这个 ...

  2. Spring mvc中DispatcherServlet详解

    简介 DispatcherServlet是前端控制器设计模式的实现,提供SpringWebMVC的集中访问点,而且负责职责的分派,而且与spring IOC容器无缝集成,从而可以获得Spring的优势 ...

  3. Spring Mvc中DispatcherServlet和Servlet的区别小结

    在web开发过程中开始接触的是servlet,用来处理用户请求.这几年随着spring 框架越来越成熟,几乎成了java web开发界的主流框架.既然这么受欢迎肯定有它的优点,spring框架在原来的 ...

  4. Spring MVC中DispatcherServlet工作原理探究

    转:http://blog.csdn.net/zhouyuqwert/article/details/6853730 下面类图将主要的类及方法抽离出来,以便查看方便,根据类的结构来说明整个请求是如何工 ...

  5. Spring MVC 中的基于注解的 Controller【转】

    原文地址:http://my.oschina.net/abian/blog/128028 终于来到了基于注解的 Spring MVC 了.之前我们所讲到的 handler,需要根据 url 并通过 H ...

  6. Spring MVC中基于注解的 Controller

         终于来到了基于注解的 Spring MVC 了.之前我们所讲到的 handler,需要根据 url 并通过 HandlerMapping 来映射出相应的 handler 并调用相应的方法以响 ...

  7. Spring MVC中的HandlerMapping与HandlerAdapter

    *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...

  8. Servlet的生命周期以及在Spring MVC中调用流程

    接触Web时间比较久,虽然知道Servlet的生命周期但是理解却还是不够,今天刚好debug代码涉及这块就利用余下时间研究了一下. Servlet的生命周期以及处理浏览器请求的过程.Servlet接口 ...

  9. Spring MVC 中的基于注解的 Controller(转载)

           终于来到了基于注解的 Spring MVC 了.之前我们所讲到的 handler,需要根据 url 并通过 HandlerMapping 来映射出相应的 handler 并调用相应的方法 ...

随机推荐

  1. 927. Three Equal Parts

    Given an array A of 0s and 1s, divide the array into 3 non-empty parts such that all of these parts ...

  2. Ajax请求的一个重要属性contentType

    比如 contentType : 'application/json;charset=UTF-8', 或者 contentType : 'text/html;charset=UTF-8', 如果不加此 ...

  3. Ubuntu更新提示哈希和不匹配“Hash Sum mismatch”

    Ubuntu更新提示哈希和不匹配"Hash Sum mismatch" 今天在常规更新软件的时候,我的ubuntu报了一个错误. 应该是ubuntu程序更新转交给另外一个更新造成 ...

  4. miniui中表单验证规则总结

    页面链接: http://www.miniui.com/demo/#src=form/rules.html 页面效果图: 页面代码: <!DOCTYPE html PUBLIC "-/ ...

  5. C# 文件读写Helper类

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.I ...

  6. 高阶篇:4.2.2)DFMEA层级分明的失效模式、失效后果、失效原因

    本章目的:明确失效模式.失效后果.失效原因的定义,分清楚层次关系,完成DFMEA这部分的填写. 1.失效模式,失效后果,失效原因的定义: 这是FEMEA手册第四册中的定义. 1.1 潜在失效模式 (b ...

  7. Maven 整合 robot framework 进行测试

    1. 在maven pom.xml中先配置robot framework的plugin: <plugin> <!-- integration test runner (robot-f ...

  8. css提取数据2个常用方法

    提取标签里的内容 所谓数据就是HTML里标签的内容,如下面红色字体,就是标签内容 <title>我只是个实验 - SCRAPY</title> 提取标签里的数据,标签可以是ti ...

  9. V1-bug Alpha阶段项目展示

    V1-bug Alpha阶段项目展示 团队成员简介 Name Summary Sefie wxmwy V1-bug制造公司资深工程师精通各种抱大腿方式团队吉祥物 182 面面俱到流派一丝不苟 Powe ...

  10. 4G模块在AM335x上的移植

    关于4G模块的移植  看到一个很实用的写的比较好的   借鉴一下 参考:https://e2echina.ti.com/question_answer/dsp_arm/sitara_arm/f/25/ ...