首页 > 代码库 > Servlet在启动时加载的tomcat源码(原创)

Servlet在启动时加载的tomcat源码(原创)

tomcat 8.0.36

知识点:

  • 通过配置loadOnStartup可以设置Servlet是否在Tomcat启动时加载,以及按值大小进行有序加载,其最小有效值为0,最大有效值为Integer.MAX_VALUE。
  • Jsp Servlet的类是org.apache.jasper.servlet.JspServlet。
  • Jsp Servlet是强制性启动时加载,其loadOnStartup的默认值,或其值是失效值时,将使用最大有效值。
  • 通过配置Context或Host的failCtxIfServletStartFails属性值,优先使用Context的,设置tomcat启动时加载servlet时,是否忽略抛出的ServletException异常,如果不忽略,则tomcat启动失败,默认不忽略。

 

解说源码:

Tomcat在启动时,就会调用loadOnStartup,传入的参数是一个Container[]的数组,这个数组代表的是从我们的web.xml,web-fragment.xml,注解,以及动态添加等方式配置的关于Servlet等信息的数组。

ok设置为false,表示Tomcat启动失败,将无法运作。即loadOnStartup的返回值将影响Tomcat是否运作。

if (!loadOnStartup(findChildren())) {
    ok = false;
}

 

进入loadOnStartup方法后,这里首先定义了一个TreeMap,使用TreeMap的主要目的就是可以排序。

然后遍历Servlet信息集,将遍历中的Servlet信息转化为实际类型Wrapper。

通过getLoadOnStartup方法得到Servlet的启动序级,过滤掉启动序级小于0的Servlet。

接下来,就把大于或等于0的启动序级加入到TreeMap,映射的值是一个Wrapper表,即把Servlet分箱装入到所属启动序级的箱子里面。

TreeMap<Integer, ArrayList<Wrapper>> map = new TreeMap<>();
for (int i = 0; i < children.length; i++) {
    Wrapper wrapper = (Wrapper) children[i];
    int loadOnStartup = wrapper.getLoadOnStartup();
    if (loadOnStartup < 0)
        continue;
    Integer key = Integer.valueOf(loadOnStartup);
    ArrayList<Wrapper> list = map.get(key);
    if (list == null) {
        list = new ArrayList<>();
        map.put(key, list);
    }
    list.add(wrapper);
}

 

先进入getLoadOnStartup方法,这里的成员变量loadOnStartup的默认值是-1,成员变量isJspServlet是记录配置的Servlet的类是不是org.apache.jasper.servlet.JspServlet,一个Servlet是不是Jsp Servlet就看它的类是不是这个类。

简单的说,普通Servlet的启动序级的默认值为-1,最小有效值为0,最大有效值为Integer.MAX_VALUE。Jsp Servlet的启动序级的默认值为最大值,有效值与普通Servlet一致,并且其值失效时将使用最大值。

public int getLoadOnStartup() {
    if (isJspServlet && loadOnStartup < 0) {
        return Integer.MAX_VALUE;
    } else {
        return (this.loadOnStartup);
    }
}

 

回到原来的getLoadOnStartup方法里,map已经把需要启动时加载的Servlet分装到按启动序级排列好的箱子里面,接下来就是先按启动序级顺序,再按加入顺序遍历servlet,并且执行其load方法。

load方法如果抛出ServletException异常,将通过getComputedFailCtxIfServletStartFails获取的值来决定是否让Tomcat启动失败。

而获取的值是Context配置的failCtxIfServletStartFails属性,如果该属性未配置,则使用Host配置failCtxIfServletStartFails的属性,其默认值为false。

for (ArrayList<Wrapper> list : map.values()) {
    for (Wrapper wrapper : list) {
        try {
            wrapper.load();
        } catch (ServletException e) {
            if (getComputedFailCtxIfServletStartFails()) {
                return false;
            }
        }
    }
}
return true;

 

  

Servlet在启动时加载的tomcat源码(原创)