美文网首页
DispatchServlet、FrameworkServlet

DispatchServlet、FrameworkServlet

作者: 爱蛇 | 来源:发表于2018-03-27 01:02 被阅读0次
DispatchServlet接口架构

HttpServletBean

主要用于从web.xml 加载init-param参数,以及定义 initServletBean方法、initBeanWrapper方法。

// 功能: 简单的获取 servlet 中的 <init-param> 参数并绑定到 BeanWrapper 对象中, 并通过 initServletBean() 方法供子类完善其余功能
// 开始初始化 spring mvc servlet, 并实例化相应的 PropertyValues 供子类调用
@Override
public final void init() throws ServletException {
    if (logger.isDebugEnabled()) {
        logger.debug("Initializing servlet '" + getServletName() + "'");
    }
    // 获取 Servlet的初始化参数, 对 Bean 属性进行配置
    // Set bean properties from init parameters.
    // 此处便是读取 <servlet> 节点中的 <init-param> 参数保存至 MutablePropertyValues#propertyValueList 集合中
    // 解析 init-param 并封装在 pvs 中
    PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
    if (!pvs.isEmpty()) {
        try {
            // 将当前的这个 Servlet 类转化为一个 BeanWrapper, 从而能够以 Spring 的方式来对 init-param 的值进行注入
            BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);   // 将指定实例转化为 Spring 中可以处理的 BeanWrapper 类型的实例
            ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
            // 注册自定义属性编辑器, 一旦遇到 Resource 类型的属性将会使用 ResourceEditor 进行解析
            bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
            // 默认为空, 留给子类覆盖
            initBeanWrapper(bw);
            // 通过 BeanWrapper 将 getServletConfig() 中的属性配置到 DispatcherServlet
            bw.setPropertyValues(pvs, true);
        }
        catch (BeansException ex) {
            if (logger.isErrorEnabled()) {
                logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);
            }
            throw ex;
        }
    }
    // 调用 子类的 initServletBean 进行具体的初始化
    // Let subclasses do whatever initialization they like. 供子类覆写
    initServletBean();
}

作者:爱吃鱼的KK
链接:https://www.jianshu.com/p/322a9b345c07
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

FrameworkServlet

主要作用:

1.初始化WebApplicationContext:
初始化WebApplicationContext时会初始化IOC容器里的bean:

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

        if (this.webApplicationContext != null) {
            // A context instance was injected at construction time -> use it
            wac = this.webApplicationContext;
            if (wac instanceof ConfigurableWebApplicationContext) {
                ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
                if (!cwac.isActive()) {
                    // The context has not yet been refreshed -> provide services such as
                    // setting the parent context, setting the application context id, etc
                    if (cwac.getParent() == null) {
                        // The context instance was injected without an explicit parent -> set
                        // the root application context (if any; may be null) as the parent
                        cwac.setParent(rootContext);
                    }
                    configureAndRefreshWebApplicationContext(cwac);
                }
            }
        }
        if (wac == null) {
            // No context instance was injected at construction time -> see if one
            // has been registered in the servlet context. If one exists, it is assumed
            // that the parent context (if any) has already been set and that the
            // user has performed any initialization such as setting the context id
            wac = findWebApplicationContext();
        }
        if (wac == null) {
            // No context instance is defined for this servlet -> create a local one
            wac = createWebApplicationContext(rootContext);
        }

        if (!this.refreshEventReceived) {
            // Either the context is not a ConfigurableApplicationContext with refresh
            // support or the context injected at construction time had already been
            // refreshed -> trigger initial onRefresh manually here.
            onRefresh(wac);  //这里触发onRefresh时会触发 子类DispatchServlet 所有init开头的方法,比如initInterceptors,initHandlers
        }

        if (this.publishContext) {
            // Publish the context as a servlet context attribute.
            String attrName = getServletContextAttributeName();
            getServletContext().setAttribute(attrName, wac);
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Published WebApplicationContext of servlet '" + getServletName() +
                        "' as ServletContext attribute with name [" + attrName + "]");
            }
        }

        return wac;
    }

DispatchServlet 中实现FrameworkServlet的onRefresh模板方法:

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

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

2.拦截Servlet接口doPost、doGet、doDelete方法做预处理:

processRequest

3.实现了父类 HttpServletBean 的虚拟方法 initServletBean:


initServletBean

相关文章

网友评论

      本文标题:DispatchServlet、FrameworkServlet

      本文链接:https://www.haomeiwen.com/subject/bdldcftx.html