Tomcat
Tomcat是運(yùn)行在Apache之上的應(yīng)用服務(wù)器,為客戶端提供可以調(diào)用的方法严嗜。Tomcat是一個(gè)Servlet容器(可以認(rèn)為Apache的擴(kuò)展),可獨(dú)立運(yùn)行。
基本結(jié)構(gòu)
源碼解析
原版Maven Tomcat源碼來自簡(jiǎn)書《maven構(gòu)建tomcat 源碼》
個(gè)人注釋版Tomcat源碼Github Tomcat8.5
類/接口 | 作用 |
---|---|
Bootstrap | 啟動(dòng)類扮叨,封裝了Catalina的基本方法(通過反射) |
CatalinaProperties | 初始化Tomcat的配置并注冊(cè)到System中 |
Catalina | 啟動(dòng)/關(guān)閉命令行程序 |
Digester | 配置解析器,封裝了XMLReader领迈,通過配置可讀取XML并轉(zhuǎn)化成對(duì)象 |
Lifecycle | 生命周期接口彻磁,擁有init、start狸捅、stop衷蜓、destroy四個(gè)周期API以及添加生命周期監(jiān)聽器LiftcycleListener的API<br />繼承自此接口的類有:Server、Service尘喝、Connector磁浇、Engine、Host朽褪、Context |
Server | 代表Tomcat服務(wù)器 |
Service | 封裝幾個(gè)連接器和一個(gè)主機(jī)容器Engine置吓,主要用于分組連接器-主機(jī),便于管理 |
Connector | 代表一個(gè)連接器缔赠,負(fù)責(zé)維護(hù)客戶端和服務(wù)器端的連接 |
Engine | 主機(jī)容器衍锚,封裝幾個(gè)主機(jī)以便統(tǒng)一管理 |
Host | 代表一個(gè)虛擬主機(jī) |
Context | 代表一個(gè)Web應(yīng)用 |
Bootstrap啟動(dòng)類
Bootstrap擁有main方法,是Tomcat的啟動(dòng)類
/**
* 初始化daemon并使用daemon執(zhí)行命令(無參數(shù)默認(rèn)啟動(dòng)嗤堰,有參數(shù)則根據(jù)參數(shù)啟動(dòng)/停止/配置測(cè)試)
* @param args 命令參數(shù)
*/
public static void main(String args[]) {
//初始化daemon
if (daemon == null) {
// 創(chuàng)建一個(gè)Bootstrap對(duì)象戴质,初始化并賦值給daemon
Bootstrap bootstrap = new Bootstrap();
try {
bootstrap.init();
}
//簡(jiǎn)單打印錯(cuò)誤堆棧,然后重新拋出
catch (Throwable t) {
handleThrowable(t);
t.printStackTrace();
return;
}
daemon = bootstrap;
} else {
//有另一個(gè)線程已經(jīng)為daemon賦值踢匣,則讓當(dāng)前線程使用daemon的上下文類加載器
Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);
}
//使用daemon執(zhí)行命令,默認(rèn)start(調(diào)用Catalina的setAwait告匠、load、start)
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();
if (null == daemon.getServer()) {
System.exit(1);
}
} 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);
}
}
public void init() throws Exception {
//初始化類加載器
initClassLoaders();
//為當(dāng)前線程設(shè)置上下文類加載器
Thread.currentThread().setContextClassLoader(catalinaLoader);
SecurityClassLoad.securityClassLoad(catalinaLoader);
if (log.isDebugEnabled())
log.debug("Loading startup class");
//加載啟動(dòng)類——Catalina符糊,并獲取其實(shí)例
Class<?> startupClass = catalinaLoader.loadClass("org.apache.catalina.startup.Catalina");
Object startupInstance = startupClass.getConstructor().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;
//反射調(diào)用Catalina的setParentClassLoader方法設(shè)置父類加載器為sharedLoader
Method method =
startupInstance.getClass().getMethod(methodName, paramTypes);
method.invoke(startupInstance, paramValues);
//將實(shí)例化出的Catalina設(shè)置為Catalina守護(hù)
catalinaDaemon = startupInstance;
}
private void initClassLoaders() {
try {
//調(diào)用createClassLoader創(chuàng)建common加載器
commonLoader = createClassLoader("common", null);
if( commonLoader == null ) {
// no config file, default to this loader - we might be in a 'single' env.
commonLoader=this.getClass().getClassLoader();
}
//調(diào)用createClassLoader創(chuàng)建catalina加載器和shared加載器
catalinaLoader = createClassLoader("server", commonLoader);
sharedLoader = createClassLoader("shared", commonLoader);
} catch (Throwable t) {
handleThrowable(t);
log.error("Class loader creation threw exception", t);
System.exit(1);
}
}
//創(chuàng)建出的類加載器是加載指定路徑j(luò)ar包的UrlClassLoader
private ClassLoader createClassLoader(String name, ClassLoader parent)
throws Exception {
//根據(jù)加載器名字從Catalina屬性集獲取屬性值(來自catalina.properties)
//Debug:value="${catalina.base}/lib","${catalina.base}/lib/*.jar","${catalina.home}/lib","${catalina.home}/lib/*.jar"
String value = CatalinaProperties.getProperty(name + ".loader");
if ((value == null) || (value.equals("")))
return parent;
value = replace(value);
List<Repository> repositories = new ArrayList<>();
String[] repositoryPaths = getPaths(value);
//根據(jù)類加載器屬性(jar包地址)生成資源集合
for (String repository : repositoryPaths) {
// Check for a JAR URL repository
try {
@SuppressWarnings("unused")
URL url = new URL(repository);
repositories.add(
new Repository(repository, RepositoryType.URL));
continue;
} catch (MalformedURLException e) {
// Ignore
}
// Local repository
if (repository.endsWith("*.jar")) {
repository = repository.substring
(0, repository.length() - "*.jar".length());
repositories.add(
new Repository(repository, RepositoryType.GLOB));
} else if (repository.endsWith(".jar")) {
repositories.add(
new Repository(repository, RepositoryType.JAR));
} else {
repositories.add(
new Repository(repository, RepositoryType.DIR));
}
}
//根據(jù)jar包路徑資源集合創(chuàng)建類加載器——加載指定路徑下jar包的UrlClassLoader
return ClassLoaderFactory.createClassLoader(repositories, parent);
}
CatalinaProperties配置
CatalinaProperties在加載期獲取Catalina的配置并注冊(cè)到System屬性中
static {
loadProperties();
}
//加載屬性集并注冊(cè)到System中
private static void loadProperties() {
//屬性文件輸入流
InputStream is = null;
try {
//屬性文件路徑:系統(tǒng)屬性"catalina.config"
String configUrl = System.getProperty("catalina.config");
if (configUrl != null) {
is = (new URL(configUrl)).openStream();
}
} catch (Throwable t) {
handleThrowable(t);
}
//系統(tǒng)屬性為空則 Tomcat項(xiàng)目根目錄\conf\catalina.properties文件
if (is == null) {
try {
File home = new File(Bootstrap.getCatalinaBase());
File conf = new File(home, "conf");
File propsFile = new File(conf, "catalina.properties");
is = new FileInputStream(propsFile);
} catch (Throwable t) {
handleThrowable(t);
}
}
//Tomcat項(xiàng)目根目錄\conf\catalina.properties文件不存在則class目錄/org/apache/catalina/startup/catalina.properties文件
if (is == null) {
try {
is = CatalinaProperties.class.getResourceAsStream
("/org/apache/catalina/startup/catalina.properties");
} catch (Throwable t) {
handleThrowable(t);
}
}
//配置文件不為空凫海,加載配置
if (is != null) {
try {
properties = new Properties();
properties.load(is);
} catch (Throwable t) {
handleThrowable(t);
log.warn(t);
} finally {
try {
is.close();
} catch (IOException ioe) {
log.warn("Could not close catalina.properties", ioe);
}
}
}
//屬性文件仍舊為空,使用空值對(duì)象取代null(新建Properties對(duì)象)
if ((is == null)) {
// Do something
log.warn("Failed to load catalina.properties");
// That's fine - we have reasonable defaults.
properties = new Properties();
}
// 最后把屬性全部注冊(cè)進(jìn)System中
Enumeration<?> enumeration = properties.propertyNames();
while (enumeration.hasMoreElements()) {
String name = (String) enumeration.nextElement();
String value = properties.getProperty(name);
if (value != null) {
System.setProperty(name, value);
}
}
}
#配置訪問權(quán)限(UrlClassLoader在加載類時(shí)會(huì)核對(duì)權(quán)限)男娄,擁有RuntimePermission ("accessClassInPackage."+package)權(quán)限方可訪問
package.access=sun.,org.apache.catalina.,org.apache.coyote.,org.apache.jasper.,org.apache.tomcat.
#配置能夠通過checkPackageDefinition的權(quán)限:RuntimePermission ("defineClassInPackage."+package)
package.definition=sun.,java.,org.apache.catalina.,org.apache.coyote.,\
org.apache.jasper.,org.apache.naming.,org.apache.tomcat.
#配置類加載器的加載路徑(用于加載Catalina的類加載器)
common.loader="${catalina.base}/lib","${catalina.base}/lib/*.jar","${catalina.home}/lib","${catalina.home}/lib/*.jar"
#配置類加載器的加載路徑(用于加載Server)
server.loader=
#共享型類加載器的加載路徑
shared.loader=
# 配置JarScanner跳過掃描的jar包
# The JARs listed below include:
# - Tomcat Bootstrap JARs
# - Tomcat API JARs
# - Catalina JARs
# - Jasper JARs
# - Tomcat JARs
# - Common non-Tomcat JARs
# - Test JARs (JUnit, Cobertura and dependencies)
tomcat.util.scan.StandardJarScanFilter.jarsToSkip=\
annotations-api.jar,\
ant-junit*.jar,\
ant-launcher.jar,\
ant.jar,\
asm-*.jar,\
aspectj*.jar,\
bootstrap.jar,\
catalina-ant.jar,\
catalina-ha.jar,\
catalina-jmx-remote.jar,\
catalina-storeconfig.jar,\
catalina-tribes.jar,\
catalina-ws.jar,\
catalina.jar,\
cglib-*.jar,\
cobertura-*.jar,\
commons-beanutils*.jar,\
commons-codec*.jar,\
commons-collections*.jar,\
commons-daemon.jar,\
commons-dbcp*.jar,\
commons-digester*.jar,\
commons-fileupload*.jar,\
commons-httpclient*.jar,\
commons-io*.jar,\
commons-lang*.jar,\
commons-logging*.jar,\
commons-math*.jar,\
commons-pool*.jar,\
dom4j-*.jar,\
easymock-*.jar,\
ecj-*.jar,\
el-api.jar,\
geronimo-spec-jaxrpc*.jar,\
h2*.jar,\
hamcrest-*.jar,\
hibernate*.jar,\
httpclient*.jar,\
icu4j-*.jar,\
jasper-el.jar,\
jasper.jar,\
jaspic-api.jar,\
jaxb-*.jar,\
jaxen-*.jar,\
jdom-*.jar,\
jetty-*.jar,\
jmx-tools.jar,\
jmx.jar,\
jsp-api.jar,\
jstl.jar,\
jta*.jar,\
junit-*.jar,\
junit.jar,\
log4j*.jar,\
mail*.jar,\
objenesis-*.jar,\
oraclepki.jar,\
oro-*.jar,\
servlet-api-*.jar,\
servlet-api.jar,\
slf4j*.jar,\
taglibs-standard-spec-*.jar,\
tagsoup-*.jar,\
tomcat-api.jar,\
tomcat-coyote.jar,\
tomcat-dbcp.jar,\
tomcat-i18n-*.jar,\
tomcat-jdbc.jar,\
tomcat-jni.jar,\
tomcat-juli-adapters.jar,\
tomcat-juli.jar,\
tomcat-util-scan.jar,\
tomcat-util.jar,\
tomcat-websocket.jar,\
tools.jar,\
websocket-api.jar,\
wsdl4j*.jar,\
xercesImpl.jar,\
xml-apis.jar,\
xmlParserAPIs-*.jar,\
xmlParserAPIs.jar,\
xom-*.jar
# 需要掃描的jar包(jarsToSkip配置的目錄下可能有需要掃描的jar包)
tomcat.util.scan.StandardJarScanFilter.jarsToScan=\
log4j-taglib*.jar,\
log4j-web*.jar,\
log4javascript*.jar,\
slf4j-taglib*.jar
# 字符串緩存配置
tomcat.util.buf.StringCache.byte.enabled=true
#tomcat.util.buf.StringCache.char.enabled=true
#tomcat.util.buf.StringCache.trainThreshold=500000
#tomcat.util.buf.StringCache.cacheSize=5000
Catalina
Catalina是真正啟動(dòng)Tomcat的類(Bootstrap相當(dāng)于Catalina的對(duì)外代理人)
public Catalina() {
//向Security注冊(cè)訪問權(quán)限
setSecurityProtection();
//空方法行贪,提前觸發(fā)ExceptionUtils的加載
ExceptionUtils.preload();
}
protected void setSecurityProtection(){
//獲取SecurityConfig單例,SecurityConfig從catalina.properties文件中讀取Security屬性(沒有則使用默認(rèn)值)并設(shè)置到Security中
SecurityConfig securityConfig = SecurityConfig.newInstance();
//設(shè)置包定義權(quán)限
securityConfig.setPackageDefinition();
//設(shè)置包訪問權(quán)權(quán)限
securityConfig.setPackageAccess();
}
public void load() {
if (loaded) {
return;
}
loaded = true;
long t1 = System.nanoTime();
//初始化臨時(shí)目錄
initDirs();
// 初始化命名Before digester - it may be needed
initNaming();
// 創(chuàng)建并啟動(dòng)配置文件解析器
Digester digester = createStartDigester();
InputSource inputSource = null;
InputStream inputStream = null;
File file = null;
try {
try {
//獲取配置文件
file = configFile();
inputStream = new FileInputStream(file);
inputSource = new InputSource(file.toURI().toURL().toString());
} catch (Exception e) {
if (log.isDebugEnabled()) {
log.debug(sm.getString("catalina.configFail", file), e);
}
}
if (inputStream == null) {
try {
inputStream = getClass().getClassLoader()
.getResourceAsStream(getConfigFile());
inputSource = new InputSource
(getClass().getClassLoader()
.getResource(getConfigFile()).toString());
} catch (Exception e) {
if (log.isDebugEnabled()) {
log.debug(sm.getString("catalina.configFail",
getConfigFile()), e);
}
}
}
// 配用配置類加載器目錄/server-embed.xml
if (inputStream == null) {
try {
inputStream = getClass().getClassLoader()
.getResourceAsStream("server-embed.xml");
inputSource = new InputSource
(getClass().getClassLoader()
.getResource("server-embed.xml").toString());
} catch (Exception e) {
if (log.isDebugEnabled()) {
log.debug(sm.getString("catalina.configFail",
"server-embed.xml"), e);
}
}
}
if (inputStream == null || inputSource == null) {
if (file == null) {
log.warn(sm.getString("catalina.configFail",
getConfigFile() + "] or [server-embed.xml]"));
} else {
log.warn(sm.getString("catalina.configFail",
file.getAbsolutePath()));
if (file.exists() && !file.canRead()) {
log.warn("Permissions incorrect, read permission is not allowed on the file.");
}
}
return;
}
try {
inputSource.setByteStream(inputStream);
digester.push(this);
digester.parse(inputSource);
} catch (SAXParseException spe) {
log.warn("Catalina.start using " + getConfigFile() + ": " +
spe.getMessage());
return;
} catch (Exception e) {
log.warn("Catalina.start using " + getConfigFile() + ": " , e);
return;
}
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (IOException e) {
// Ignore
}
}
}
//設(shè)置Server屬性(Catalina模闲、Catalina主目錄建瘫、Catalina根目錄)
//在Bootstrap的靜態(tài)塊中初始化(先System后用戶路徑/bootstrap.jar)
getServer().setCatalina(this);
getServer().setCatalinaHome(Bootstrap.getCatalinaHomeFile());
getServer().setCatalinaBase(Bootstrap.getCatalinaBaseFile());
//重定向流
initStreams();
// 初始化啟動(dòng)Server
try {
getServer().init();
} catch (LifecycleException e) {
if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE")) {
throw new java.lang.Error(e);
} else {
log.error("Catalina.start", e);
}
}
long t2 = System.nanoTime();
if(log.isInfoEnabled()) {
log.info("Initialization processed in " + ((t2 - t1) / 1000000) + " ms");
}
}
public void start() {
//Server尚為空——重新加載
if (getServer() == null) {
load();
}
if (getServer() == null) {
log.fatal("Cannot start server. Server instance is not configured.");
return;
}
long t1 = System.nanoTime();
// 啟動(dòng)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");
}
// 如果掛了關(guān)閉鉤子——初始化鉤子
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();
}
}
public void stop() {
//移除關(guān)閉鉤子(防止被再次觸發(fā))
try {
if (useShutdownHook) {
Runtime.getRuntime().removeShutdownHook(shutdownHook);
LogManager logManager = LogManager.getLogManager();
if (logManager instanceof ClassLoaderLogManager) {
((ClassLoaderLogManager) logManager).setUseShutdownHook(
true);
}
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
}
// 停止并銷毀Server
try {
Server s = getServer();
LifecycleState state = s.getState();
if (LifecycleState.STOPPING_PREP.compareTo(state) <= 0
&& LifecycleState.DESTROYED.compareTo(state) >= 0) {
// Nothing to do. stop() was already called
} else {
s.stop();
s.destroy();
}
} catch (LifecycleException e) {
log.error("Catalina.stop", e);
}
}
配置解析器Digester
封裝了XMLReader,通過配置可讀取XML并轉(zhuǎn)化成對(duì)象尸折,用于將服務(wù)器配置(默認(rèn)server.xml)轉(zhuǎn)化為Server對(duì)象
protected Digester createStartDigester() {
long t1=System.currentTimeMillis();
// Initialize the digester
Digester digester = new Digester();
digester.setValidating(false);
digester.setRulesValidation(true);
Map<Class<?>, List<String>> fakeAttributes = new HashMap<>();
List<String> objectAttrs = new ArrayList<>();
objectAttrs.add("className");
fakeAttributes.put(Object.class, objectAttrs);
// Ignore attribute added by Eclipse for its internal tracking
List<String> contextAttrs = new ArrayList<>();
contextAttrs.add("source");
fakeAttributes.put(StandardContext.class, contextAttrs);
digester.setFakeAttributes(fakeAttributes);
digester.setUseContextClassLoader(true);
// Configure the actions we will be using
digester.addObjectCreate("Server",
"org.apache.catalina.core.StandardServer",
"className");
digester.addSetProperties("Server");
digester.addSetNext("Server",
"setServer",
"org.apache.catalina.Server");
digester.addObjectCreate("Server/GlobalNamingResources",
"org.apache.catalina.deploy.NamingResourcesImpl");
digester.addSetProperties("Server/GlobalNamingResources");
digester.addSetNext("Server/GlobalNamingResources",
"setGlobalNamingResources",
"org.apache.catalina.deploy.NamingResourcesImpl");
digester.addObjectCreate("Server/Listener",
null, // MUST be specified in the element
"className");
digester.addSetProperties("Server/Listener");
digester.addSetNext("Server/Listener",
"addLifecycleListener",
"org.apache.catalina.LifecycleListener");
digester.addObjectCreate("Server/Service",
"org.apache.catalina.core.StandardService",
"className");
digester.addSetProperties("Server/Service");
digester.addSetNext("Server/Service",
"addService",
"org.apache.catalina.Service");
digester.addObjectCreate("Server/Service/Listener",
null, // MUST be specified in the element
"className");
digester.addSetProperties("Server/Service/Listener");
digester.addSetNext("Server/Service/Listener",
"addLifecycleListener",
"org.apache.catalina.LifecycleListener");
//Executor
digester.addObjectCreate("Server/Service/Executor",
"org.apache.catalina.core.StandardThreadExecutor",
"className");
digester.addSetProperties("Server/Service/Executor");
digester.addSetNext("Server/Service/Executor",
"addExecutor",
"org.apache.catalina.Executor");
digester.addRule("Server/Service/Connector",
new ConnectorCreateRule());
digester.addRule("Server/Service/Connector",
new SetAllPropertiesRule(new String[]{"executor", "sslImplementationName"}));
digester.addSetNext("Server/Service/Connector",
"addConnector",
"org.apache.catalina.connector.Connector");
digester.addObjectCreate("Server/Service/Connector/SSLHostConfig",
"org.apache.tomcat.util.net.SSLHostConfig");
digester.addSetProperties("Server/Service/Connector/SSLHostConfig");
digester.addSetNext("Server/Service/Connector/SSLHostConfig",
"addSslHostConfig",
"org.apache.tomcat.util.net.SSLHostConfig");
digester.addRule("Server/Service/Connector/SSLHostConfig/Certificate",
new CertificateCreateRule());
digester.addRule("Server/Service/Connector/SSLHostConfig/Certificate",
new SetAllPropertiesRule(new String[]{"type"}));
digester.addSetNext("Server/Service/Connector/SSLHostConfig/Certificate",
"addCertificate",
"org.apache.tomcat.util.net.SSLHostConfigCertificate");
digester.addObjectCreate("Server/Service/Connector/SSLHostConfig/OpenSSLConf",
"org.apache.tomcat.util.net.openssl.OpenSSLConf");
digester.addSetProperties("Server/Service/Connector/SSLHostConfig/OpenSSLConf");
digester.addSetNext("Server/Service/Connector/SSLHostConfig/OpenSSLConf",
"setOpenSslConf",
"org.apache.tomcat.util.net.openssl.OpenSSLConf");
digester.addObjectCreate("Server/Service/Connector/SSLHostConfig/OpenSSLConf/OpenSSLConfCmd",
"org.apache.tomcat.util.net.openssl.OpenSSLConfCmd");
digester.addSetProperties("Server/Service/Connector/SSLHostConfig/OpenSSLConf/OpenSSLConfCmd");
digester.addSetNext("Server/Service/Connector/SSLHostConfig/OpenSSLConf/OpenSSLConfCmd",
"addCmd",
"org.apache.tomcat.util.net.openssl.OpenSSLConfCmd");
digester.addObjectCreate("Server/Service/Connector/Listener",
null, // MUST be specified in the element
"className");
digester.addSetProperties("Server/Service/Connector/Listener");
digester.addSetNext("Server/Service/Connector/Listener",
"addLifecycleListener",
"org.apache.catalina.LifecycleListener");
digester.addObjectCreate("Server/Service/Connector/UpgradeProtocol",
null, // MUST be specified in the element
"className");
digester.addSetProperties("Server/Service/Connector/UpgradeProtocol");
digester.addSetNext("Server/Service/Connector/UpgradeProtocol",
"addUpgradeProtocol",
"org.apache.coyote.UpgradeProtocol");
// Add RuleSets for nested elements
digester.addRuleSet(new NamingRuleSet("Server/GlobalNamingResources/"));
digester.addRuleSet(new EngineRuleSet("Server/Service/"));
digester.addRuleSet(new HostRuleSet("Server/Service/Engine/"));
digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/"));
addClusterRuleSet(digester, "Server/Service/Engine/Host/Cluster/");
digester.addRuleSet(new NamingRuleSet("Server/Service/Engine/Host/Context/"));
// When the 'engine' is found, set the parentClassLoader.
digester.addRule("Server/Service/Engine",
new SetParentClassLoaderRule(parentClassLoader));
addClusterRuleSet(digester, "Server/Service/Engine/Cluster/");
long t2=System.currentTimeMillis();
if (log.isDebugEnabled()) {
log.debug("Digester for server.xml created " + ( t2-t1 ));
}
return (digester);
}
public Object parse(InputSource input) throws IOException, SAXException {
//確認(rèn)是否配置過
configure();
//用自身配置配置XMLReader啰脚,然后用XMLReader解析XML文件
getXMLReader().parse(input);
return (root);
}
<?xml version="1.0" encoding="UTF-8"?>
<!-- Server -->
<Server port="8005" shutdown="SHUTDOWN">
<!--幾個(gè)生命周期監(jiān)聽器-->
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<!--全局JNDI服務(wù)命名資源集-->
<GlobalNamingResources>
<!--用戶數(shù)據(jù)庫(xml數(shù)據(jù)庫),用于讓UserDatabaseRealm校驗(yàn)用戶身份-->
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<!-- Service -->
<Service name="Catalina">
<!--Connector的共享執(zhí)行器-->
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
maxThreads="150" minSpareThreads="4"/>
<!--Connector連接器,擁有執(zhí)行器橄浓、端口粒梦、協(xié)議、超時(shí)時(shí)限和重定向端口等屬性-->
<Connector executor="tomcatThreadPool"
port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<!--定義一個(gè) 實(shí)現(xiàn)NIO的基于SSL/TLS HTTP/1.1連接的連接器-->
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true">
<SSLHostConfig>
<Certificate certificateKeystoreFile="conf/localhost-rsa.jks"
type="RSA" />
</SSLHostConfig>
</Connector>
<!-- 定義一個(gè) 協(xié)議為 AJP 1.3 的連接器 -->
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
<!-- Engine:處理請(qǐng)求荸实,分析請(qǐng)求頭然后傳遞給指定的主機(jī)Host -->
<Engine name="Catalina" defaultHost="localhost">
<!-- 用戶身份權(quán)限認(rèn)證 -->
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<!--虛擬主機(jī)-->
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<!--單例值匀们,保存用戶認(rèn)證信息,此值在多個(gè)Web應(yīng)用下共享-->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>
</Service>
</Server>
生命周期Lifecycle
Lifecycle接口代表組件的生命周期准给,擁有init泄朴、start、stop露氮、destory四個(gè)生命周期方法祖灰,并可添加LifecycleListener生命周期監(jiān)聽器,并定義了若干監(jiān)聽器觸發(fā)事件(初始化前 初始化后 啟動(dòng)前 啟動(dòng) 啟動(dòng)后 停止前 停止 停止后 銷毀前 銷毀后)
骨架類LifecycleBase
簡(jiǎn)單實(shí)現(xiàn)Lifecycle接口——同步生命周期API畔规,確保生命周期狀態(tài)正常變更局扶,并將具體實(shí)現(xiàn)職責(zé)下放到XXXInternal中
//未聲明構(gòu)造函數(shù),默認(rèn)構(gòu)造函數(shù)
public final synchronized void init() throws LifecycleException {
//狀態(tài)為New方可初始化
if (!state.equals(LifecycleState.NEW)) {
//拋出狀態(tài)異常
invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
}
try {
//狀態(tài)變更——初始化中
setStateInternal(LifecycleState.INITIALIZING, null, false);
//初始化具體邏輯
initInternal();
//狀態(tài)變更——初始化后
setStateInternal(LifecycleState.INITIALIZED, null, false);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException(
sm.getString("lifecycleBase.initFail",toString()), t);
}
}
//狀態(tài)為New——現(xiàn)初始化
//狀態(tài)為Failed——停止
//狀態(tài)不為初始化完成或已停止——生命周期異常
public final synchronized void start() throws LifecycleException {
//狀態(tài)為啟動(dòng)前叁扫、中详民、后——不可啟動(dòng)
if (LifecycleState.STARTING_PREP.equals(state) || LifecycleState.STARTING.equals(state) ||
LifecycleState.STARTED.equals(state)) {
if (log.isDebugEnabled()) {
Exception e = new LifecycleException();
log.debug(sm.getString("lifecycleBase.alreadyStarted", toString()), e);
} else if (log.isInfoEnabled()) {
log.info(sm.getString("lifecycleBase.alreadyStarted", toString()));
}
return;
}
//狀態(tài)為New——現(xiàn)初始化
if (state.equals(LifecycleState.NEW)) {
init();
//狀態(tài)為Failed——停止
} else if (state.equals(LifecycleState.FAILED)) {
stop();
//狀態(tài)不為初始化完成或已停止——生命周期異常
} else if (!state.equals(LifecycleState.INITIALIZED) &&
!state.equals(LifecycleState.STOPPED)) {
invalidTransition(Lifecycle.BEFORE_START_EVENT);
}
try {
//狀態(tài)變更——啟動(dòng)前
setStateInternal(LifecycleState.STARTING_PREP, null, false);
startInternal();
//狀態(tài)為啟動(dòng)失敗——停止
if (state.equals(LifecycleState.FAILED)) {
stop();
//狀態(tài)不為啟動(dòng)中——生命周期異常
} else if (!state.equals(LifecycleState.STARTING)) {
invalidTransition(Lifecycle.AFTER_START_EVENT);
//狀態(tài)變更——啟動(dòng)后
} else {
setStateInternal(LifecycleState.STARTED, null, false);
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException(sm.getString("lifecycleBase.startFail", toString()), t);
}
}
//New——直接設(shè)置為停止后
//啟動(dòng)后/啟動(dòng)失敗——執(zhí)行停止
public final synchronized void stop() throws LifecycleException {
//狀態(tài)為停止前、中陌兑、后——生命周期異常
if (LifecycleState.STOPPING_PREP.equals(state) || LifecycleState.STOPPING.equals(state) ||
LifecycleState.STOPPED.equals(state)) {
if (log.isDebugEnabled()) {
Exception e = new LifecycleException();
log.debug(sm.getString("lifecycleBase.alreadyStopped", toString()), e);
} else if (log.isInfoEnabled()) {
log.info(sm.getString("lifecycleBase.alreadyStopped", toString()));
}
return;
}
//狀態(tài)為New——變更為已停止
if (state.equals(LifecycleState.NEW)) {
state = LifecycleState.STOPPED;
return;
}
//狀態(tài)不為啟動(dòng)后或啟動(dòng)失敗——生命周期異常
if (!state.equals(LifecycleState.STARTED) && !state.equals(LifecycleState.FAILED)) {
invalidTransition(Lifecycle.BEFORE_STOP_EVENT);
}
try {
if (state.equals(LifecycleState.FAILED)) {
//觸發(fā)監(jiān)聽器事件——停止前
fireLifecycleEvent(BEFORE_STOP_EVENT, null);
} else {
setStateInternal(LifecycleSta te.STOPPING_PREP, null, false);
}
stopInternal();
if (!state.equals(LifecycleState.STOPPING) && !state.equals(LifecycleState.FAILED)) {
invalidTransition(Lifecycle.AFTER_STOP_EVENT);
}
setStateInternal(LifecycleState.STOPPED, null, false);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException(sm.getString("lifecycleBase.stopFail",toString()), t);
} finally {
if (this instanceof Lifecycle.SingleUse) {
// Complete stop process first
setStateInternal(LifecycleState.STOPPED, null, false);
destroy();
}
}
}
//啟動(dòng)失敗——先調(diào)停止,再觸發(fā)銷毀
//New由捎、初始化后兔综、啟動(dòng)后、停止后——觸發(fā)銷毀
public final synchronized void destroy() throws LifecycleException {
//啟動(dòng)失敗——觸發(fā)停止
if (LifecycleState.FAILED.equals(state)) {
try {
// Triggers clean-up
stop();
} catch (LifecycleException e) {
// Just log. Still want to destroy.
log.error(sm.getString("lifecycleBase.destroyStopFail", toString()), e);
}
}
//銷毀中或已銷毀——生命周期異常
if (LifecycleState.DESTROYING.equals(state) ||
LifecycleState.DESTROYED.equals(state)) {
if (log.isDebugEnabled()) {
Exception e = new LifecycleException();
log.debug(sm.getString("lifecycleBase.alreadyDestroyed", toString()), e);
} else if (log.isInfoEnabled() && !(this instanceof Lifecycle.SingleUse)) {
// Rather than have every component that might need to call
// destroy() check for SingleUse, don't log an info message if
// multiple calls are made to destroy()
log.info(sm.getString("lifecycleBase.alreadyDestroyed", toString()));
}
return;
}
//狀態(tài)不為已停止或啟動(dòng)失敗或New或初始化完成——生命周期異常
if (!state.equals(LifecycleState.STOPPED) &&
!state.equals(LifecycleState.FAILED) &&
!state.equals(LifecycleState.NEW) &&
!state.equals(LifecycleState.INITIALIZED)) {
invalidTransition(Lifecycle.BEFORE_DESTROY_EVENT);
}
try {
setStateInternal(LifecycleState.DESTROYING, null, false);
destroyInternal();
setStateInternal(LifecycleState.DESTROYED, null, false);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
setStateInternal(LifecycleState.FAILED, null, false);
throw new LifecycleException(
sm.getString("lifecycleBase.destroyFail",toString()), t);
}
}
LifecycleMBeanBase
Tomcat構(gòu)件基礎(chǔ)狞玛,Tomcat的構(gòu)件基本都繼承或間接繼承自此類
//未聲明構(gòu)造函數(shù)软驰,默認(rèn)構(gòu)造函數(shù)
protected void initInternal() throws LifecycleException {
//oname為空代表未注冊(cè)到命名服務(wù)——將當(dāng)前對(duì)象注冊(cè)到命名服務(wù)
if (oname == null) {
mserver = Registry.getRegistry(null, null).getMBeanServer();
oname = register(this, getObjectNameKeyProperties());
}
}
//未實(shí)現(xiàn)startInternal()
//未實(shí)現(xiàn)stopInternal()
//未實(shí)現(xiàn)destoryInternal()
組件注冊(cè)器Registry
組件(MBean)注冊(cè)器:提供創(chuàng)建和操作組件以及簡(jiǎn)化組件使用的類,其本身也是一個(gè)組件
實(shí)現(xiàn)了RegistryMBean接口和MBeanRegistration接口
意義 | 變量 |
---|---|
日志 | Log log |
注冊(cè)器集(以web應(yīng)用為鍵) | HashMap<Object,Registry> perLoaderRegistries |
組件集(以名為鍵) | HashMap<String,ManagedBean> descriptors |
組件集(以類名為鍵) | HashMap<String,ManagedBean> descriptorsByClass |
URL集(以名為鍵) | HashMap<String,URL> searchedPaths |
id所在域集(以域名為鍵) | Hashtable<String,Hashtable<String,Integer>> idDomains |
id集(以名為鍵) | Hashtable<String,int[]> ids |
RegistryMBean接口
組件注冊(cè)器的主要接口:提供創(chuàng)建和操作組件以及簡(jiǎn)化組件使用的方法
作用 | API |
---|---|
注冊(cè)/取消注冊(cè)組件 | register/unRegisterComponent |
調(diào)用指定組件列表中所有組件的一個(gè)指定的操作 | invoke |
獲取能夠更快訪問的ID | getId |
終止并回到初始狀態(tài) | stop |
MBeanRegistration接口
組件注冊(cè)的監(jiān)聽器接口心肪,提供注冊(cè)锭亏、取消注冊(cè)觸發(fā)事件的方法
作用 | API |
---|---|
注冊(cè)前/后觸發(fā) | pre/postRegister |
取消注冊(cè)前/后觸發(fā) | pre/postDeregister |
服務(wù)器Server
Server代表整個(gè)Servlet容器
Server接口繼承自Lifecycle接口,并提供了大量服務(wù)器相關(guān)API
類型 | 作用 | API |
---|---|---|
獲取/設(shè)置 | 所在Catalina | get/setCatalina |
Catalina的base路徑 | get/setCatalinaBase | |
Catalina的home路徑 | get/setCatalinaHome | |
全局命名資源 | get/setGlobalNamingResource | |
全局命名上下文 | get/setGlobalNamingContext | |
等待的Shutdown命令字符串 | get/setShutdown | |
地址 | get/setAddress | |
端口號(hào) | get/setPort | |
其他 | 等待直到Shutdown命令到達(dá) | await |
查找Service | findService(String name) | |
獲取Service集合 | findService | |
增刪Service | add/removeService |
實(shí)現(xiàn)類StandardServer
繼承自LifecycleMBeanBase類硬鞍,實(shí)現(xiàn)Server接口
public StandardServer() {
super();
//初始化全局命名資源集
globalNamingResources = new NamingResourcesImpl();
globalNamingResources.setContainer(this);
//使用了命名服務(wù)——添加命名上下文監(jiān)聽器
if (isUseNaming()) {
namingContextListener = new NamingContextListener();
addLifecycleListener(namingContextListener);
} else {
namingContextListener = null;
}
}
protected void initInternal() throws LifecycleException {
super.initInternal();
// JNDI服務(wù)端注冊(cè)字符串緩存服務(wù)(類型為StringCache)
onameStringCache = register(new StringCache(), "type=StringCache");
// JNDI服務(wù)端注冊(cè)組件工程服務(wù)(類型為MBeanFactory)
MBeanFactory factory = new MBeanFactory();
factory.setContainer(this);
onameMBeanFactory = register(factory, "type=MBeanFactory");
// 從JDNI命名資源集中提取數(shù)據(jù)注冊(cè)到JNDI服務(wù)
globalNamingResources.init();
// 加載類(來自Catalina.properties慧瘤,在Bootstrap的initClassLoader方法中將jar路徑存放至Url類加載器并將此類加載器存放至Catalina中)
if (getCatalina() != null) {
ClassLoader cl = getCatalina().getParentClassLoader();
while (cl != null && cl != ClassLoader.getSystemClassLoader()) {
if (cl instanceof URLClassLoader) {
URL[] urls = ((URLClassLoader) cl).getURLs();
for (URL url : urls) {
if (url.getProtocol().equals("file")) {
try {
File f = new File (url.toURI());
if (f.isFile() &&
f.getName().endsWith(".jar")) {
ExtensionValidator.addSystemResource(f);
}
} catch (URISyntaxException e) {
// Ignore
} catch (IOException e) {
// Ignore
}
}
}
}
cl = cl.getParent();
}
}
// 初始化所有Service
for (int i = 0; i < services.length; i++) {
services[i].init();
}
}
protected void startInternal() throws LifecycleException {
//觸發(fā)監(jiān)聽器——啟動(dòng)事件
fireLifecycleEvent(CONFIGURE_START_EVENT, null);
//狀態(tài)切換——啟動(dòng)中
setState(LifecycleState.STARTING);
//全局命名資源集啟動(dòng)
globalNamingResources.start();
// 啟動(dòng)所有Service
synchronized (servicesLock) {
for (int i = 0; i < services.length; i++) {
services[i].start();
}
}
}
protected void stopInternal() throws LifecycleException {
//切換狀態(tài)——停止中;觸發(fā)監(jiān)聽器——停止事件
setState(LifecycleState.STOPPING);
fireLifecycleEvent(CONFIGURE_STOP_EVENT, null);
// 停止所有Service
for (int i = 0; i < services.length; i++) {
services[i].stop();
}
//停止全局命名資源集
globalNamingResources.stop();
//停止等待中的線程和socket連接
stopAwait();
}
protected void destroyInternal() throws LifecycleException {
// 摧毀所有Service
for (int i = 0; i < services.length; i++) {
services[i].destroy();
}
//摧毀命名資源集
globalNamingResources.destroy();
//取消注冊(cè)組件工廠和字符串緩存
unregister(onameMBeanFactory);
unregister(onameStringCache);
super.destroyInternal();
}
Service
Service是一個(gè)包含多個(gè)連接器Connector和一個(gè)主機(jī)容器Engine的容器固该,以便于:多個(gè)連接器統(tǒng)一為同一個(gè)主機(jī)容器提供請(qǐng)求-響應(yīng)連接锅减。
Service接口繼承自LifeCycle接口,額外提供Service的API伐坏。
類別 | 作用 | API |
---|---|---|
獲取/設(shè)置 | 所在服務(wù)器Server | get/setServer |
名字 | get/setServer | |
類加載器 | get/setParentClassLoader | |
主機(jī)容器Engine | get/setContainer | |
增/刪/查 | 連接器Connector | add/remove/findConnector |
連接器共享執(zhí)行器 | add/remove/findExecutor |
StandardService
Service的默認(rèn)實(shí)現(xiàn)類怔匣,繼承自LifeCycleMBean
//未聲明構(gòu)造函數(shù),默認(rèn)構(gòu)造函數(shù)
protected void initInternal() throws LifecycleException {
super.initInternal();
//先初始化主機(jī)容器
if (engine != null) {
engine.init();
}
// 再初始化所有共享執(zhí)行器
for (Executor executor : findExecutors()) {
if (executor instanceof JmxEnabled) {
((JmxEnabled) executor).setDomain(getDomain());
}
executor.init();
}
// 初始化監(jiān)聽器
mapperListener.init();
// 初始化定義好的連接器(同步)
synchronized (connectorsLock) {
for (Connector connector : connectors) {
try {
connector.init();
} catch (Exception e) {
String message = sm.getString(
"standardService.connector.initFailed", connector);
log.error(message, e);
if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE"))
throw new LifecycleException(message);
}
}
}
}
protected void startInternal() throws LifecycleException {
if(log.isInfoEnabled())
log.info(sm.getString("standardService.start.name", this.name));
setState(LifecycleState.STARTING);
// 同步啟動(dòng)Engine
if (engine != null) {
synchronized (engine) {
engine.start();
}
}
//同步啟動(dòng)執(zhí)行器
synchronized (executors) {
for (Executor executor: executors) {
executor.start();
}
}
//啟動(dòng)映射器監(jiān)聽器
mapperListener.start();
// 同步啟動(dòng)所有連接器
synchronized (connectorsLock) {
for (Connector connector: connectors) {
try {
// If it has already failed, don't try and start it
if (connector.getState() != LifecycleState.FAILED) {
connector.start();
}
} catch (Exception e) {
log.error(sm.getString(
"standardService.connector.startFailed",
connector), e);
}
}
}
}
protected void stopInternal() throws LifecycleException {
// 同步暫停所有連接器
synchronized (connectorsLock) {
for (Connector connector: connectors) {
try {
connector.pause();
} catch (Exception e) {
log.error(sm.getString(
"standardService.connector.pauseFailed",
connector), e);
}
// Close server socket if bound on start
// Note: test is in AbstractEndpoint
connector.getProtocolHandler().closeServerSocketGraceful();
}
}
//狀態(tài)切換
if(log.isInfoEnabled())
log.info(sm.getString("standardService.stop.name", this.name));
setState(LifecycleState.STOPPING);
// 停止Engine
if (engine != null) {
synchronized (engine) {
engine.stop();
}
}
// 同步停止所有連接器
synchronized (connectorsLock) {
for (Connector connector: connectors) {
if (!LifecycleState.STARTED.equals(
connector.getState())) {
// Connectors only need stopping if they are currently
// started. They may have failed to start or may have been
// stopped (e.g. via a JMX call)
continue;
}
try {
connector.stop();
} catch (Exception e) {
log.error(sm.getString(
"standardService.connector.stopFailed",
connector), e);
}
}
}
//停止映射器監(jiān)聽器
if (mapperListener.getState() != LifecycleState.INITIALIZED) {
mapperListener.stop();
}
//同步停止所有執(zhí)行器
synchronized (executors) {
for (Executor executor: executors) {
executor.stop();
}
}
}
protected void destroyInternal() throws LifecycleException {
//摧毀映射器監(jiān)聽器
mapperListener.destroy();
// 同步摧毀所有連接器
synchronized (connectorsLock) {
for (Connector connector : connectors) {
try {
connector.destroy();
} catch (Exception e) {
log.error(sm.getString(
"standardService.connector.destroyFailed", connector), e);
}
}
}
// 摧毀所有執(zhí)行器
for (Executor executor : findExecutors()) {
executor.destroy();
}
//摧毀Engine
if (engine != null) {
engine.destroy();
}
super.destroyInternal();
}
連接器Connector
Connector維護(hù)客戶端和服務(wù)器端的聯(lián)系桦沉,繼承自LifecycleMBeanBase每瞒,額外提供連接器API
類型 | 作用 | API |
---|---|---|
獲取/設(shè)置 | 所在Service | get/setService |
使用執(zhí)行器的名字 | get/setExecutorName | |
協(xié)議處理器的指定屬性 | get/setProperty | |
協(xié)議處理器的指定屬性(效果同上) | get/setAttribute | |
是否可追溯 | get/setAllowTrace | |
請(qǐng)求的同步時(shí)限 | get/setAsyncTimeout | |
是否允許DNS查找 | get/setEnableLookups | |
最大Cookie數(shù) | get/setMaxCookieCount | |
最大參數(shù)數(shù) | get/setMaxParameterCount | |
Post請(qǐng)求大小限制 | get/setMaxPostSize | |
端口號(hào) | get/setPort | |
協(xié)議 | get/setProtocol | |
協(xié)議執(zhí)行器的類名 | get/setProtocolHandlerClassName | |
代理服務(wù)器名 | get/setProxyName | |
代理端口 | get/setProxyPort | |
重定向端口 | get/setRedirectPort | |
增/刪/查 | SSL主機(jī)配置 | add/remove/findSslHostConfig |
更新協(xié)議 | add/remove/findUpgradeProtocol |
public Connector(String protocol) {
//設(shè)置協(xié)議
setProtocol(protocol);
//實(shí)例化協(xié)議執(zhí)行器
ProtocolHandler p = null;
try {
Class<?> clazz = Class.forName(protocolHandlerClassName);
p = (ProtocolHandler) clazz.getConstructor().newInstance();
} catch (Exception e) {
log.error(sm.getString(
"coyoteConnector.protocolHandlerInstantiationFailed"), e);
} finally {
this.protocolHandler = p;
}
//設(shè)置字符集
if (Globals.STRICT_SERVLET_COMPLIANCE) {
uriCharset = StandardCharsets.ISO_8859_1;
} else {
uriCharset = StandardCharsets.UTF_8;
}
}
protected void initInternal() throws LifecycleException {
super.initInternal();
// 初始化協(xié)議執(zhí)行器的連接適配器
adapter = new CoyoteAdapter(this);
protocolHandler.setAdapter(adapter);
// 確保請(qǐng)求體解析器有效
if (null == parseBodyMethodsSet) {
setParseBodyMethods(getParseBodyMethods());
}
//協(xié)議解析器需要APR/native庫——生命周期異常
if (protocolHandler.isAprRequired() && !AprLifecycleListener.isAprAvailable()) {
throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerNoApr",
getProtocolHandlerClassName()));
}
//基于JSSE(Java安全socket層)的HTTP協(xié)議執(zhí)行器需要設(shè)置SSL實(shí)現(xiàn)類的名稱
if (AprLifecycleListener.isAprAvailable() && AprLifecycleListener.getUseOpenSSL() &&
protocolHandler instanceof AbstractHttp11JsseProtocol) {
AbstractHttp11JsseProtocol<?> jsseProtocolHandler =
(AbstractHttp11JsseProtocol<?>) protocolHandler;
if (jsseProtocolHandler.isSSLEnabled() &&
jsseProtocolHandler.getSslImplementationName() == null) {
// OpenSSL is compatible with the JSSE configuration, so use it if APR is available
jsseProtocolHandler.setSslImplementationName(OpenSSLImplementation.class.getName());
}
}
try {
//初始化協(xié)議執(zhí)行器
protocolHandler.init();
} catch (Exception e) {
throw new LifecycleException(
sm.getString("coyoteConnector.protocolHandlerInitializationFailed"), e);
}
}
protected void startInternal() throws LifecycleException {
// 確認(rèn)端口號(hào)有效
if (getPort() < 0) {
throw new LifecycleException(sm.getString(
"coyoteConnector.invalidPort", Integer.valueOf(getPort())));
}
//切換狀態(tài)
setState(LifecycleState.STARTING);
try {
//啟動(dòng)協(xié)議執(zhí)行器
protocolHandler.start();
} catch (Exception e) {
throw new LifecycleException(
sm.getString("coyoteConnector.protocolHandlerStartFailed"), e);
}
}
protected void stopInternal() throws LifecycleException {
//切換狀態(tài)
setState(LifecycleState.STOPPING);
try {
//停止協(xié)議執(zhí)行器
protocolHandler.stop();
} catch (Exception e) {
throw new LifecycleException(
sm.getString("coyoteConnector.protocolHandlerStopFailed"), e);
}
}
protected void destroyInternal() throws LifecycleException {
try {
//銷毀協(xié)議執(zhí)行器
protocolHandler.destroy();
} catch (Exception e) {
throw new LifecycleException(
sm.getString("coyoteConnector.protocolHandlerDestroyFailed"), e);
}
//從所在Service中移除自己
if (getService() != null) {
getService().removeConnector(this);
}
super.destroyInternal();
}
協(xié)議執(zhí)行器ProtocolHandler
ProtocolHandler接口代表單線程的協(xié)議執(zhí)行器金闽,用于維護(hù)流式協(xié)議的連接
類型 | 作用 | API |
---|---|---|
生命周期 | 初始化 | init |
啟動(dòng) | start | |
暫停/恢復(fù) | pause/resume | |
停止 | stop | |
銷毀 | destory | |
查詢 | 是否需要APR/native庫 | isAprRequired |
協(xié)議是否支持發(fā)送文件 | isSendfileSupported | |
獲取/設(shè)置 | 發(fā)起連接的適配器 | get/setAdapter |
增/查 | SSL主機(jī)配置 | add/findSslHostConfig |
更新協(xié)議 | add/findUpgradeProtocol |
主機(jī)容器Engine
Engine是包含多個(gè)主機(jī)的容器,它封裝多個(gè)主機(jī)剿骨,以便:
- 統(tǒng)一攔截到達(dá)他們的請(qǐng)求代芜;
- 讓他們統(tǒng)一使用同一個(gè)連接器
Engine實(shí)現(xiàn)LifeCycle接口,額外提供Engine的API懦砂。
作用 | API |
---|---|
獲取/設(shè)置所在Service | get/setService |
獲取/設(shè)置默認(rèn)主機(jī) | get/setDefaultHost |
獲取/設(shè)置JVM路由ID | get/setJvmRoute |
StandardEngine
Engine的默認(rèn)實(shí)現(xiàn)類蜒犯,繼承自ContainerBase(間接繼承自LifecycleMBeanBase)
//創(chuàng)建擁有默認(rèn)屬性的Engine(Jvm路由:系統(tǒng)jvmRoute屬性;后臺(tái)進(jìn)程延遲:10)
public StandardEngine() {
super();
pipeline.setBasic(new StandardEngineValve());
try {
setJvmRoute(System.getProperty("jvmRoute"));
} catch(Exception ex) {
log.warn(sm.getString("standardEngine.jvmRouteFail"));
}
backgroundProcessorDelay = 10;
}
protected void initInternal() throws LifecycleException {
// 確保權(quán)限認(rèn)證Realm存在
getRealm();
super.initInternal();
}
public Realm getRealm() {
Realm configured = super.getRealm();
//權(quán)限認(rèn)證Realm不存在——返回空值對(duì)象
if (configured == null) {
configured = new NullRealm();
this.setRealm(configured);
}
return configured;
}
protected synchronized void startInternal() throws LifecycleException {
if(log.isInfoEnabled())
log.info( "Starting Servlet Engine: " + ServerInfo.getServerInfo());
super.startInternal();
}
//未實(shí)現(xiàn)stopInternal
//未實(shí)現(xiàn)destoryInternal