Hello World

DispatcherServlet 的创建过程

【参考文章】:SpringMvc 启动原理源码分析

【参考文章】:【Spring】DispatcherServlet的启动和初始化

【参考文章】:servlet 百度百科

1. servlet 生命周期  

  一个客户端的请求到达 Server;

  Server 创建一个请求对象,处理客户端请求;

  Server 创建一个响应对象,响应客户端请求;

  Server 加载 Servlet 并调用其 init() 进行初始化;

  Server 激活 Servlet 的 service() 方法,传递请求和响应对象作为参数;

  service() 方法获得关于请求对象的信息,处理请求,访问其他资源,获得需要的信息;

  service() 方法使用响应对象的方法,将响应传回Server,最终到达客户端;

  一般 Servlet 只初始化一次(只有一个对象),当 Server 不再需要 Servlet 时(一般当 Server 关闭时),Server 调用 Servlet 的 destroy() 方法。

 

  Servlet 容器处理由多个线程产生的多个请求,每个线程执行一个单一的 Servlet 实例的 service() 方法;

  Spring  MVC 中由一个单例的 DispatcherServlet  处理所有请求。

2. DispatcherServlet  的创建  

  DispatcherServlet就是一个前端控制器,集中提供请求处理机制。将url映射到指定的Controller处理,Controller处理完毕后将ModelAndView返回给DispatcherServlet,DispatcherServlet通过viewResovler进行视图解析,然后将model填充到view,响应给用户

2.1 构造方法

  先调用父类 FrameworkServlet 的构造方法,再调用自己的构造方法;

public class DispatcherServlet extends FrameworkServlet {    
   
    public DispatcherServlet() {
        super();
        setDispatchOptionsRequest(true);
    }
}

public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {

    public FrameworkServlet() {
    }
}

2.2 init()  

  DispatcherServlet 调用基类 HttpServletBeaninit(),

  主要获取 servletContextservletConfig 对象

@Override    
public final void init() throws ServletException {      
  if (logger.isDebugEnabled()) {
            logger.debug("Initializing servlet '" + getServletName() + "'");
        }

        // Set bean properties from init parameters.
        try {
        // 获取servletConfig
            PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
        // 将dispatcherServlet对象封装到BeanWrapper类里
            BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
        // 获取servletContext
            ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
            bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
        // 空的方法
            initBeanWrapper(bw);
            bw.setPropertyValues(pvs, true);
        }
        catch (BeansException ex) {
            logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
            throw ex;
        }

        // Let subclasses do whatever initialization they like.
     //这个方法由FrameworkServlet提供实现
        initServletBean();

        if (logger.isDebugEnabled()) {
            logger.debug("Servlet '" + getServletName() + "' configured successfully");
        }
    }

   

  HttpServletBean 的 init() 又会调用  FrameworkServlet 的 initServletBean();

  主要初始化 Spring 的 webApplicationContext  对象

    @Override
    protected final void initServletBean() throws ServletException {
        getServletContext().log("Initializing Spring " + getClass().getSimpleName() + " '" + getServletName() + "'");
        if (logger.isInfoEnabled()) {
            logger.info("Initializing Servlet '" + getServletName() + "'");
        }
        long startTime = System.currentTimeMillis();

        try {
            // 真正有效的方法
            this.webApplicationContext = initWebApplicationContext();
            initFrameworkServlet();
        }
        catch (ServletException | RuntimeException ex) {
            logger.error("Context initialization failed", ex);
            throw ex;
        }

        if (logger.isDebugEnabled()) {
            String value = this.enableLoggingRequestDetails ?
                    "shown which may lead to unsafe logging of potentially sensitive data" :
                    "masked to prevent unsafe logging of potentially sensitive data";
            logger.debug("enableLoggingRequestDetails='" + this.enableLoggingRequestDetails +
                    "': request parameters and headers will be " + value);
        }

        if (logger.isInfoEnabled()) {
            logger.info("Completed initialization in " + (System.currentTimeMillis() - startTime) + " ms");
        }
    }        

   

  初始化 WebApplicationContext后,调用 DispatcherServlet中 的 onRefresh();

    protected WebApplicationContext initWebApplicationContext() {
        WebApplicationContext rootContext =
                WebApplicationContextUtils.getWebApplicationContext(getServletContext());
        WebApplicationContext wac = null;

        if (this.webApplicationContext != null) {
            wac = this.webApplicationContext;
            if (wac instanceof ConfigurableWebApplicationContext) {
                ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
                if (!cwac.isActive()) {
                    if (cwac.getParent() == null) {
                        cwac.setParent(rootContext);
                    }
                    configureAndRefreshWebApplicationContext(cwac);
                }
            }
        }
        if (wac == null) {
            wac = findWebApplicationContext();
        }
        if (wac == null) {
            wac = createWebApplicationContext(rootContext);
        }
        if (!this.refreshEventReceived) {
            synchronized (this.onRefreshMonitor) {
                // 初始化 Spring MVC 的基本组件
                onRefresh(wac);
            }
        }
        if (this.publishContext) {
            String attrName = getServletContextAttributeName();
            getServletContext().setAttribute(attrName, wac);
        }

        return wac;
    }

   

  onRefresh() 直接调用 initStrategies() ;

    @Override
    protected void onRefresh(ApplicationContext context) {
        initStrategies(context);
    }

 

   initStrategies() 初始化基本组件,启动整个 Spring MVC 框架

protected void initStrategies(ApplicationContext context) {
     //初始化上传文件解析器
        initMultipartResolver(context);
      //初始化本地解析器
        initLocaleResolver(context);
     //主题处理器
        initThemeResolver(context);
     //映射处理器
        initHandlerMappings(context);
     //处理适配器
        initHandlerAdapters(context);
     //异常处理器
        initHandlerExceptionResolvers(context);
     //请求到视图名的翻译器
        initRequestToViewNameTranslator(context);
     //视图解析器
        initViewResolvers(context);
     //初始化FlashManager
        initFlashMapManager(context);
    }

 

posted @ 2018-12-26 23:03  小小忧愁米粒大  阅读(1071)  评论(0编辑  收藏  举报
瞅啥瞅,好好看书