文章目錄
1.源碼引入
1.1.1.server.xml:截圖樣例(整體的組件配置文件)
1.1.2.附帶源文件:server.xml
<?xml version='1.0' encoding='utf-8'?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Note: A "Server" is not itself a "Container", so you may not
define subcomponents such as "Valves" at this level.
Documentation at /docs/config/server.html
-->
<Server port="8005" shutdown="SHUTDOWN">
<!-- Security listener. Documentation at /docs/config/listeners.html
<Listener className="org.apache.catalina.security.SecurityListener" />
-->
<!--APR library loader. Documentation at /docs/apr.html -->
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<!-- Prevent memory leaks due to use of particular java/javax APIs-->
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<!-- Global JNDI resources
Documentation at /docs/jndi-resources-howto.html
-->
<GlobalNamingResources>
<!-- Editable user database that can also be used by
UserDatabaseRealm to authenticate users
-->
<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>
<!-- A "Service" is a collection of one or more "Connectors" that share
a single "Container" Note: A "Service" is not itself a "Container",
so you may not define subcomponents such as "Valves" at this level.
Documentation at /docs/config/service.html
-->
<Service name="Catalina">
<!--The connectors can use a shared executor, you can define one or more named thread pools-->
<!--
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
maxThreads="150" minSpareThreads="4"/>
-->
<!-- A "Connector" represents an endpoint by which requests are received
and responses are returned. Documentation at :
Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)
Java AJP Connector: /docs/config/ajp.html
APR (HTTP/AJP) Connector: /docs/apr.html
Define a non-SSL HTTP/1.1 Connector on port 8080
-->
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<!-- A "Connector" using the shared thread pool-->
<!--
<Connector executor="tomcatThreadPool"
port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
-->
<!-- Define a SSL HTTP/1.1 Connector on port 8443
This connector uses the NIO implementation that requires the JSSE
style configuration. When using the APR/native implementation, the
OpenSSL style configuration is required as described in the APR/native
documentation -->
<!--
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS" />
-->
<!-- Define an AJP 1.3 Connector on port 8009 -->
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
<!-- An Engine represents the entry point (within Catalina) that processes
every request. The Engine implementation for Tomcat stand alone
analyzes the HTTP headers included with the request, and passes them
on to the appropriate Host (virtual host).
Documentation at /docs/config/engine.html -->
<!-- You should set jvmRoute to support load-balancing via AJP ie :
<Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
-->
<Engine name="Catalina" defaultHost="localhost">
<!--For clustering, please take a look at documentation at:
/docs/cluster-howto.html (simple how to)
/docs/config/cluster.html (reference documentation) -->
<!--
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>
-->
<!-- Use the LockOutRealm to prevent attempts to guess user passwords
via a brute-force attack -->
<Realm className="org.apache.catalina.realm.LockOutRealm">
<!-- This Realm uses the UserDatabase configured in the global JNDI
resources under the key "UserDatabase". Any edits
that are performed against this UserDatabase are immediately
available for use by the Realm. -->
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<!-- SingleSignOn valve, share authentication between web applications
Documentation at: /docs/config/valve.html -->
<!--
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
-->
<!-- Access log processes all example.
Documentation at: /docs/config/valve.html
Note: The pattern used is equivalent to using pattern="common" -->
<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>
1.1.3.層次結構圖
2.整體架構圖
2.1.通過上面的結構層級,得出下面的整體架構圖架構圖
2.2.整體架構圖流程說明
首先我們需要理解的問題是:
1.圖示中的每一個組件對應着源碼中那個類圖?
2.tomcat如何接收的?誰接收的?---->Connector
3.tomcat在處理的過程中如何進入到具體的servlet業務邏輯中進行處理?
3.Tomcat架構中各個組件的含義
https://tomcat.apache.org/tomcat-8.0-doc/architecture/overview.html
3.1.Server
3.1.1.類圖示
3.1.2.概念
1.In the Tomcat world, a Server represents the whole container. Tomcat provides a default implementation of the
Server interface which is rarely customized by users.
Server代表整個容器,Tomcat提供給了一個Server接口的默認實現,用戶很少去自定義;
2.Server 可以認爲是一個頂級的容器,啓動了Server容器,其他的組件也就可以使用;
3.2.Service
3.2.1.類圖示
3.2.2.概念
A Service is an intermediate component which lives inside a Server and ties one or more Connectors to exactly one Engine.
The Service element is rarely customized by users, as the default implementation is simple and sufficient: Service interface.
Service是一個運行在Server內部的一箇中間組件,Service將一個或者多個Connector緊密的連接到Engine組件上面;
Service組件用戶很少去自定義,默認的Service組件Service接口簡單高效的;
3.2.Engine
3.3.1.類圖示
3.3.2.概念
An Engine represents request processing pipeline for a specific Service.
Engine代表特定服務的請求處理管道。
As a Service may have multiple Connectors, the Engine receives and processes all requests from these connectors,
handing the response back to the appropriate connector for transmission to the client.
由於服務可能具有多個Connectors,因此Engine會接收並處理來自這些Connectors的所有請求,
將響應傳遞迴適當的Connectors以傳輸到客戶端。
The Engine interface may be implemented to supply custom Engines, though this is uncommon.
儘快Engine自定義接口不太常見,當時Engine接口可以自定義的Engine接口實現,
3.4.Host
3.4.1.類圖示
3.4.2.概念
A Host is an association of a network name, e.g. www.yourcompany.com, to the Tomcat server.
Host是一個關聯我們服務的網絡的名字,比如www.yourcompany.com
An Engine may contain multiple hosts, and the Host element also supports network aliases
such as yourcompany.com and abc.yourcompany.com.
一個Engine可能包含多個Hosts,並且每個host可以配置不同的網絡別名。比如as yourcompany.com 和 abc.yourcompany.com
Users rarely create custom Hosts because the StandardHost implementation provides significant additional functionality.
由於StandardHost接口實現非常的高效,用戶很少創建自定義的hosts;
像我們平時啓動了本地的tomcat服務之後,我們可以直接使用localhost這個host去訪問,我們也可以配置其他的
3.5.Connector
3.5.1.類圖示
3.5.2.概念
https://tomcat.apache.org/tomcat-8.0-doc/architecture/overview.html
1.A Connector handles communications with the client.
Connector負責與客戶端的交互;
There are multiple connectors available with Tomcat.
Tomcat中有多個是可以使用connectors;
These include the HTTP connector which is used for most HTTP traffic, especially when running Tomcat as
a standalone server, and the AJP connector which implements the AJP protocol used when connecting Tomcat to
a web server such as Apache HTTPD server. Creating a customized connector is a significant effort.
這些Connectors包含Http類型的connector(比如:獨立運行的tomcat服務)
另外,AJP類型的Connector實現了AJP協議,(比如:tomcat連接Apache Httpd Server類型的web服務)
創建定製的連接器是一項巨大的工作
3.5.2.源碼流程
源碼追溯,我們可以看到最終是ServerSocket進行監聽
3.5.4.EndPoint
1.AbstractEndPoint:對於傳輸層協議的抽象,裏面是寫Socket代碼的
2.JioEndPoint:同步阻塞IO,針對併發量比較大的時候,效率比較低,一個連接要一個線程
3.NIO:同步非阻塞IO,併發量比較大的時候,比較佔優勢,單獨一個線程,處理併發
4.Apr:與本地方法庫進行交互,
3.5.5.關於協議類型的設置
tomcat8 默認是NIO模式
3.6.Context
3.6.1.類視圖
3.6.2.概念
A Context represents a web application. A Host may contain multiple contexts, each with a unique path.
Context代表一個web應用。一個Host可能包含多個Context,每一個Context有一個唯一的path地址
The Context interface may be implemented to create custom Contexts, but this is rarely the case
because the StandardContext provides significant additional functionality.
Conext很少被自定義實現,因爲默認的StandardContext接口提供了高效的功能;
3.5.3.源碼流程
3.6.4.Context的配置類ContextConfig:代表加載web.xml中的Servlet類
3.6.4.1.ContextConfig.webConfig()方法介紹
/**
* Scan the web.xml files that apply to the web application and merge them
* using the rules defined in the spec. For the global web.xml files,
* where there is duplicate configuration, the most specific level wins. ie
* an application's web.xml takes precedence over the host level or global
* web.xml file.
* 掃描web.xml文件,將相關屬性賦予到web應用中使其生效
*/
protected void webConfig() {
/*
* Anything and everything can override the global and host defaults.
* This is implemented in two parts
* - Handle as a web fragment that gets added after everything else so
* everything else takes priority
* - Mark Servlets as overridable so SCI configuration can replace
* configuration from the defaults
*/
/*
* The rules for annotation scanning are not as clear-cut as one might
* think. Tomcat implements the following process:
* - As per SRV.1.6.2, Tomcat will scan for annotations regardless of
* which Servlet spec version is declared in web.xml. The EG has
* confirmed this is the expected behaviour.
* - As per http://java.net/jira/browse/SERVLET_SPEC-36, if the main
* web.xml is marked as metadata-complete, JARs are still processed
* for SCIs.
* - If metadata-complete=true and an absolute ordering is specified,
* JARs excluded from the ordering are also excluded from the SCI
* processing.
* - If an SCI has a @HandlesType annotation then all classes (except
* those in JARs excluded from an absolute ordering) need to be
* scanned to check if they match.
*/
Set<WebXml> defaults = new HashSet<>();
defaults.add(getDefaultWebXmlFragment());
WebXml webXml = createWebXml();
// Parse context level web.xml
InputSource contextWebXml = getContextWebXmlSource();
if (!webXmlParser.parseWebXml(contextWebXml, webXml, false)) {
ok = false;
}
ServletContext sContext = context.getServletContext();
// Ordering is important here
// Step 1. Identify all the JARs packaged with the application and those
// provided by the container. If any of the application JARs have a
// web-fragment.xml it will be parsed at this point. web-fragment.xml
// files are ignored for container provided JARs.
Map<String,WebXml> fragments = processJarsForWebFragments(webXml);
// Step 2. Order the fragments.
Set<WebXml> orderedFragments = null;
orderedFragments =
WebXml.orderWebFragments(webXml, fragments, sContext);
// Step 3. Look for ServletContainerInitializer implementations
if (ok) {
processServletContainerInitializers(sContext);
}
if (!webXml.isMetadataComplete() || typeInitializerMap.size() > 0) {
// Step 4. Process /WEB-INF/classes for annotations and
// @HandlesTypes matches
if (ok) {
WebResource[] webResources =
context.getResources().listResources("/WEB-INF/classes");
for (WebResource webResource : webResources) {
processAnnotationsWebResource(webResource, webXml,
webXml.isMetadataComplete());
}
}
// Step 5. Process JARs for annotations for annotations and
// @HandlesTypes matches - only need to process those fragments we
// are going to use (remember orderedFragments includes any
// container fragments)
if (ok) {
processAnnotations(
orderedFragments, webXml.isMetadataComplete());
}
// Cache, if used, is no longer required so clear it
javaClassCache.clear();
}
if (!webXml.isMetadataComplete()) {
// Step 6. Merge web-fragment.xml files into the main web.xml
// file.
if (ok) {
ok = webXml.merge(orderedFragments);
}
// Step 7. Apply global defaults
// Have to merge defaults before JSP conversion since defaults
// provide JSP servlet definition.
webXml.merge(defaults);
// Step 8. Convert explicitly mentioned jsps to servlets
if (ok) {
convertJsps(webXml);
}
// Step 9. Apply merged web.xml to Context
if (ok) {
configureContext(webXml);
}
} else {
webXml.merge(defaults);
convertJsps(webXml);
configureContext(webXml);
}
// Step 9a. Make the merged web.xml available to other
// components, specifically Jasper, to save those components
// from having to re-generate it.
// TODO Use a ServletContainerInitializer for Jasper
String mergedWebXml = webXml.toXml();
sContext.setAttribute(
org.apache.tomcat.util.scan.Constants.MERGED_WEB_XML,
mergedWebXml);
if (context.getLogEffectiveWebXml()) {
log.info("web.xml:\n" + mergedWebXml);
}
// Always need to look for static resources
// Step 10. Look for static resources packaged in JARs
if (ok) {
// Spec does not define an order.
// Use ordered JARs followed by remaining JARs
Set<WebXml> resourceJars = new LinkedHashSet<>();
if (orderedFragments != null) {
for (WebXml fragment : orderedFragments) {
resourceJars.add(fragment);
}
}
for (WebXml fragment : fragments.values()) {
if (!resourceJars.contains(fragment)) {
resourceJars.add(fragment);
}
}
processResourceJARs(resourceJars);
// See also StandardContext.resourcesStart() for
// WEB-INF/classes/META-INF/resources configuration
}
// Step 11. Apply the ServletContainerInitializer config to the
// context
if (ok) {
for (Map.Entry<ServletContainerInitializer,
Set<Class<?>>> entry :
initializerClassMap.entrySet()) {
if (entry.getValue().isEmpty()) {
context.addServletContainerInitializer(
entry.getKey(), null);
} else {
context.addServletContainerInitializer(
entry.getKey(), entry.getValue());
}
}
}
}
呼應了Wrapper=Servlet