dispatcherServler的实现

 DispatcherServlet是前端控制器设计模式的实现,负责职责的分派

DispatcherServlet 主要用作职责调度工作,本身主要用于控制流程,主要职责如下:

1:文件上传解析,如果请求类型是 multipart 将通过 MultipartResolver 进行文件上传解析
2:通过HandlerMapping,将请求映射到处理器(返回一个 HandlerExecutionChain,它包括一个处理器、多个 HandlerInterceptor 拦截器)
3:通过 HandlerAdapter 支持多种类型的处理器(HandlerExecutionChain 中的处理器)
4:通过 ViewResolver 解析逻辑视图名到具体视图实现
5:本地化解析
6:渲染具体的视图
7:如果执行过程中遇到异常将交给 HandlerExceptionResolver 来解析

 DispatcherServlet 也可以配置自己的初始化参数,也就是 servlet 配置中可以配置<init-param>

contextClass 实现 WebApplicationContext 接口的类,当前的 servlet 用它来创建上下文。如果这个参数没有指定,默认使用 XmlWebApplicationContext
contextConfigLocation 传给上下文实例(由 contextClass 指定)的字符串,用来指定上下文的位置。这个字符串可以被分成多个字符串(使用逗号作为分隔符)来支持多个上下文(在有多个上下文的情况下,如果同一个 bean 被定义两次,后面一个优先)
namespace 命名空间。默认值是 [servlet-name]-servlet

 一旦你的一段程序有了外部变量,这段程序就不完整,不能独立运行。你为了使他们运行,就要给所有的外部变量一个一个写一些值进去。这些值的集合就叫上下文。上下文是程序的运行环境

contextConfigLocation:表示用于加载 Bean 的配置文件路径;
contextClass:表示用于加载 Bean 的 ApplicationContext 实现类,默认 WebApplicationContext

 DispatcherServlet 的初始化顺序

1:HttpServletBean 继承 HttpServlet,因此在 Web 容器启动时将调用它的 init 方法
2:FrameworkServlet 继承 HttpServletBean,通过 initServletBean() 进行 Web 上下文初始化
3:DispatcherServlet 继承 FrameworkServlet,并实现了 onRefresh() 方法提供一些前端控制器相关的配置

 在 SpringMVC 框架 DispatcherServlet 中的第 470 行左右:

protected void initStrategies(ApplicationContext context) {
    initMultipartResolver(context);
    initLocaleResolver(context);
    initThemeResolver(context);
    initHandlerMappings(context);
    initHandlerAdapters(context);
    initHandlerExceptionResolvers(context);
    initRequestToViewNameTranslator(context);
    initViewResolvers(context);
    initFlashMapManager(context);
}

 整个 DispatcherServler 初始化的过程具体主要做了两件事情:

  • 初始化 SpringMVC 使用的 Web 上下文,并且可能指定父容器(ContextLoaderListener 加载了根上下文)
  • 初始化 DispatcherServlet 使用的策略,如 HandlerMapping、HandlerAdapter 等

DispatcherServler 的默认配置:

  DispatcherServlet 的默认配置在 DispatcherServlet.properties(和 DispatcherServlet 类在一个包下)中,而且是当 Spring 配置文件中没有指定配置时使用的默认策略;

DispatcherServlet 中的特殊 Bean

DispatcherServlet 默认使用 WebApplicationContext 作为上下文,该上下文中有以下的一些 Bean:

Controller

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

HandlerMapping

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

HandlerAdapter:

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

ViewResolver

  ViewResolver 将把逻辑视图名解析为具体的 View,如InternalResourceViewResoulver 将逻辑视图名映射为 jsp 视图;

LocalResolver

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

ThemeResolver

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

MultipartResolver

  文件上传解析,用于支持文件上传;

HandlerExceptionResolver

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

RequestToViewNameTranslator

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

FlashMapManager

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

Controller 简介

  Controller 控制器,是 MVC 中的部分 C,主要负责功能处理部分

1、收集、验证请求参数并绑定到命令对象
2、将命令对象交给业务对象,由业务对象处理并返回模型数据
3、返回 ModelAndView(Model 部分是业务对象返回的模型数据,视图部分为逻辑视图名)

HandlerMapping功能分析

HandlerMapping是spring中最重要的一个类,主要功能就是为请求找到合适的处理器,现在Controller只是处理器的一种,

RequestMappingHandlerMapping

这个就是现在默认的请求匹配方式,通过@RequestMapping 注解来决定调用方法和具体的类,也是最常用的一种。

DispatcherServlet初始化的时候会调用initHandlerMappings()进行初始化

//初始化handlermapping
  private void initHandlerMappings(ApplicationContext context) {
        this.handlerMappings = null;
        //判断是否默认添加所有的HandlerMappings,初始值是默认添加的
        if (this.detectAllHandlerMappings) {
            // Find all HandlerMappings in the ApplicationContext, including ancestor contexts.
            Map<String, HandlerMapping> matchingBeans =
                    BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
            if (!matchingBeans.isEmpty()) {
                this.handlerMappings = new ArrayList<HandlerMapping>(matchingBeans.values());
                // We keep HandlerMappings in sorted order.
                //通过@order注解去排序
                AnnotationAwareOrderComparator.sort(this.handlerMappings);
            }
        }
        //如果不是默认添加所有的,那么就去context中找一个声明的bean
        else {
            try {
                HandlerMapping hm = context.getBean(HANDLER_MAPPING_BEAN_NAME, HandlerMapping.class);
                this.handlerMappings = Collections.singletonList(hm);
            }
            catch (NoSuchBeanDefinitionException ex) {
                // Ignore, we'll add a default HandlerMapping later.
            }
        }

        // Ensure we have at least one HandlerMapping, by registering
        // a default HandlerMapping if no other mappings are found.
        //如果上面两步没有找到可以使用的handlerMapping,那么就采用默认的handlerMapping
        //默认的HandlerMapping都定义在了DispatcherServlet.properties中,大致定义了如下两个
        //org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
    //org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping
        if (this.handlerMappings == null) {
            this.handlerMappings = getDefaultStrategies(context, HandlerMapping.class);
            if (logger.isDebugEnabled()) {
                logger.debug("No HandlerMappings found in servlet '" + getServletName() + "': using default");
            }
        }
    }

默认的RequestMappingHandlerMapping已经把所有路径映射进去,相关的spring拦截器也放到了RequestMappingHandlerMapping中,由此说来,拦截器其实是跟RequestMappingHandlerMapping进行关联的。

HandlerMapping流程需要弄清楚几个类的定义:

HandlerExecutionChain

HandlerExecutionChain是 handler的执行链,由一些handler object 和 handler interceptors组成,这个里面包含了interceptor的所有执行,包括这个请求是否通过preHandle

HandlerAdapter 这个是spring的核心功能,所有的请求对应Controller方法都是通过HandlerAdapter 大概作用就是进行方法映射和调用并且返回结果,对应spring中正常用法实现类是HttpRequestHandlerAdapter,一般基本的http请求都是通过这个进行处理的。

猜你喜欢

转载自blog.csdn.net/qq_34971162/article/details/81288179