一、SpringMVC中的DispatcherServlet介绍

1、DispatcherServlet的介绍

DispatcherServlet是Spring MVC框架的核心组件之一,它负责请求的接收、处理和响应。DispatcherServlet在整个请求处理过程中扮演着调度者的角色,将请求分发到相应的处理器进行处理,并将处理结果返回给客户端。

DispatcherServlet的主要功能包括:

  1. 请求接收:DispatcherServlet接收客户端发送的请求,并将其封装为HttpServletRequest对象。
  2. 请求分发:根据请求的URL路径和处理器映射信息,DispatcherServlet将请求分发到相应的处理器(Controller)进行处理。
  3. 处理器调用:DispatcherServlet根据请求的URL路径和处理器映射信息,找到相应的处理器,并调用其相应的方法进行处理。
  4. 视图渲染:处理器处理完请求后,可以返回一个视图名称或一个包含视图名称的ModelAndView对象。DispatcherServlet根据返回的视图名称或ModelAndView对象,找到相应的视图(View)进行渲染,最终将渲染后的结果返回给客户端。
  5. 异常处理:如果在请求处理过程中出现异常,DispatcherServlet会根据异常类型和处理器映射信息,找到相应的异常处理器(ExceptionHandler)进行处理。

DispatcherServlet是Spring MVC框架中负责请求处理的核心组件,它扮演着调度者的角色,将请求分发到相应的处理器进行处理,并将处理结果返回给客户端。

2、DispatcherServlet配置上下文

DispatcherServlet默认使用WebApplicationContext作为上下文,Spring默认配置文件为“/WEB-INF/[servlet名字]-servlet.xml”。DispatcherServlet也可以配置自己的初始化参数:

a、配置contextClass

b、配置contextConfigLocation

c、配置namespace

DispatcherServlet的上下文仅仅是Spring MVC的上下文,而Spring加载的上下文是通过ContextLoaderListener来加载的。一般spring web项目中同时会使用这两种上下文,前者仅负责MVC相关bean的配置管理(如ViewResolver、Controller、MultipartResolver等),后者则负责整个spring相关bean的配置管理(如相关Service、DAO等)。

因此在/WEB-INF/[server-name]-servlet.xml中配置的Bean一般只针对Spring MVC有效,而在ContextLoaderListener配置文件下配置的bean则对整个spring有效。

上下文创建完后会放在ServletContext对象中,其中ContextLoaderListener加载的上下文放在ServletContext的key为WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE属性中,而DispatcherServlet加载的上下文在每次请求时会放一份在request对象的key为WEB_APPLICATION_CONTEXT_ATTRIBUTE属性中。因而两者的获取方式也不一样,前者可以通过WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext)或WebApplicationContextUtils.getWebApplicationContext(servletContext)或WebApplicationContextUtils.getWebApplicationContext(servletContext,attrname)方法来获取对应的applicationContext,而后者则通过RequestContextUtils.getWebApplicationContext(request)或 WebApplicationContextUtils.getWebApplicationContext(servletContext,attrname)方法来获取对应的applicationContext。

对于ContextLoaderListener加载的上下文即上面提到的WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE;而对于DispatcherServlet中的上下文则为FrameworkServlet.class.getName() + ".CONTEXT." + getServletName()。

通过上下文所在的属性可以看出,如果通过WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext)来试图获取DispatcherServlet加载的applicationContext时,就会抛出"No WebApplicationContext found: no ContextLoaderListener registered?"的异常。

3、DispatcherServlet中特殊Bean

DispatcherServlet默认使用WebApplicationContext作为上下文,因此我们来看一下该上下文中有哪些特殊的Bean:

a、Controller:处理器/页面控制器,做的是MVC中的C的事情,但控制逻辑转移到前端控制器了,用于对请求进行处理;

b、HandlerMapping:请求到处理器的映射,如果映射成功返回一个HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器)对象;如BeanNameUrlHandlerMapping将URL与Bean名字映射,映射成功的Bean就是此处的处理器;

c、HandlerAdapter:HandlerAdapter将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;如SimpleControllerHandlerAdapter将对实现了Controller接口的Bean进行适配,并且掉处理器的handleRequest方法进行功能处理;

d、ViewResolver:ViewResolver将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;如InternalResourceViewResolver将逻辑视图名映射为jsp视图;

e、LocalResover:本地化解析,因为Spring支持国际化,因此LocalResover解析客户端的Locale信息从而方便进行国际化;

f、ThemeResovler:主题解析,通过它来实现一个页面多套风格,即常见的类似于软件皮肤效果;

g、MultipartResolver:文件上传解析,用于支持文件上传;

h、HandlerExceptionResolver:处理器异常解析,可以将异常映射到相应的统一错误界面,从而显示用户友好的界面(而不是给用户看到具体的错误信息);

i、RequestToViewNameTranslator:当处理器没有返回逻辑视图名等相关信息时,自动将请求URL映射为逻辑视图名;

j、FlashMapManager:用于管理FlashMap的策略接口,FlashMap用于存储一个请求的输出,当进入另一个请求时作为该请求的输入,通常用于重定向场景
 

通过以上的bean可以看出,一般LocalResover、ViewResolver等需要配置在/WEB-INF/[server-name]-servlet.xml文件中。

二、源码详解

在源代码中,DispatcherServlet类位于org.springframework.web.servlet包中。下面是对DispatcherServlet的简单解释:

  1. 请求接收:
    在doService方法中,DispatcherServlet接收客户端发送的请求,并创建一个HttpServletRequest对象。该方法将请求封装为RequestContextHolder中的WebRequest对象,以便在整个请求处理过程中使用。
  2. 请求分发:
    在handleRequest方法中,DispatcherServlet根据请求的URL路径和处理器映射信息,将请求分发到相应的处理器(Controller)。该方法根据请求的URL路径和处理器映射信息,找到相应的处理器,并调用其相应的方法进行处理。
  3. 处理器调用:
    在handleRequest方法中,DispatcherServlet根据请求的URL路径和处理器映射信息,找到相应的处理器,并调用其相应的方法进行处理。在调用处理器方法之前,DispatcherServlet会将请求封装为HandlerExecutionChain对象,以便在请求处理过程中使用。
  4. 视图渲染:
    在handleRequest方法中,DispatcherServlet根据处理器返回的视图名称或ModelAndView对象,找到相应的视图(View)进行渲染。如果处理器返回了视图名称,DispatcherServlet会根据视图名称找到相应的视图对象进行渲染;如果处理器返回了ModelAndView对象,DispatcherServlet会根据ModelAndView对象中的视图名称和模型数据进行渲染。最终,DispatcherServlet将渲染后的结果返回给客户端。
  5. 异常处理:
    在handleRequest方法中,如果请求处理过程中出现异常,DispatcherServlet会根据异常类型和处理器映射信息,找到相应的异常处理器(ExceptionHandler)进行处理。如果找到了对应的异常处理器,DispatcherServlet会调用其相应的方法处理异常;否则,会抛出异常给调用者。

DispatcherServlet是Spring MVC框架中负责请求处理的核心组件之一。它接收客户端发送的请求,根据请求的URL路径和处理器映射信息将请求分发到相应的处理器进行处理,并将处理结果返回给客户端。同时,它还负责异常处理和视图渲染等操作。

三、应用的设计模式

DispatcherServlet主要使用了以下设计模式:

  1. 策略模式:DispatcherServlet定义了一组接口,这些接口定义了如何处理请求和生成响应。然后,它使用一个具体的策略对象(也就是一个实现这些接口的类)来处理每个请求。这种设计使得应用程序可以在不修改现有代码的情况下更换不同的策略对象,从而改变其行为。
  2. 工厂模式:DispatcherServlet使用工厂模式创建了处理器对象。它根据请求的类型和内容,动态地创建一个能够处理该请求的对象,并将其封装到HandlerExecutionChain对象中。这种设计使得处理器对象的创建和使用更加灵活,不需要在代码中硬编码处理器的类型。
  3. 观察者模式:DispatcherServlet使用观察者模式来监听和处理请求。当请求到达时,它会触发一个事件,并通知所有注册的观察者(也就是处理器)。这种设计使得处理器的执行顺序可以根据请求的类型和内容动态改变,而不需要修改现有的代码。
  4. 单例模式:DispatcherServlet是一个单例对象。它在整个应用程序中只有一个实例,可以用于处理所有的请求。这种设计使得DispatcherServlet可以全局管理所有的请求和响应,并且可以在不同的请求之间共享状态和资源。

DispatcherServlet的设计方法使得它具有高度的可扩展性和灵活性,可以轻松地添加新的处理器、视图和异常处理器,并且可以动态地改变其行为和执行顺序。