查看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 访问都会创建一次。