1.版本选择
1.1.SpringMVC版本为3.2.4;
1.2.Tomcat的版本为8.0.47;
1.3.servlet-api的版本为3.1.0;
2.Tomcat的基本原理
2.1.调用在Bootstrap中的主函数main()程序入口调用自身的start()方法,在start()方法中实例化org.apache.catalina.startup.Catalina类调用其start()方法,在Catalina的start()中调用load()载入tomcat文件夹目录下conf文件夹下的server.xml并创建Server类,然后调用Server的start()方法,到这里我们的tomcat就运行起来了.
2.2.Server类代表整个Tomcat服务器,这里有必要介绍一下为什么Tomcat叫Servlet容器,在Tomcat中包含四个容器,分别为Engine,Host,Context,Wrapper.Engine是Host的父容器,依次类推.四者都继承自Container接口.一般在Tomcat中一个Engine实例中包含一个Host实例,一个Host实例中包含一个Context实例,一个Context代表一个WEB程序并包含多个Wrapper实例,一个Wrapper代表一个Servlet类.
2.3.一次请求的大题流程是这样的,首先由Connector获取到Http请求,封装ServletRequest和ServletResponse对象并派发给Context管道中的所有Valve,执行完所有Valve后执行基础Valve根据请求的url映射到对应的Wrapper,然后调用个Wrapper管道中的所有Valve,最后调用基础Valve在如这个Wrapper类所封装的Servlet,实例化后调用器Service方法对用户的请求进行处理,最后将结果负载在response中返回给用户.
3.tomcat运行原理得源码分析
public static void main(String args[])
{
if (daemon == null)
{
// Don't set daemon until init() has completed
Bootstrap bootstrap = new Bootstrap();
try
{
bootstrap.init();
} catch (Throwable t)
{
handleThrowable(t);
t.printStackTrace();
return;
}
daemon = bootstrap;
} else
{
// When running as a service the call to stop will be on a new
// thread so make sure the correct class loader is used to prevent
// a range of class not found exceptions.
Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);
}
try
{
String command = "start";
if (args.length > 0)
{
command = args[args.length - 1];
}
if (command.equals("startd"))
{
args[args.length - 1] = "start";
daemon.load(args);
daemon.start();
} else if (command.equals("stopd"))
{
args[args.length - 1] = "stop";
daemon.stop();
} else if (command.equals("start"))
{
// 在这里读取命令行参数,然后启动。
daemon.setAwait(true);
daemon.load(args);
daemon.start();
} else if (command.equals("stop"))
{
daemon.stopServer(args);
} else if (command.equals("configtest"))
{
daemon.load(args);
if (null == daemon.getServer())
{
System.exit(1);
}
System.exit(0);
} else
{
log.warn("Bootstrap: command \"" + command + "\" does not exist.");
}
} catch (Throwable t)
{
// Unwrap the Exception for clearer error reporting
if (t instanceof InvocationTargetException && t.getCause() != null)
{
t = t.getCause();
}
handleThrowable(t);
t.printStackTrace();
System.exit(1);
}
}
第一次启动是会调用内部生成的Bootstrap类,调用start方法。
public void start() throws Exception
{
if (catalinaDaemon == null)
init();
Method method = catalinaDaemon.getClass().getMethod("start", (Class[]) null);
method.invoke(catalinaDaemon, (Object[]) null);
}
在init方法中实例化Catalinna类然后通过反射调用其start方法。
public void init() throws Exception
{
initClassLoaders();
Thread.currentThread().setContextClassLoader(catalinaLoader);
SecurityClassLoad.securityClassLoad(catalinaLoader);
// Load our startup class and call its process() method
if (log.isDebugEnabled())
log.debug("Loading startup class");
Class<?> startupClass = catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");
Object startupInstance = startupClass.newInstance();
// Set the shared extensions class loader
if (log.isDebugEnabled())
log.debug("Setting startup class properties");
String methodName = "setParentClassLoader";
Class<?> paramTypes[] = new Class[1];
paramTypes[0] = Class.forName("java.lang.ClassLoader");
Object paramValues[] = new Object[1];
paramValues[0] = sharedLoader;
Method method = startupInstance.getClass().getMethod(methodName, paramTypes);
method.invoke(startupInstance, paramValues);
catalinaDaemon = startupInstance;
}
在start()中调用load()方法载入了Server类,然后调用了其start()方法启动了Tomcat.
public void start()
{
if (getServer() == null)
{
load();
}
if (getServer() == null)
{
log.fatal("Cannot start server. Server instance is not configured.");
return;
}
long t1 = System.nanoTime();
// Start the new server
try
{
getServer().start();
} catch (LifecycleException e)
{
log.fatal(sm.getString("catalina.serverStartFail"), e);
try
{
getServer().destroy();
} catch (LifecycleException e1)
{
log.debug("destroy() failed for failed Server ", e1);
}
return;
}
long t2 = System.nanoTime();
if (log.isInfoEnabled())
{
log.info("Server startup in " + ((t2 - t1) / 1000000) + " ms");
}
// Register shutdown hook
if (useShutdownHook)
{
if (shutdownHook == null)
{
shutdownHook = new CatalinaShutdownHook();
}
Runtime.getRuntime().addShutdownHook(shutdownHook);
// If JULI is being used, disable JULI's shutdown hook since
// shutdown hooks run in parallel and log messages may be lost
// if JULI's hook completes before the CatalinaShutdownHook()
LogManager logManager = LogManager.getLogManager();
if (logManager instanceof ClassLoaderLogManager)
{
((ClassLoaderLogManager) logManager).setUseShutdownHook(false);
}
}
if (await)
{
await();
stop();
}
}