• 【Tomcat源码学习】3.应用管理


    通过上一节我们完成了对容器进行了加载、初始化、启动,而对于应用的加载部分独立出来,本节进行单独的讲解
     

    一、应用加载流程

    1)应用识别,Context创建
    • 在Host启动后,会调用Host的监听HostConfig进行启动事件处理
    • HostConfig在监听到启动事件后,会分别尝试从context.xml下,wabapps下war,webapp下文件夹进行应用的读取,读取过程中通过Host的启停线程池(startStopExecutor)进行独立线程读取,读取最终结果生成Context对象并添加进入Host容器中。注意这里用到了Future<?>协同方式
    • 这里构建的Context仅包含如下基本参数(如:name,path,webappVersion,docBase),另外会给Context默认增加监听ContextConfig
     
    2)应用加载,Context启动

      • Engine启动ContainerBackgroundProcessor线程进行对所有容器进行后台处理,即调用所有容器的backgroundProcess()方法
      • 容器backgroundProcess()方法处理完成后,通知相应的监听器(事件类型为Lifecycle.PERIODIC_EVENT)
      • HostConfig会根据Context是否启动,进行相应启动操作(context.start()),
      • Context启动过程如下:
        • 获取一个WebAppLoader,
        • 应用类加载,执行WebAppLoader.start()方法,该方法内,会创建一个ClassLoader(WebappClassLoader),在调用ClassLoader.start()方法进行jar与class的加载
        • 添加应用级监听器至Context成员变量中,其中主要有:ServletContextAttributeListener,ServletRequestAttributeListener,ServletRequestListener,HttpSessionIdListener,HttpSessionAttributeListener,ServletContextListener,Context成员变量声明如下:
          private List<Object> applicationEventListenersList = new CopyOnWriteArrayList<>();
        • 执行SevletContextListener监听器上下文完成初始化方法(注意,Spring就是这里进行的初始化的)
      • Context启动完成后,通知相应的监听器ContextConfig,进行启动完成处理
      • ContextConfig.start()方法(核心为调用webConfig()方法)
        • 读取/WEB-INF/web.xml文件,构建WebXml对象
        • 解析所有class,判断是否有使用servlet相关注解(Ljavax/servlet/annotation/WebServlet),如果使用就注解对象手动添加至WebXml对象中,即生成ServletDef定义文件
        • 将jsp转换为ServletDef定义文件,并添加至WebXml对象中
        • 将WebXml对象内容解析至Context对象中(方法:configcontext),一个Servlet对应一个Wrapper容器
            for (Entry<String, String> entry : webxml.getContextParams().entrySet()) {
                context.addParameter(entry.getKey(), entry.getValue());
            }//context全局参数
            ....
            for (ErrorPage errorPage : webxml.getErrorPages().values()) {
                context.addErrorPage(errorPage);
            }//404页面
            for (FilterDef filter : webxml.getFilters().values()) {
                if (filter.getAsyncSupported() == null) {
                    filter.setAsyncSupported("false");
                }
                context.addFilterDef(filter);
            }//拦截器
            for (FilterMap filterMap : webxml.getFilterMappings()) {
                context.addFilterMap(filterMap);
            }//拦截器Map
            context.setJspConfigDescriptor(webxml.getJspConfigDescriptor());
            for (String listener : webxml.getListeners()) {
                context.addApplicationListener(listener);
            }//监听器
           ......
            for (ServletDef servlet : webxml.getServlets().values()) {
                Wrapper wrapper = context.createWrapper();//一个servlet对应一个封装器Wrapper
                // Description is ignored
                // Display name is ignored
                // Icons are ignored
                // jsp-file gets passed to the JSP Servlet as an init-param
                if (servlet.getLoadOnStartup() != null) {
                    wrapper.setLoadOnStartup(servlet.getLoadOnStartup().intValue());
                }
                if (servlet.getEnabled() != null) {
                    wrapper.setEnabled(servlet.getEnabled().booleanValue());
                }
                wrapper.setName(servlet.getServletName());
                Map<String,String> params = servlet.getParameterMap();
                for (Entry<String, String> entry : params.entrySet()) {
                    wrapper.addInitParameter(entry.getKey(), entry.getValue());
                }
                wrapper.setRunAs(servlet.getRunAs());
                Set<SecurityRoleRef> roleRefs = servlet.getSecurityRoleRefs();
                for (SecurityRoleRef roleRef : roleRefs) {
                    wrapper.addSecurityReference(
                            roleRef.getName(), roleRef.getLink());
                }
                wrapper.setServletClass(servlet.getServletClass());
                MultipartDef multipartdef = servlet.getMultipartDef();
                if (multipartdef != null) {
                    if (multipartdef.getMaxFileSize() != null &&
                            multipartdef.getMaxRequestSize()!= null &&
                            multipartdef.getFileSizeThreshold() != null) {
                        wrapper.setMultipartConfigElement(new MultipartConfigElement(
                                multipartdef.getLocation(),
                                Long.parseLong(multipartdef.getMaxFileSize()),
                                Long.parseLong(multipartdef.getMaxRequestSize()),
                                Integer.parseInt(
                                        multipartdef.getFileSizeThreshold())));
                    } else {
                        wrapper.setMultipartConfigElement(new MultipartConfigElement(
                                multipartdef.getLocation()));
                    }
                }
                if (servlet.getAsyncSupported() != null) {
                    wrapper.setAsyncSupported(
                            servlet.getAsyncSupported().booleanValue());
                }
                wrapper.setOverridable(servlet.isOverridable());
                context.addChild(wrapper);
            }
            for (Entry<String, String> entry :
                    webxml.getServletMappings().entrySet()) {
                context.addServletMapping(entry.getKey(), entry.getValue());
            }
            //sesseionConfig对象
            SessionConfig sessionConfig = webxml.getSessionConfig();
            if (sessionConfig != null) {
                if (sessionConfig.getSessionTimeout() != null) {
                    context.setSessionTimeout(
                            sessionConfig.getSessionTimeout().intValue());
                }
                SessionCookieConfig scc =
                    context.getServletContext().getSessionCookieConfig();
                scc.setName(sessionConfig.getCookieName());
                scc.setDomain(sessionConfig.getCookieDomain());
                scc.setPath(sessionConfig.getCookiePath());
                scc.setComment(sessionConfig.getCookieComment());
                if (sessionConfig.getCookieHttpOnly() != null) {
                    scc.setHttpOnly(sessionConfig.getCookieHttpOnly().booleanValue());
                }
                if (sessionConfig.getCookieSecure() != null) {
                    scc.setSecure(sessionConfig.getCookieSecure().booleanValue());
                }
                if (sessionConfig.getCookieMaxAge() != null) {
                    scc.setMaxAge(sessionConfig.getCookieMaxAge().intValue());
                }
                if (sessionConfig.getSessionTrackingModes().size() > 0) {
                    context.getServletContext().setSessionTrackingModes(
                            sessionConfig.getSessionTrackingModes());
                }
            }
      • 从WebApp加载中读取ServletContainerInitializer的实现,并添加至context容器中
     
        至此,host下面的context,wrapper,等容器就就已经生成并初始化了。





  • 相关阅读:
    Nginx(一)——介绍及安装配置
    Keepalived(二)
    H3C 交换机限速和添加Vlan
    The difference between su and su-
    CentOS7 修改 ssh 文件总结
    华为eNSP模拟器学习(一)
    如何使用Open Live Writer
    Ubuntu 开启远程ssh服务
    CentOS7 禁用firewall防火墙 启用iptables 步骤
    CentOS 7 精简版安装后联网问题
  • 原文地址:https://www.cnblogs.com/hframe/p/5326352.html
Copyright © 2020-2023  润新知