• 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);
        }
  • 相关阅读:
    Oracle 12c中文乱码,修改字符集的方法
    C++设计模式——简单工厂模式与策略模式比较
    C++设计模式——工厂模式Factory Method
    JavaWeb——Servlet基础
    C++设计模式——装饰模式Bridge-Pattern
    线性代数思维导图(2)——矩阵
    线性代数思维导图(1)——行列式
    C++设计模式——适配器模式Bridge-Pattern
    C++设计模式——桥接模式Bridge-Pattern
    不想写博客?那试试日记吧!
  • 原文地址:https://www.cnblogs.com/virgosnail/p/10182468.html
Copyright © 2020-2023  润新知