j2ee标准-web.xml中load-on-startup源码解析

查看tomcat 7.0 源码:

/**
 * Load and initialize all servlets marked "load on startup" in the
 * web application deployment descriptor.
 *
 * @param children Array of wrappers for all currently defined
 *                 servlets (including those not declared load on startup)
 */
/**
 * StandardContext类,代表webapps目录下的一个web应用
 * 方法会被startInternal调用(),也就是应用在启动的时候
 * @param children
 * @return
 */
public boolean loadOnStartup(Container children[]) {

    // Collect "load on startup" servlets that need to be initialized
    //用TreeMap来排序 默认为natural order,也就是按ascii码
    TreeMap<Integer, ArrayList<Wrapper>> map =
            new TreeMap<Integer, ArrayList<Wrapper>>();
    for (int i = 0; i < children.length; i++) {
        Wrapper wrapper = (Wrapper) children[i];
        //每个Wrapper对应一个Servlet,负责创建、初始化、销毁servlet,并为其提供ServletConfig
        int loadOnStartup = wrapper.getLoadOnStartup();
        if (loadOnStartup < 0) //如果loadOnStartup的配置参数小于0,则不添加到TreeMap中
            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);
    }

    // Load the collected "load on startup" servlets
    //按loadOnStartup 的natural order即升序,依次对servlet进行初始化
    for (ArrayList<Wrapper> list : map.values()) {
        for (Wrapper wrapper : list) {
            try {
                //此方法包含对servlet的实例化和init方法的调用
                wrapper.load();
            } catch (ServletException e) {
                getLogger().error(sm.getString("standardContext.loadOnStartup.loadException",
                        getName(), wrapper.getName()), StandardWrapper.getRootCause(e));
                // NOTE: load errors (including a servlet that throws
                // UnavailableException from the init() method) are NOT
                // fatal to application startup
                // unless failCtxIfServletStartFails="true" is specified
                if (getComputedFailCtxIfServletStartFails()) {
                    return false;
                }
            }
        }
    }
    return true;

}

代码和清晰

总结:如果web.xml中的servlet没有配置 <load-on-startup> 标签或者其值小于0,那么在容器启动时不会对其初始化;否则按照数字升序排列串行对其初始化(这也证实了 正数的值越小,启动该servlet的优先级越高 这句话)。

来自:https://blog.csdn.net/joenqc/article/details/73497804


自己动手 单独测试了一下:

一、创建最新的dynamic web project
二、在WebContent目录中(即网站根目录),创建 index.jsp   如下:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>







<h3> helleo  word</h3>







</body>
</html>
三、编辑web.xml  文件 如下:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>webXml</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  <servlet>
    <servlet-name>S1</servlet-name>
    <servlet-class>com.web.servlet.S1</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet>
    <servlet-name>S2</servlet-name>
    <servlet-class>com.web.servlet.S2</servlet-class>
    <load-on-startup>2</load-on-startup>
  </servlet>
  <servlet>
    <servlet-name>S3</servlet-name>
    <servlet-class>com.web.servlet.S3</servlet-class>
    <load-on-startup>-1</load-on-startup>
  </servlet>
  <servlet>
    <servlet-name>S4</servlet-name>
    <servlet-class>com.web.servlet.S4</servlet-class>
    <load-on-startup>4</load-on-startup>
  </servlet>
  <servlet>
    <servlet-name>S5</servlet-name>
    <servlet-class>com.web.servlet.S5</servlet-class>
    <load-on-startup>0</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>S1</servlet-name>
    <url-pattern>/s1</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>S2</servlet-name>
    <url-pattern>/s2</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>S3</servlet-name>
    <url-pattern>/s3</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>S4</servlet-name>
    <url-pattern>/s4</url-pattern>
  </servlet-mapping>
  <servlet-mapping>
    <servlet-name>S5</servlet-name>
    <url-pattern>/s5</url-pattern>
  </servlet-mapping>
</web-app>
四、创建 servlet 文件:

在 com.web.servlet 下面创建 5个 差不多的 servlet (eclipse 右键新建 servlet 即可) ,仅在 url ,构造函数 上进行了修改
S1 代码:

package com.web.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class S1
 */
@WebServlet(name = "S001", urlPatterns = { "/001" })
public class S1 extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public S1() {
        super();
        System.out.println("S1:init ready");
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.getWriter().append("Served at: ").append(request.getContextPath());
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

同理 S2代码如下:

package com.web.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class S1
 */
@WebServlet(name = "S002", urlPatterns = { "/002" })
public class S2 extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public S2() {
        super();
        System.out.println("S2:init ready");
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		response.getWriter().append("Served at: ").append(request.getContextPath());
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}

其他servlet代码 类似

五、测试结果总结:

1、load on startup 大于等于 0,服务器启动时,会加载servlet ,并调用servlet的init方法。当以后 用 url 再访问 servlet时,servlet 不会再创建了,直接回把之前创建好的,直接拿过来用了。

@Override
public void init() throws ServletException {
	// TODO Auto-generated method stub
	super.init();
}

如果load on startup 值小于0,那么服务器启动时不会加载,直达 调用时才会 加载。加载完成后,以后调用时,就直接拿来用了,不会再创建第二遍了。

2、servlet 3.0 加入了注解功能,我上面写的S1。。。都用了注解。url 可以用/S1访问,也可以用 /001 访问。因为 同一个 servlet 配置时取了两个名字,两个路径。服务器 启动时,会当做两个 servlet 来处理,每种 url 访问都会创建一次。

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments