`

tomcat源码研究之 web.xml中load-on-startup标签的含义

阅读更多

(1)

在servlet的配置当中,<load-on-startup>5</load-on-startup>的含义是:

标记容器是否在启动的时候就加载这个servlet。

当值为0或者大于0时,表示容器在应用启动时就加载这个servlet;

当是一个负数时或者没有指定时,则指示容器在该servlet被选择时才加载。

正数的值越小,启动该servlet的优先级越高。

web.xml的配置如下:

<servlet>  
 <servlet-name>initservlet</servlet-name>  
 <servlet-class>com.ccc.lxy.util.initServlet</servlet-class>  
 <load-on-startup>1</load-on-startup>  
</servlet>  

(2) 在我的tomcat源码研究中我已经介绍到,tomcat本身就是组件构成的容器,我们的应用程序程序将对应到Context组件

而Context组件实现是StandardContext这个类,而Servlet对应的组件是Wrapper,它的实现是StandardWrapper,

既然当load-on-startup值大于等于0时候 在启动时候 那么我看StandardContext 这个类启动时的情况 

  protected synchronized void startInternal() throws LifecycleException {

        if(log.isDebugEnabled())
            log.debug("Starting " + getBaseName());

        // Send j2ee.state.starting notification 
        if (this.getObjectName() != null) {
            Notification notification = new Notification("j2ee.state.starting",
                    this.getObjectName(), sequenceNumber.getAndIncrement());
            broadcaster.sendNotification(notification);
        }

        setConfigured(false);
        boolean ok = true;

        // Currently this is effectively a NO-OP but needs to be called to
        // ensure the NamingResources follows the correct lifecycle
        if (namingResources != null) {
            namingResources.start();
        }
        
        // Add missing components as necessary
        if (webappResources == null) {   // (1) Required by Loader
            if (log.isDebugEnabled())
                log.debug("Configuring default Resources");
            try {
                if ((getDocBase() != null) && (getDocBase().endsWith(".war")) &&
                        (!(new File(getBasePath())).isDirectory()))
                    setResources(new WARDirContext());
                else
                    setResources(new FileDirContext());
            } catch (IllegalArgumentException e) {
                log.error("Error initializing resources: " + e.getMessage());
                ok = false;
            }
        }
// 代码省略...

    if (ok) {
                if (!listenerStart()) {
                    log.error( "Error listenerStart");
                    ok = false;
                }
            }
            
            try {
                // Start manager
                if ((manager != null) && (manager instanceof Lifecycle)) {
                    ((Lifecycle) getManager()).start();
                }
            } catch(Exception e) {
                log.error("Error manager.start()", e);
                ok = false;
            }

            // Configure and call application filters
            if (ok) {
                if (!filterStart()) {
                    log.error("Error filterStart");
                    ok = false;
                }
            }
            
            // Load and initialize all "load on startup" servlets
            
            //加载servlet的loadOnStardup属性
            if (ok) {
                if (!loadOnStartup(findChildren())){
                    log.error("Error loadOnStartup");
                    ok = false;
                }
            }
            
            // Start ContainerBackgroundProcessor thread
            super.threadStart();
//代码省略

 从上述代码中,我可知Context组件在启动时调用方法 loadOnStartup这个方法

public boolean loadOnStartup(Container children[]) {

        // Collect "load on startup" servlets that need to be initialized
        TreeMap<Integer, ArrayList<Wrapper>> map =
            new TreeMap<Integer, ArrayList<Wrapper>>();
        for (int i = 0; i < children.length; i++) {
            Wrapper wrapper = (Wrapper) children[i];
            int loadOnStartup = wrapper.getLoadOnStartup();
            //从这儿可知loadonStartup 小于0时 跳过,
            //也就是只有大于等于0时才进行的 初始化化加载了
            if (loadOnStartup < 0)
                continue;
            Integer key = Integer.valueOf(loadOnStartup);
            ArrayList<Wrapper> list = map.get(key);
            if (list == null) {
                list = new ArrayList<Wrapper>();
                map.put(key, list);
            }
            list.add(wrapper);
        }

        //下面是具体初始化加载的loadonStartup>=0的Servlet
        
        // Load the collected "load on startup" servlets
        for (ArrayList<Wrapper> list : map.values()) {
            for (Wrapper wrapper : list) {
                try {
                    wrapper.load();
                } catch (ServletException e) {
                    getLogger().error(sm.getString("standardWrapper.loadException",
                                      getName()), StandardWrapper.getRootCause(e));
                    // NOTE: load errors (including a servlet that throws
                    // UnavailableException from tht init() method) are NOT
                    // fatal to application startup, excepted if failDeploymentIfServletLoadedOnStartupFails is specified
                    if(getComputedFailCtxIfServletStartFails()) {
                        return false;
                    }
                }
            }
        }
        return true;

    }

  从上面可知只有loadonStartup>=0时才调用wrapper的load

 而且从上面可知将这些大于等于0的Servlet都放入一个treemap, treemap恰恰是一个排序map且升序map 所以loadonstartup 越小越先遍历到 越先执行load

 

而Wrapper的load就是StandardWrapper的load方法具体如下

  public synchronized void load() throws ServletException {
    	//实例化一个Servlet
        instance = loadServlet();
        //实例化完成以后开始调用InitServlet方法
        if (!instanceInitialized) {
            initServlet(instance);
        }

        if (isJspServlet) {
            StringBuilder oname =
                new StringBuilder(MBeanUtils.getDomain(getParent()));
            
            oname.append(":type=JspMonitor,name=");
            oname.append(getName());
            
            oname.append(getWebModuleKeyProperties());
            
            try {
                jspMonitorON = new ObjectName(oname.toString());
                Registry.getRegistry(null, null)
                    .registerComponent(instance, jspMonitorON, null);
            } catch( Exception ex ) {
                log.info("Error registering JSP monitoring with jmx " +
                         instance);
            }
        }
    }


 具体调用InitServlet方法如下:

   

 private synchronized void initServlet(Servlet servlet)
            throws ServletException {
        
        if (instanceInitialized && !singleThreadModel) return;

        // Call the initialization method of this servlet
        try {
            instanceSupport.fireInstanceEvent(InstanceEvent.BEFORE_INIT_EVENT,
                                              servlet);

            //调用Servlet的init方法
            if( Globals.IS_SECURITY_ENABLED) {
                boolean success = false;
                try {
                	//反射调用init方法
                    Object[] args = new Object[] { facade };
                    SecurityUtil.doAsPrivilege("init",
                                               servlet,
                                               classType,
                                               args);
                    success = true;
                } finally {
                    if (!success) {
                        // destroy() will not be called, thus clear the reference now
                        SecurityUtil.remove(servlet);
                    }
                }
            } else {
            	//{初始化servlet的init(ServletConfig config)方法然后 在这方法中init()方法了了}
                servlet.init(facade);
            }

            instanceInitialized = true;

            instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,
                                              servlet);
        } catch (UnavailableException f) {
            instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,
                                              servlet, f);
            unavailable(f);
            throw f;
        } catch (ServletException f) {
            instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,
                                              servlet, f);
            // If the servlet wanted to be unavailable it would have
            // said so, so do not call unavailable(null).
            throw f;
        } catch (Throwable f) {
            ExceptionUtils.handleThrowable(f);
            getServletContext().log("StandardWrapper.Throwable", f );
            instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,
                                              servlet, f);
            // If the servlet wanted to be unavailable it would have
            // said so, so do not call unavailable(null).
            throw new ServletException
                (sm.getString("standardWrapper.initException", getName()), f);
        }
    }

 从这里可知我们Servlet调用情况

分享到:
评论

相关推荐

    搭建struts1.x环境例子源码

    &lt;load-on-startup&gt;2&lt;/load-on-startup&gt; &lt;filter-mapping&gt; &lt;filter-name&gt;strutsPrepareFilter&lt;/filter-name&gt; &lt;url-pattern&gt;/*&lt;/url-pattern&gt; &lt;/filter-mapping&gt; &lt;filter-name&gt;strutsExecuteFilter&lt;/filter-name...

    Jcrontab-1.4.1 源码

    5、非常容易的可以和Web应用服务器结合,Tomcat, Resin, Jetty and Jboss这些服务器已经通过测试和应用,这一切只需要在web.xml中添加load-on-startup直接指定Jcrontab下的 loadCrontabServlet,就可以了。...

    Struts 源码学习之ActionServlet

    ### Struts 源码学习之ActionServlet #### 一、引言 在Java Web开发领域,Struts框架因其简洁的MVC(Model-View-Controller)架构模式而备受开发者青睐。本文旨在深入剖析Struts框架的核心组件之一——`Action...

    WEB-INF目录下的jsp页面如何访问

    &lt;load-on-startup&gt;1&lt;/load-on-startup&gt; &lt;servlet-mapping&gt; &lt;servlet-name&gt;dispatcher&lt;/servlet-name&gt; &lt;url-pattern&gt;/&lt;/url-pattern&gt; &lt;/servlet-mapping&gt; ``` - 这里通过配置前端控制器`DispatcherServlet...

    struts国际化的使用

    &lt;load-on-startup&gt;1&lt;/load-on-startup&gt; &lt;servlet-mapping&gt; &lt;servlet-name&gt;action&lt;/servlet-name&gt; &lt;url-pattern&gt;*.do&lt;/url-pattern&gt; &lt;/servlet-mapping&gt; &lt;/web-app&gt; ``` 这里配置了Struts的核心Servlet——`...

    SpringMVC请求流程源码分析.doc

    &lt;load-on-startup&gt;1&lt;/load-on-startup&gt; &lt;servlet-mapping&gt; &lt;servlet-name&gt;dispatcherServlet&lt;/servlet-name&gt; &lt;url-pattern&gt;/&lt;/url-pattern&gt; &lt;/servlet-mapping&gt; ``` ##### 2. 工程配置 在完成项目的基本...

    spring3 MVC 入门hello world源码

    &lt;load-on-startup&gt;1&lt;/load-on-startup&gt; ... &lt;servlet-mapping&gt; &lt;servlet-name&gt;dispatcher&lt;/servlet-name&gt; &lt;url-pattern&gt;/&lt;/url-pattern&gt; &lt;/servlet-mapping&gt; ``` 配置DispatcherServlet启动和URL映射。 3...

    我的tomcat7源码手撕过程

    ### Tomcat7源码手撕过程详解 #### Tomcat初始化流程分析 Tomcat是一个流行的Java Servlet容器,用于部署和运行Web应用程序。理解Tomcat的工作原理对于优化应用性能、解决部署问题至关重要。以下是对Tomcat7启动...

    maven +Jersey Restful实现源码

    &lt;load-on-startup&gt;1&lt;/load-on-startup&gt; &lt;servlet-mapping&gt; &lt;servlet-name&gt;Jersey Web Application&lt;/servlet-name&gt; &lt;url-pattern&gt;/rest/*&lt;/url-pattern&gt; &lt;/servlet-mapping&gt; ... &lt;/web-app&gt; ``` 这里,`...

    tomcat php 简单配置

    &lt;load-on-startup&gt;1&lt;/load-on-startup&gt; &lt;servlet-mapping&gt; &lt;servlet-name&gt;PHPServlet&lt;/servlet-name&gt; &lt;url-pattern&gt;*.php&lt;/url-pattern&gt; &lt;/servlet-mapping&gt; ``` 这将使Tomcat将所有`.php`扩展名的请求转发到`...

    spring mvc MultiActionController配置方法源码

    &lt;load-on-startup&gt;1&lt;/load-on-startup&gt; &lt;!-- 配置Servlet映射 --&gt; &lt;servlet-mapping&gt; &lt;servlet-name&gt;dispatcher&lt;/servlet-name&gt; &lt;url-pattern&gt;/&lt;/url-pattern&gt; &lt;/servlet-mapping&gt; ``` 4. **Spring MVC配置**: ...

    springmvc环境搭建之配置和所需jar包

    &lt;load-on-startup&gt;1&lt;/load-on-startup&gt; &lt;servlet-mapping&gt; &lt;servlet-name&gt;dispatcher&lt;/servlet-name&gt; &lt;url-pattern&gt;/&lt;/url-pattern&gt; &lt;/servlet-mapping&gt; &lt;/web-app&gt; ``` 然后,在WEB-INF/spring/appServlet...

    cxf tomcat发布

    &lt;load-on-startup&gt;1&lt;/load-on-startup&gt; &lt;servlet-mapping&gt; &lt;servlet-name&gt;CXFServlet&lt;/servlet-name&gt; &lt;url-pattern&gt;/services/*&lt;/url-pattern&gt; &lt;/servlet-mapping&gt; ``` 7. **启动Tomcat**:完成以上步骤后...

    SpringMVC搭建

    &lt;load-on-startup&gt;1&lt;/load-on-startup&gt; &lt;servlet-mapping&gt; &lt;servlet-name&gt;dispatcher&lt;/servlet-name&gt; &lt;url-pattern&gt;/&lt;/url-pattern&gt; &lt;/servlet-mapping&gt; &lt;listener-class&gt;org.springframework.web....

    Spring MVC HelloWorld Maven实例

    &lt;load-on-startup&gt;1&lt;/load-on-startup&gt; &lt;servlet-mapping&gt; &lt;servlet-name&gt;dispatcher&lt;/servlet-name&gt; &lt;url-pattern&gt;/&lt;/url-pattern&gt; &lt;/servlet-mapping&gt; ``` **5. 编译与运行** 通过运行`mvn clean install`...

    Eclipse配置SpringMVC源码

    &lt;load-on-startup&gt;1&lt;/load-on-startup&gt; &lt;servlet-mapping&gt; &lt;servlet-name&gt;dispatcher&lt;/servlet-name&gt; &lt;url-pattern&gt;/&lt;/url-pattern&gt; &lt;/servlet-mapping&gt; ``` - 创建`servlet-context.xml`:在`WEB-INF/...

    JAX-WS 实现WebService发布

    &lt;load-on-startup&gt;1&lt;/load-on-startup&gt; &lt;servlet-mapping&gt; &lt;servlet-name&gt;HelloWorldService&lt;/servlet-name&gt; &lt;url-pattern&gt;/HelloWorldService&lt;/url-pattern&gt; &lt;/servlet-mapping&gt; ``` 然后,将服务实现类和`...

    Spring之MVC 入门实例

    &lt;load-on-startup&gt;1&lt;/load-on-startup&gt; &lt;servlet-mapping&gt; &lt;servlet-name&gt;dispatcher&lt;/servlet-name&gt; &lt;url-pattern&gt;/&lt;/url-pattern&gt; &lt;/servlet-mapping&gt; &lt;/web-app&gt; ``` 2. **servlet-context.xml**:...

    eclipse 搭建SpringMVC框架一

    &lt;load-on-startup&gt;1&lt;/load-on-startup&gt; &lt;servlet-mapping&gt; &lt;servlet-name&gt;dispatcher&lt;/servlet-name&gt; &lt;url-pattern&gt;/&lt;/url-pattern&gt; &lt;/servlet-mapping&gt; &lt;/web-app&gt; ``` 4. **创建servlet-context.xml** ...

    servlet和struts2笔记

    - 可以通过在 `web.xml` 中添加 `&lt;load-on-startup&gt;` 标签来指定 Servlet 随项目启动而自动创建。 - 示例配置: ```xml &lt;servlet-name&gt;AServlet&lt;/servlet-name&gt; &lt;servlet-class&gt;it.cast.AServlet&lt;/servlet-...

Global site tag (gtag.js) - Google Analytics