0%

Tomcat

一、Servlet

1.1、规范

Servlet是JavaEE规范中的一种,主要是为了扩展Java作为Web服务的功能,统一定义了对应的接口,比如Servlet接口,HttpRequest接口,HttpResponse接口,Filter接口。然后由具体的服务厂商来实现这些接口功能,比如Tomcat,jetty等。

在Servlet规范中规定了一个http请求到来的执行处理流程:对应的服务器容器会接收到对应的Http请求,然后解析该请求,然后创建对应的Servlet实例,调用对应init方法来完成初始化,把请求的相关信息封装为HttpServletRequest对象来调用Servlet的service方法来处理请求,然后通过HttpServletResponse封装响应的信息交给容器,响应给客户端。

1.2、核心对象

API 描述
ServletConfig 获取servlet初始化参数和servletContext对象。
ServletContext 在整个Web应用的动态资源之间共享数据。
ServletRequest 封装Http请求信息,在请求时创建。
ServletResponse 封装Http响应信息,在请求时创建。

1.2.1、ServletConfig

  容器在初始化servlet时,为该servlet创建一个servletConfig对象,并将这个对象通过init()方法来传递并保存在此Servlet对象中。核心作用:

  1. 获取初始化信息;
  2. 获取ServletContext对象。

1.2.2、ServletContext

  一个项目只有一个ServletContext对象,可以在多个Servlet中来获取这个对象,使用它可以给多个Servlet传递数据,该对象在Tomcat启动时就创建,在Tomcat关闭时才会销毁!作用是在整个Web应用的动态资源之间共享数据。

  在实际的Servlet开发中,我们会实现HttpServlet接口,在该接口中会实现GenericServlet,而在GenericServlet会实现ServiceConfig接口,从而可以获取ServletContext容器对象

1.2.3、ServletRequest

  HttpServletRequest接口继承ServletRequest接口,用于封装请求信息,该对象在用户每次请求servlet时创建并传入servlet的service()方法,在该方法中,传入的servletRequest将会被强制转化为HttpServletRequest 对象来进行HTTP请求信息的处理。

核心作用:

  1. 获取请求报文信息;
  2. 获取网络连接信息;
  3. 获取请求域属性信息。

1.2.4、ServletResponse

  HttpServletResponse继承自ServletResponse,封装了Http响应信息。客户端每个请求,服务器都会创建一个response对象,并传入给Servlet.service()方法。

核心作用:

  1. 设置响应头信息;
  2. 发送状态码;
  3. 设置响应正文;
  4. 重定向;

二、Tomcat

2.1、介绍

  通过上面Servlet规范的介绍,可以发现如果要实现Servlet规范的话,很重要的就得提供一个服务容器来获取请求,解析封装数据,并调用Servlet实例相关的方法。

如图

Tomcat是一个Servlet规范的实现,要接收请求和响应请求。

2.2、组件

server.xml

conf/server.xml是Tomcat中最重要的配置文件,server.xml 的每一个元素都对应了Tomcat 中的一个组件;通过对xml文件中元素的配置,可以实现对Tomcat中各个组件的控制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<?xml version="1.0" encoding="UTF-8"?>

<Server port="8005" shutdown="SHUTDOWN">
<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" />
<GlobalNamingResources>
<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 name="Catalina">

<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<!--
<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true">
<SSLHostConfig>
<Certificate certificateKeystoreFile="conf/localhost-rsa.jks"
type="RSA" />
</SSLHostConfig>
</Connector>
-->

<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>

<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t &quot;%r&quot; %s %b" />
</Host>
</Engine>
</Service>
</Server>
1
2
3
4
5
6
7
8
9
10
11
<Server>
<Service>
<Connector/>
<Connector/>
<Engine>
<Host>
<Context/>
</Host>
</Engine>
</Service>
</Server>

介绍

顶级元素:

  • Server:是整个配置文件的根元素
  • Service:代表一个Engine元素以及一组与之相连的Connector元素

连接器:代表了外部客户端发送请求到特定Service的接口;同时也是外部客户端从特定Service接收响应的接口。

容器:容器的作用是处理Connector接收进来的请求,并产生对应的响应,Engine,Host和Context都是容器,他们不是平行关系,而是父子关系。

  • Engine:可以处理所有请求
  • Host:可以处理发向一个特定虚拟主机的所有请求
  • Context:可以处理一个特定Web应用的所有请求

其他组件:

  • Executor:线程池
  • Manger:管理器【Session管理】
  • Valve:拦截器
  • Listener:监听器
  • Realm:数据库权限

2.3、流程

当客户端请求发送过来后其实是通过这些组件相互之间配合完成了对应的操作。

  • Server元素在最顶层,代表整个Tomcat容器;一个Server元素中可以有一个或多个Service元素
  • Service在Connector和Engine外面包了一层,把它们组装在一起,对外提供服务。一个Service可以包含多个Connector,但是只能包含一个Engine;Connector接收请求,Engine处理请求。
  • Engine、Host和Context都是容器,且Engine包含Host,Host包含Context。每个Host组件代表Engine中的一个虚拟主机;每个Context组件代表在特定Host上运行的一个Web应用.

2.4、生命周期

为了统一管理Tomcat中的核心组件的生命周期,init,start,stop,destory方法,而专门设计了LifeCycle接口来统一管理。

Lifecycle

Lifecycle中声明了相关的状态和事件的生命周期字符串,在LifecycleState中建立了对应关系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
public interface Lifecycle {
public static final String BEFORE_START_EVENT = "before_start";
public static final String AFTER_START_EVENT = "after_start";
public static final String STOP_EVENT = "stop";
public static final String BEFORE_STOP_EVENT = "before_stop";
public static final String AFTER_STOP_EVENT = "after_stop";
public static final String AFTER_DESTROY_EVENT = "after_destroy";
public static final String BEFORE_DESTROY_EVENT = "before_destroy";
public static final String PERIODIC_EVENT = "periodic";
public static final String CONFIGURE_START_EVENT = "configure_start";
public static final String CONFIGURE_STOP_EVENT = "configure_stop";

public void addLifecycleListener(LifecycleListener listener);
public LifecycleListener[] findLifecycleListeners();
public void removeLifecycleListener(LifecycleListener listener);
}

public enum LifecycleState {
NEW(false, null),
INITIALIZING(false, Lifecycle.BEFORE_INIT_EVENT),
INITIALIZED(false, Lifecycle.AFTER_INIT_EVENT),
STARTING_PREP(false, Lifecycle.BEFORE_START_EVENT),
STARTING(true, Lifecycle.START_EVENT),
STARTED(true, Lifecycle.AFTER_START_EVENT),
STOPPING_PREP(true, Lifecycle.BEFORE_STOP_EVENT),
STOPPING(false, Lifecycle.STOP_EVENT),
STOPPED(false, Lifecycle.AFTER_STOP_EVENT),
DESTROYING(false, Lifecycle.BEFORE_DESTROY_EVENT),
DESTROYED(false, Lifecycle.AFTER_DESTROY_EVENT),
FAILED(false, null);

private final boolean available; // 组件是否可用
private final String lifecycleEvent; // 事件字符串

private LifecycleState(boolean available, String lifecycleEvent) {
this.available = available;
this.lifecycleEvent = lifecycleEvent;
}

public boolean isAvailable() {
return available;
}

public String getLifecycleEvent() {
return lifecycleEvent;
}
}

public interface LifecycleListener {
public void lifecycleEvent(LifecycleEvent event);
}

public final class LifecycleEvent extends EventObject {
public LifecycleEvent(Lifecycle lifecycle, String type, Object data) {
super(lifecycle); // 将lifecycle保存在父类数据字段
this.type = type; //传递给监听器的数据
this.data = data; //事件类型
}

private final Object data;

private final String type;

public Lifecycle getLifecycle() {
return (Lifecycle) getSource();
}

public String getType() {
return this.type;
}
}

LifecycleBase

Tomcat中设计了Lifecycle和LifecycleListener和LifecycleEvent来管理核心组件的生命周期;同时提供了一个LifecycleBase的抽象类,帮助我们实现了很多和具体业务无关的处理,来简化了具体组件的业务。

LifecycleBase实现了Lifecycle中的生命周期相关逻辑,主要关注模板方法initstartstopdestory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
public abstract class LifecycleBase implements Lifecycle {
private final List<LifecycleListener> lifecycleListeners = new CopyOnWriteArrayList<>();

private volatile LifecycleState state = LifecycleState.NEW;

@Override
public void addLifecycleListener(LifecycleListener listener) {
lifecycleListeners.add(listener);
}

@Override
public LifecycleListener[] findLifecycleListeners() {
return lifecycleListeners.toArray(new LifecycleListener[0]);
}

@Override
public void removeLifecycleListener(LifecycleListener listener) {
lifecycleListeners.remove(listener);
}

/**
* 发送LifecycleEvent
*/
protected void fireLifecycleEvent(String type, Object data) {
LifecycleEvent event = new LifecycleEvent(this, type, data);
for (LifecycleListener listener : lifecycleListeners) {
// 遍历获取所有的监听器-->触发
listener.lifecycleEvent(event);
}
}

/**
* 实现了 Lifecycle 中定义的init方法
* 该方法和对应的组件的状态产生的关联
* 1.具体的组件初始化操作 Server Service Connector Engine Host Context
* 2.状态变化
* 3.事件发布
*/
@Override
public final synchronized void init() throws LifecycleException {
if (!state.equals(LifecycleState.NEW)) {
// 无效的操作,只有状态为 New 的才能调用init方法进入初始化
invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
}

try {
// 设置状态为初始化进行中....同步在方法中会触发对应的事件
setStateInternal(LifecycleState.INITIALIZING, null, false);
initInternal(); // 交给子类具体的实现 初始化操作
// 更新状态为初始化完成 同步在方法中会触发对应的事件
setStateInternal(LifecycleState.INITIALIZED, null, false);
} catch (Throwable t) {
handleSubClassException(t, "lifecycleBase.initFail", toString());
}
}

@Override
public final synchronized void start() throws LifecycleException {

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;
}

if (state.equals(LifecycleState.NEW)) {
init();
} else if (state.equals(LifecycleState.FAILED)) {
stop();
} else if (!state.equals(LifecycleState.INITIALIZED) &&
!state.equals(LifecycleState.STOPPED)) {
invalidTransition(Lifecycle.BEFORE_START_EVENT);
}

try {
// 设置状态为启动之前
setStateInternal(LifecycleState.STARTING_PREP, null, false);
// 交给子类来具体的实现
startInternal();
// 子类处理完成后
if (state.equals(LifecycleState.FAILED)) {
// This is a 'controlled' failure. The component put itself into the
// FAILED state so call stop() to complete the clean-up.
stop();
} else if (!state.equals(LifecycleState.STARTING)) {
// Shouldn't be necessary but acts as a check that sub-classes are
// doing what they are supposed to.
invalidTransition(Lifecycle.AFTER_START_EVENT);
} else {
setStateInternal(LifecycleState.STARTED, null, false);
}
} catch (Throwable t) {
// This is an 'uncontrolled' failure so put the component into the
// FAILED state and throw an exception.
handleSubClassException(t, "lifecycleBase.startFail", toString());
}
}
}

2.5、启动入口

本次源码分析以Tomcat8.5为例

Bootstrap初始化,调用Catalina加载解析server.xml,初始、启动组件

组件根据父类LifecycleBaseinit,start,stop,destory等模板方法嵌套调用子组件

2.5.1、脚本

启动脚本startup.bat

1
2
3
set "EXECUTABLE=%CATALINA_HOME%\bin\catalina.bat"
...
call "%EXECUTABLE%" start %CMD_LINE_ARGS%

发现执行了catalina.bat脚本,进入catalina.bat

1
2
3
set MAINCLASS=org.apache.catalina.startup.Bootstrap
...
%MAINCLASS% %CMD_LINE_ARGS% %ACTION%

可以看到调用了org.apache.catalina.startup.Bootstrap,由此可知Tomcat的入口为Bootstrap中的main方法

2.5.2、Bootstrap

main方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static void main(String args[]) {
synchronized (daemonLock) {
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);
}
}
//...
}

init方法

初始化类加载器,反射创建Catalina

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public void init() throws Exception {
// 1、初始化创建相关的类加载器
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");
}
// 2、通过反射创建了 Catalina 类对象
Class<?> startupClass = catalinaLoader
.loadClass("org.apache.catalina.startup.Catalina");
// 创建了 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;
// 把 sharedLoader 设置为了 commonLoader的父加载器
Method method =
startupInstance.getClass().getMethod(methodName, paramTypes);
method.invoke(startupInstance, paramValues);
// Catalina 实例 赋值给了 catalinaDaemon
catalinaDaemon = startupInstance;

//...

}

main方法

start命名触发调用Catalina的load方法和start方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static void main(String args[]) {
//...
try {
String command = "start";
if (args.length > 0) {
command = args[args.length - 1];
}

if (command.equals("startd")) {
args[args.length - 1] = "start";
//该方法内部通过反射调用org.apache.catalina.startup.Catalina的load方法
daemon.load(args);
//该方法内部通过反射调用org.apache.catalina.startup.Catalina的start方法
daemon.start();
}

//...
}

2.5.3、Catalina

解析Server.xml,加载组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void load() {
//创建Digester对象,解析Server.xml
Digester digester = createStartDigester();
file = configFile();// conf/server.xml
inputStream = new FileInputStream(file);
inputSource.setByteStream(inputStream);
digester.push(this);
digester.parse(inputSource);//解析server.xml

//...

getServer().init(); // 完成 Server Service Engine Connector Context等组件的init操作

//...
}

组件初始化时调用其父类LifecycleBase的init模板方法

1
2
3
4
5
6
// 设置状态为初始化进行中....同步在方法中会触发对应的事件
setStateInternal(LifecycleState.INITIALIZING, null, false);
//交给子类具体的实现 初始化操作
initInternal();
// 更新状态为初始化完成 同步在方法中会触发对应的事件
setStateInternal(LifecycleState.INITIALIZED, null, false);

启动组件

完成Server组件的start方法,同时嵌套完成其他核心子组件的启动

1
2
3
4
5
6
7
8
9
10
11
public void start() {
if (getServer() == null) {
load(); // 如果Server 为空 重新 init 相关的组件
}

//...
//启动Server
getServer().start();

//...
}

组件初始化时调用其父类LifecycleBase的start模板方法

1
2
3
4
5
6
7
8
9
10
11
12
// 设置状态为启动之前
setStateInternal(LifecycleState.STARTING_PREP, null, false);
// 交给子类来具体的实现
startInternal();
// 子类处理完成后
if (state.equals(LifecycleState.FAILED)) {
stop();
} else if (!state.equals(LifecycleState.STARTING)) {
invalidTransition(Lifecycle.AFTER_START_EVENT);
} else {
setStateInternal(LifecycleState.STARTED, null, false);
}

2.6、Pipeline-Valve管道设计

Container用于封装和管理Servlet,以及具体处理Request请求,在Connector内部包含了4个子容器

  • Engine:Tomcat连接器(Connector) 将接收到的连接提交给Engine处理,作为整个Servlet引擎的组件概念,用来管理多个虚拟站点,Engine和Host也是一对n的关系
  • Host:表示虚拟主机的概念,因为一台服务器不仅能够对product.baidu.com提供服务,同时也可以对test.baidu.com提供服务,同时每个虚拟主机都可以运行多个Java Web程序,所以Host和Context的关系也是1对n
  • Context:表示我们的应用程序,比如一个运行中Java Web程序,一个程序里面自然有多个Servlet,所以Conxtet和Wrapper的关系是1对n
  • Wrapper:对Servlet定义的组件概念,一个Wrapper代表一个Servlet

Container使用Pipeline-Valve管道来处理请求。

Pipeline-Valve是责任链模式,责任链模式是指在一个请求处理的过程中有很多处理者依次对请求进行处理,每个处理者负责做自己相应的处理,处理完之后将处理后的请求返回,再让下一个处理着继续处理。

每个组件的父类都持有一个自己的StandardPipeline成员属性

protected final Pipeline pipeline = new StandardPipeline(this);

在组件通过构造方法创建时,会设置Value实现到Pipeline中,多个实现构成一条调用链

pipeline.setBasic(new StandardEngineValve());

使用时,获取对应组件的Pipeline,获取链路上的Value实现的invoke方法

host.getPipeline().getFirst().invoke(request, response);

后面的2.8访问流程会使用到该概念,这里暂做了解

2.7、上下文启动初始化

StandardContext组件启动方法中:

  • 调用fireLifecycleEvent方法,发送配置启动事件,ContextConfig监听器匹配事件,解析web.xml,加载自定义的servelt、Listener、filter等信息
  • 调用listenerStart方法,初始化上下文监听器(SpringMVC的ContextLoaderListener在此处触发,创建Spring IOC容器)

发送事件

StandardContext发送CONFIGURE_START_EVENT事件

1
2
3
4
5
6
7
8
9
10
public class StandardContext extends ContainerBase implements Context, NotificationEmitter {

@Override
protected synchronized void startInternal() throws LifecycleException {
//...
//向监听器发送配置开启事件,如 监听器ContextConfig,涉及web.xml配置解析
fireLifecycleEvent(Lifecycle.CONFIGURE_START_EVENT, null);
//...
}
}

调用父类LifecycleBase的fireLifecycleEvent方法

1
2
3
4
5
6
7
8
9
10
public abstract class LifecycleBase implements Lifecycle {

protected void fireLifecycleEvent(String type, Object data) {
LifecycleEvent event = new LifecycleEvent(this, type, data);
for (LifecycleListener listener : lifecycleListeners) {
// 遍历获取所有的监听器-->触发
listener.lifecycleEvent(event);
}
}
}

ContextConfig解析web.xml

ContextConfig监听Lifecycle.CONFIGURE_START_EVENT,处理启动配置解析工作,如解析web.xml配置等操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
public class ContextConfig implements LifecycleListener {
/**
* Process events for an associated Context.
*
* @param event The lifecycle event that has occurred
*/
@Override
public void lifecycleEvent(LifecycleEvent event) {

// Identify the context we are associated with
try {
//从1、事件从取出当前组件,进行强转
context = (Context) event.getLifecycle();
} catch (ClassCastException e) {
log.error(sm.getString("contextConfig.cce", event.getLifecycle()), e);
return;
}

// Process the event that has occurred
//StandardContext的startInternal方法中触发CONFIGURE_START_EVENT事件
if (event.getType().equals(Lifecycle.CONFIGURE_START_EVENT)) {
configureStart();//2、启动配置处理,解析处理web.xml配置等
} else if (event.getType().equals(Lifecycle.BEFORE_START_EVENT)) {
beforeStart();
} else if (event.getType().equals(Lifecycle.AFTER_START_EVENT)) {
// Restore docBase for management tools
if (originalDocBase != null) {
context.setDocBase(originalDocBase);
}
} else if (event.getType().equals(Lifecycle.CONFIGURE_STOP_EVENT)) {
configureStop();
} else if (event.getType().equals(Lifecycle.AFTER_INIT_EVENT)) {
init();
} else if (event.getType().equals(Lifecycle.AFTER_DESTROY_EVENT)) {
destroy();
}
}

protected synchronized void configureStart() {
//略
//3、解析处理web.xml配置
webConfig();
//略
}

//扫描适用于web应用程序的web.xml文件,并使用规范中定义的规则合并它们。
//对于全局web.xml文件,其中有重复的配置,最特定的级别优先。
//Ie应用程序的web.xml优先于主机级或全局web.xml文件。
protected void webConfig() {

/*
* 注释扫描的规则并不像人们想象的那么明确。 Tomcat实现了以下过程:
* - 根据SRV.1.6.2, Tomcat会扫描注释而不管在web.xml中声明的Servlet规范版本。专家组已经证实,这是预期的行为。
* - 根据http://java.net/jira/browse/SERVLET_SPEC-36,如果主web.xml被标记为元数据完整,则仍然会为sci处理jar。
* - 如果metadata-complete=true并且指定了绝对排序,那么从排序中排除的jar也将从SCI处理中排除。
* - 如果SCI有@HandlesType注释,那么需要扫描所有的类(除了那些在jar中被排除在绝对排序之外的类),以检查它们是否匹配。
*/
WebXmlParser webXmlParser = new WebXmlParser(context.getXmlNamespaceAware(),
context.getXmlValidation(), context.getXmlBlockExternal());

Set<WebXml> defaults = new HashSet<>();
defaults.add(getDefaultWebXmlFragment(webXmlParser));

WebXml webXml = createWebXml();

//解析上下文级别的web.xml
InputSource contextWebXml = getContextWebXmlSource();
if (!webXmlParser.parseWebXml(contextWebXml, webXml, false)) {
ok = false;
}

ServletContext sContext = context.getServletContext();

// Ordering is important here

// Step 1.
// 标识与应用程序打包的所有jar和容器提供的jar。
// 如果任何应用程序jar有一个web-fragment.xml,它将在此时被解析。
// 容器提供的jar忽略web-fragment.xml文件
Map<String,WebXml> fragments = processJarsForWebFragments(webXml, webXmlParser);

// Step 2.对fragments排序
Set<WebXml> orderedFragments = null;
orderedFragments =
WebXml.orderWebFragments(webXml, fragments, sContext);

// Step 3. 寻找ServletContainerInitializer实现
if (ok) {
processServletContainerInitializers();
}

if (!webXml.isMetadataComplete() || typeInitializerMap.size() > 0) {
// Steps 4 & 5.
processClasses(webXml, orderedFragments);
}

if (!webXml.isMetadataComplete()) {
// Step 6. 合并web-fragment.xml文件到main web.xml文件
if (ok) {
ok = webXml.merge(orderedFragments);
}

// Step 7. Apply global defaults
// 必须在JSP转换之前合并默认值,因为默认值提供JSP servlet定义
webXml.merge(defaults);

// Step 8. 将显式地提到的jsp转换为servlet
if (ok) {
convertJsps(webXml);
}

// Step 9. 将合并后的web.xml应用到Context
if (ok) {
configureContext(webXml);
}
} else {
webXml.merge(defaults);
convertJsps(webXml);
configureContext(webXml);
}

if (context.getLogEffectiveWebXml()) {
log.info("web.xml:\n" + webXml.toXml());
}

// Always need to look for static resources
// Step 10. 寻找打包在jar中的静态资源
if (ok) {
// Spec does not define an order.
// Use ordered JARs followed by remaining JARs
Set<WebXml> resourceJars = new LinkedHashSet<>(orderedFragments);
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. 将ServletContainerInitializer配置应用于上下文
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());
}
}
}
}
}

StandardContext触发上下文初始化

调用ContextLoaderListener的contextInitialized方法进行初始化,创建Spring IOC容器(SpringMVC一侧的操作)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
public class StandardContext extends ContainerBase implements Context, NotificationEmitter {

@Override
protected synchronized void startInternal() throws LifecycleException {
//...

//1、调用父类LifecycleBase的fireLifecycleEvent方法
//向监听器发送配置开启事件,如 监听器ContextConfig,涉及web.xml配置解析
fireLifecycleEvent(Lifecycle.CONFIGURE_START_EVENT, null);
//...

// Configure and call application event listeners
if (ok) {
//2、为应用上下文配置实例化事件监听器
if (!listenerStart()) {
log.error(sm.getString("standardContext.listenerFail"));
ok = false;
}
}
}

public boolean listenerStart() {
//...
//获取应用监听器类名称数组(顺序按照web.xml中解析顺序)
String listeners[] = findApplicationListeners();
//...
//创建Servlet上下文事件
ServletContextEvent event = new ServletContextEvent(getServletContext());
ServletContextEvent tldEvent = null;
if (noPluggabilityListeners.size() > 0) {
noPluggabilityServletContext = new NoPluggabilityServletContext(getServletContext());
tldEvent = new ServletContextEvent(noPluggabilityServletContext);
}
for (Object instance : instances) {
if (!(instance instanceof ServletContextListener)) {
continue;
}
ServletContextListener listener = (ServletContextListener) instance;
try {
fireContainerEvent("beforeContextInitialized", listener);
//调用监听器上下文初始化方法,SpringMVC配置的上下文监听器ContextLoaderListener在此处触发上下文初始化
if (noPluggabilityListeners.contains(listener)) {
listener.contextInitialized(tldEvent);
} else {
listener.contextInitialized(event);
}
fireContainerEvent("afterContextInitialized", listener);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
fireContainerEvent("afterContextInitialized", listener);
getLogger().error(sm.getString("standardContext.listenerStart",
instance.getClass().getName()), t);
ok = false;
}
}
return ok;
}
}

Servlet封装

ContextConfig解析web.xml,加载自定义的servelt、Listener、filter等信息,其中包括将Servlet封装为StandardWrapper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//Step 9. 将合并后的web.xml应用到Context
public class ContextConfig implements LifecycleListener {
private void configureContext(WebXml webxml) {
//...
for (ServletDef servlet : webxml.getServlets().values()) {
Wrapper wrapper = context.createWrapper();
if (servlet.getLoadOnStartup() != null) {
wrapper.setLoadOnStartup(servlet.getLoadOnStartup().intValue());
}
wrapper.setName(servlet.getServletName());
wrapper.setServletClass(servlet.getServletClass());
//...
context.addChild(wrapper);
}
}
}

加载Servlet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class StandardContext extends ContainerBase implements Context, NotificationEmitter {

@Override
protected synchronized void startInternal() throws LifecycleException {

//1、调用父类LifecycleBase的fireLifecycleEvent方法
//向监听器发送配置开启事件,如 监听器ContextConfig,涉及web.xml配置解析
fireLifecycleEvent(Lifecycle.CONFIGURE_START_EVENT, null);
//...

// Configure and call application event listeners
if (ok) {
//2、为应用上下文配置实例化事件监听器
if (!listenerStart()) {
log.error(sm.getString("standardContext.listenerFail"));
ok = false;
}
}

// Load and initialize all "load on startup" servlets
// 3、Tomcat默认是懒加载,我们一般定义DispatcherServlet时指定<load-on-startup>1</load-on-startup>,使得Tomcat在此处会加载
if (ok) {
if (!loadOnStartup(findChildren())){
log.error(sm.getString("standardContext.servletFail"));
ok = false;
}
}
}
//加载并初始化web应用程序部署描述符中标记为“加载启动”的所有servlet。
public boolean loadOnStartup(Container children[]) {
//...
//加载并初始化Servlet
wrapper.load();
//...
}
}

初始化Servlet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class StandardWrapper extends ContainerBase implements ServletConfig, Wrapper, NotificationEmitter {

@Override
public synchronized void load() throws ServletException {
//实例化Servlet
instance = loadServlet();

//初始化Servlet
if (!instanceInitialized) {
initServlet(instance);
}
//...
}

private synchronized void initServlet(Servlet servlet)
throws ServletException {
servlet.init(facade);
}
}

public abstract class GenericServlet implements Servlet, ServletConfig,java.io.Serializable {

@Override
public void init(ServletConfig config) throws ServletException {
this.config = config;
this.init();
}

//调用子类实现(SpringMVC子类实现)
public void init() throws ServletException {
// NOOP by default
}

}

2.8、访问

创建Connector

Connector连接器接收外界请求,然后转换为对应的ServletRequest对象。

构造方法根据指定协议匹配合适的协议处理器并实例化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
protected String protocolHandlerClassName = "org.apache.coyote.http11.Http11NioProtocol";
protected final ProtocolHandler protocolHandler;

public Connector() {
this(null);
}

public Connector(String protocol) {
//根据server.xml配置的协议,匹配合适的协议处理器
setProtocol(protocol);
// 实例化协议处理器
ProtocolHandler p = null;
try {
//默认情况下创建Http11NioProtocol对象,同时构造中创建NioEndpoint
Class<?> clazz = Class.forName(protocolHandlerClassName);
p = (ProtocolHandler) clazz.getConstructor().newInstance();
} catch (Exception e) {
log.error(sm.getString(
"coyoteConnector.protocolHandlerInstantiationFailed"), e);
} finally {
//协议处理器复制到Connector的成员变量
this.protocolHandler = p;
}

if (Globals.STRICT_SERVLET_COMPLIANCE) {
uriCharset = StandardCharsets.ISO_8859_1;
} else {
uriCharset = StandardCharsets.UTF_8;
}

// Default for Connector depends on this (deprecated) system property
if (Boolean.parseBoolean(System.getProperty("org.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH", "false"))) {
encodedSolidusHandling = EncodedSolidusHandling.DECODE;
}
}

//设置连接器将使用的Coyote协议,Tomcat9开始删除该方法,从构造注入,修改protocolHandlerClassName值
@Deprecated
public void setProtocol(String protocol) {

boolean aprConnector = AprLifecycleListener.isAprAvailable() &&
AprLifecycleListener.getUseAprConnector();

if ("HTTP/1.1".equals(protocol) || protocol == null) {
if (aprConnector) {
setProtocolHandlerClassName("org.apache.coyote.http11.Http11AprProtocol");
} else {
setProtocolHandlerClassName("org.apache.coyote.http11.Http11NioProtocol");
}
} else if ("AJP/1.3".equals(protocol)) {
if (aprConnector) {
setProtocolHandlerClassName("org.apache.coyote.ajp.AjpAprProtocol");
} else {
setProtocolHandlerClassName("org.apache.coyote.ajp.AjpNioProtocol");
}
} else {
setProtocolHandlerClassName(protocol);
}
}

初始化Connector

创建适配器(将Tomcat请求响应对象适配为Servlet请求响应对象),初始化协议处理器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//协议处理器,在Connector构造中创建,默认实现为Http11NioProtocol
protected final ProtocolHandler protocolHandler;

@Override
protected void initInternal() throws LifecycleException {

super.initInternal();
//实例化适配器
adapter = new CoyoteAdapter(this);
//为Http11NioProtocol是指适配器属性,用于Tomcat请求响应对象与Servlet请求响应对象之间的转换,具体看后面分析
protocolHandler.setAdapter(adapter);

//...

try {
//初始化协议处理器
protocolHandler.init();
} catch (Exception e) {
throw new LifecycleException(
sm.getString("coyoteConnector.protocolHandlerInitializationFailed"), e);
}
}

创建服务端socket通道监听

初始化Endpoint

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public abstract class AbstractProtocol<S> implements ProtocolHandler,MBeanRegistration {

@Override
public void init() throws Exception {
//...

String endpointName = getName();
endpoint.setName(endpointName.substring(1, endpointName.length()-1));
endpoint.setDomain(domain);
//NioEndpoint在Http11NioProtocol构造中创建
//初始化
endpoint.init();
}
}

Endpoint是对于传输层协议的抽象

Tomcat8.5已经移除JioEndpoint实现

Endpoint实现 说明
AprEndpoint 对应的是APR(Apache portable Run-time libraries)模式,简单理解就是从操作系统级别解决异步IO的问题,大幅度提高服务器的处理和响应性能。与本地方法库交互
JioEndpoint Java普通IO方式实现,基于ServerSocket实现,同步阻塞的IO,并发量大的情况下效率低
Nio2Endpoint 利用代码来实现异步IO
NioEndpoint 利用了JAVA的NIO实现了非阻塞IO,Tomcat默认启动是以这个来启动的,在Http11NioProtocol的午餐构造中创建

基于NIO创建服务端端口监听

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public abstract class AbstractEndpoint<S> {

public void init() throws Exception {
if (bindOnInit) {
//初始化端点
bind();
bindState = BindState.BOUND_ON_INIT;
}
//...
}
}

public class NioEndpoint extends AbstractJsseEndpoint<NioChannel> {
@Override
public void bind() throws Exception {

if (!getUseInheritedChannel()) {
//创建服务端socket通道
serverSock = ServerSocketChannel.open();
socketProperties.setProperties(serverSock.socket());
InetSocketAddress addr = (getAddress()!=null?new InetSocketAddress(getAddress(),getPort()):new InetSocketAddress(getPort()));
//绑定端口地址
serverSock.socket().bind(addr,getAcceptCount());//getAcceptCount()指定接收的socket数量,默认100
} else {
//...
}
serverSock.configureBlocking(true); //mimic APR behavior
//...
// Initialize SSL if needed
initialiseSsl();

selectorPool.open();
}
}

启动Connector

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Override
protected void startInternal() throws LifecycleException {

// Validate settings before starting
if (getPort() < 0) {
throw new LifecycleException(sm.getString(
"coyoteConnector.invalidPort", Integer.valueOf(getPort())));
}

setState(LifecycleState.STARTING);

try {
//启动协议处理器
protocolHandler.start();
} catch (Exception e) {
throw new LifecycleException(
sm.getString("coyoteConnector.protocolHandlerStartFailed"), e);
}
}

启动endpoint

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public abstract class AbstractProtocol<S> implements ProtocolHandler,MBeanRegistration {

@Override
public void start() throws Exception {
if (getLog().isInfoEnabled()) {
getLog().info(sm.getString("abstractProtocolHandler.start", getName()));
}

//端点启动
endpoint.start();

// Start timeout thread
asyncTimeout = new AsyncTimeout();
Thread timeoutThread = new Thread(asyncTimeout, getNameInternal() + "-AsyncTimeout");
int priority = endpoint.getThreadPriority();
if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) {
priority = Thread.NORM_PRIORITY;
}
timeoutThread.setPriority(priority);
timeoutThread.setDaemon(true);
timeoutThread.start();
}

public final void start() throws Exception {
if (bindState == BindState.UNBOUND) {
bind();
bindState = BindState.BOUND_ON_START;
}
//启动NioEndpoint,接收请求
startInternal();
}
}

创建Acceptor接收器、Poller轮询器,启动异步线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
public class NioEndpoint extends AbstractJsseEndpoint<NioChannel> {
@Override
public void startInternal() throws Exception {

if (!running) {
running = true;
paused = false;

processorCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getProcessorCache());
eventCache = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getEventCache());
nioChannels = new SynchronizedStack<>(SynchronizedStack.DEFAULT_SIZE,
socketProperties.getBufferPool());

// Create worker collection
if (getExecutor() == null) {
createExecutor();
}

initializeConnectionLatch();

// Start poller threads
//创建选择器线程并启动
pollers = new Poller[getPollerThreadCount()];//getPollerThreadCount(),可用处理器数量
for (int i=0; i<pollers.length; i++) {
pollers[i] = new Poller();//创建Poller,构造打开选择器,this.selector = Selector.open();
Thread pollerThread = new Thread(pollers[i], getName() + "-ClientPoller-"+i);
pollerThread.setPriority(threadPriority);
pollerThread.setDaemon(true);
//启动异步线程,运行Poller的run方法
pollerThread.start();
}
//创建Acceptor线程并启动
startAcceptorThreads();
}
}

protected final void startAcceptorThreads() {
int count = getAcceptorThreadCount();
acceptors = new Acceptor[count];

for (int i = 0; i < count; i++) {
//创建接收器对象并启动
acceptors[i] = createAcceptor();
String threadName = getName() + "-Acceptor-" + i;
acceptors[i].setThreadName(threadName);
Thread t = new Thread(acceptors[i], threadName);
t.setPriority(getAcceptorThreadPriority());
t.setDaemon(getDaemon());
t.start();//启动异步线程
}
}

@Override
protected AbstractEndpoint.Acceptor createAcceptor() {
return new Acceptor();
}
}

Acceptor接收请求

启动Acceptor线程接收客户端连接,将客户端socket封装成PollerEvent,添加到队列,等待Poller线程处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
protected class Acceptor extends AbstractEndpoint.Acceptor {

@Override
public void run() {

int errorDelay = 0;
long pauseStart = 0;

// Loop until we receive a shutdown command
while (running) {
while (paused && running) {
if (state != AcceptorState.PAUSED) {
pauseStart = System.nanoTime();
// Entered pause state
state = AcceptorState.PAUSED;
}
if ((System.nanoTime() - pauseStart) > 1_000_000) {
// Paused for more than 1ms
try {
if ((System.nanoTime() - pauseStart) > 10_000_000) {
Thread.sleep(10);
} else {
Thread.sleep(1);
}
} catch (InterruptedException e) {
// Ignore
}
}
}

if (!running) {
break;
}
state = AcceptorState.RUNNING;

try {
//if we have reached max connections, wait
countUpOrAwaitConnection();

SocketChannel socket = null;
try {
// Accept the next incoming connection from the server
// socket
//1、接收客户端连接通道
socket = serverSock.accept();
} catch (IOException ioe) {
// We didn't get a socket
countDownConnection();
if (running) {
// Introduce delay if necessary
errorDelay = handleExceptionWithDelay(errorDelay);
// re-throw
throw ioe;
} else {
break;
}
}
// Successful accept, reset the error delay
errorDelay = 0;

// Configure the socket
if (running && !paused) {
// setSocketOptions() will hand the socket off to
// an appropriate processor if successful
//2、将socket交给适当的处理器处理
if (!setSocketOptions(socket)) {
closeSocket(socket);
}
} else {
closeSocket(socket);
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error(sm.getString("endpoint.accept.fail"), t);
}
}
state = AcceptorState.ENDED;
}

protected boolean setSocketOptions(SocketChannel socket) {
// Process the connection
try {
//disable blocking, APR style, we are gonna be polling it
//设置非阻塞
socket.configureBlocking(false);
//2.1、获取客户端Socket
Socket sock = socket.socket();
socketProperties.setProperties(sock);

NioChannel channel = nioChannels.pop();
if (channel == null) {
SocketBufferHandler bufhandler = new SocketBufferHandler(
socketProperties.getAppReadBufSize(),
socketProperties.getAppWriteBufSize(),
socketProperties.getDirectBuffer());
if (isSSLEnabled()) {
channel = new SecureNioChannel(socket, bufhandler, selectorPool, this);
} else {
channel = new NioChannel(socket, bufhandler);
}
} else {
channel.setIOChannel(socket);
channel.reset();
}
//2.2、向Poller注册socket,封装成PollerEvent,添加到队列
getPoller0().register(channel);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
try {
log.error("",t);
} catch (Throwable tt) {
ExceptionUtils.handleThrowable(tt);
}
// Tell to close the socket
return false;
}
return true;
}
}

处理读写事件

Poller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
public class Poller implements Runnable {
private Selector selector;
public Poller() throws IOException {
//打开选择器
this.selector = Selector.open();
}
//注册socket,封装成PollerEvent,添加到队列
public void register(final NioChannel socket) {
socket.setPoller(this);
NioSocketWrapper ka = new NioSocketWrapper(socket, NioEndpoint.this);
socket.setSocketWrapper(ka);
ka.setPoller(this);
ka.setReadTimeout(getSocketProperties().getSoTimeout());
ka.setWriteTimeout(getSocketProperties().getSoTimeout());
ka.setKeepAliveLeft(NioEndpoint.this.getMaxKeepAliveRequests());
ka.setReadTimeout(getConnectionTimeout());
ka.setWriteTimeout(getConnectionTimeout());
PollerEvent r = eventCache.pop();
ka.interestOps(SelectionKey.OP_READ);//this is what OP_REGISTER turns into.
if ( r==null) {
r = new PollerEvent(socket,ka,OP_REGISTER);
} else {
r.reset(socket,ka,OP_REGISTER);
}
//添加PollerEvent
addEvent(r);
}

@Override
public void run() {
// Loop until destroy() is called
//线程循环调用处理socket事件
while (true) {

boolean hasEvents = false;

try {
if (!close) {
//1、轮询处理队列的PollerEvent,异步执行注册读取事件
hasEvents = events();

if (wakeupCounter.getAndSet(-1) > 0) {
// If we are here, means we have other stuff to do
// Do a non blocking select
//非阻塞select
keyCount = selector.selectNow();
} else {
//阻塞select,当没有事件处理时,select方法会阻塞线程,
keyCount = selector.select(selectorTimeout);
}
wakeupCounter.set(0);
}
if (close) {
events();
timeout(0, false);
try {
selector.close();
} catch (IOException ioe) {
log.error(sm.getString("endpoint.nio.selectorCloseFail"), ioe);
}
break;
}
} catch (Throwable x) {
ExceptionUtils.handleThrowable(x);
log.error("",x);
continue;
}
// Either we timed out or we woke up, process events first
if (keyCount == 0) {
hasEvents = (hasEvents | events());
}
//4、获取事件进行处理
Iterator<SelectionKey> iterator =
keyCount > 0 ? selector.selectedKeys().iterator() : null;
// Walk through the collection of ready keys and dispatch
// any active event.
while (iterator != null && iterator.hasNext()) {
SelectionKey sk = iterator.next();
//获取完事件处理完后,如果不移除,仍会存在,需要手动移除
iterator.remove();
NioSocketWrapper socketWrapper = (NioSocketWrapper) sk.attachment();
// Attachment may be null if another thread has called
// cancelledKey()
if (socketWrapper != null) {
//5、调用processKey方法对有数据读写的socket进行处理
processKey(sk, socketWrapper);
}
}

// Process timeouts
timeout(keyCount,hasEvents);
}

getStopLatch().countDown();
}

public boolean events() {
boolean result = false;

PollerEvent pe = null;
for (int i = 0, size = events.size(); i < size && (pe = events.poll()) != null; i++ ) {
result = true;
try {
//2、异步运行PollerEvent,注册读取事件
pe.run();
pe.reset();
if (running && !paused) {
eventCache.push(pe);
}
} catch ( Throwable x ) {
log.error("",x);
}
}

return result;
}

protected void processKey(SelectionKey sk, NioSocketWrapper attachment) {
try {
if (close) {
cancelledKey(sk);
} else if ( sk.isValid() && attachment != null ) {
if (sk.isReadable() || sk.isWritable() ) {
if ( attachment.getSendfileData() != null ) {
processSendfile(sk,attachment, false);
} else {
unreg(sk, attachment, sk.readyOps());
boolean closeSocket = false;
// Read goes before write
if (sk.isReadable()) {
//5.1、处理读事件
if (!processSocket(attachment, SocketEvent.OPEN_READ, true)) {
closeSocket = true;
}
}
if (!closeSocket && sk.isWritable()) {
//5.2、处理写事件
if (!processSocket(attachment, SocketEvent.OPEN_WRITE, true)) {
closeSocket = true;
}
}
if (closeSocket) {
cancelledKey(sk);
}
}
}
} else {
// Invalid key
cancelledKey(sk);
}
} catch (CancelledKeyException ckx) {
cancelledKey(sk);
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
log.error("",t);
}
}
}

public static class PollerEvent implements Runnable {
@Override
public void run() {
//3、注册读取事件
socket.getIOChannel().register(
socket.getPoller().getSelector(), SelectionKey.OP_READ, socketWrapper);

}
}

AbstractEndpoint处理读写事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
public abstract class AbstractEndpoint<S> {
public boolean processSocket(SocketWrapperBase<S> socketWrapper,
SocketEvent event, boolean dispatch) {
try {
if (socketWrapper == null) {
return false;
}
//1、复用之前回收的SocketProcessorBase,没有可回收则新建
SocketProcessorBase<S> sc = processorCache.pop();
if (sc == null) {
sc = createSocketProcessor(socketWrapper, event);
} else {
sc.reset(socketWrapper, event);
}
Executor executor = getExecutor();
if (dispatch && executor != null) {
//2、异步执行SocketProcessor
executor.execute(sc);
} else {
sc.run();
}
} catch (RejectedExecutionException ree) {
getLog().warn(sm.getString("endpoint.executor.fail", socketWrapper) , ree);
return false;
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
// This means we got an OOM or similar creating a thread, or that
// the pool and its queue are full
getLog().error(sm.getString("endpoint.process.fail"), t);
return false;
}
return true;
}
}

public class NioEndpoint extends AbstractJsseEndpoint<NioChannel> {

@Override
protected SocketProcessorBase<NioChannel> createSocketProcessor(
SocketWrapperBase<NioChannel> socketWrapper, SocketEvent event) {
return new SocketProcessor(socketWrapper, event);
}
}

public abstract class SocketProcessorBase<S> implements Runnable {
@Override
public final void run() {
synchronized (socketWrapper) {
// It is possible that processing may be triggered for read and
// write at the same time. The sync above makes sure that processing
// does not occur in parallel. The test below ensures that if the
// first event to be processed results in the socket being closed,
// the subsequent events are not processed.
if (socketWrapper.isClosed()) {
return;
}
//3、处理请求
doRun();
}
}
}

SocketProcessor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
protected class SocketProcessor extends SocketProcessorBase<NioChannel> {
@Override
protected void doRun() {
NioChannel socket = socketWrapper.getSocket();
SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector());
//...
if (handshake == 0) {
SocketState state = SocketState.OPEN;
// Process the request from this socket
if (event == null) {
state = getHandler().process(socketWrapper, SocketEvent.OPEN_READ);
} else {
//处理读写事件,调用ConnectionHandler的process方法
state = getHandler().process(socketWrapper, event);
}
if (state == SocketState.CLOSED) {
close(socket, key);
}
}
//...
}
}
//Http11NioProtocol的父类
public abstract class AbstractHttp11Protocol<S> extends AbstractProtocol<S> {
public AbstractHttp11Protocol(AbstractEndpoint<S> endpoint) {
super(endpoint);
setConnectionTimeout(Constants.DEFAULT_CONNECTION_TIMEOUT);
//封装连接处理器
ConnectionHandler<S> cHandler = new ConnectionHandler<>(this);
setHandler(cHandler);
getEndpoint().setHandler(cHandler);
}
}

ConnectionHandler

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
protected static class ConnectionHandler<S> implements AbstractEndpoint.Handler<S> {
@Override
public SocketState process(SocketWrapperBase<S> wrapper, SocketEvent status) {

Processor processor = connections.get(socket);

//...
try {
//...
if (processor == null) {
processor = getProtocol().createProcessor();
register(processor);
}
//...
SocketState state = SocketState.CLOSED;
do {
//处理读写事件
state = processor.process(wrapper, status);

//...
} while ( state == SocketState.UPGRADING);

//...
// 确保从当前连接列表中删除socket/processor
connections.remove(socket);
release(processor);
return SocketState.CLOSED;
}
}

AbstractProcessorLight

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public abstract class AbstractProcessorLight implements Processor {
@Override
public SocketState process(SocketWrapperBase<?> socketWrapper, SocketEvent status)throws IOException {

SocketState state = SocketState.CLOSED;
Iterator<DispatchType> dispatches = null;
do {
if (dispatches != null) {
//...
} else if (status == SocketEvent.OPEN_WRITE) {
// Extra write event likely after async, ignore
state = SocketState.LONG;
} else if (status == SocketEvent.OPEN_READ) {
//处理读取事件,这里调用Http11Processor的service方法进行处理
state = service(socketWrapper);
}
//...
} while (state == SocketState.ASYNC_END ||
dispatches != null && state != SocketState.CLOSED);

return state;
}
}

调用Http11Processor的service方法

1
2
3
4
5
6
7
8
9
10
public class Http11Processor extends AbstractProcessor {
@Override
public SocketState service(SocketWrapperBase<?> socketWrapper) throws IOException {
//...
//getAdapter()获取CoyoteAdapter,在Connector的initInternal方法中创建
//调用CoyoteAdapter的
getAdapter().service(request, response);
//...
}
}

适配request、response对象

CoyoteAdapter将Tomcat的coyoteRequest、coyoteResponse适配为HttpServletRequest、HttpServletResponse

将请求、响应传到后面的组件处理,Container使用Pipeline-Valve管道来处理请求

Connector->StandardService->StandardEngine>StandardPipeline->StandardEngineValve.invoke

Connector通过它的上级组件service,找到service的子组件Engine,在获取Pipeline,进行责任链调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class CoyoteAdapter implements Adapter {
@Override
public void service(org.apache.coyote.Request req, org.apache.coyote.Response res) throws Exception {
Request request = (Request) req.getNote(ADAPTER_NOTES);
Response response = (Response) res.getNote(ADAPTER_NOTES);

if (request == null) {
// Create objects
//创建HttpServletRequest实现类
request = connector.createRequest();
request.setCoyoteRequest(req);
//创建HttpServletResponse实现类
response = connector.createResponse();
response.setCoyoteResponse(res);

// Link objects
request.setResponse(response);
response.setRequest(request);

// Set as notes
//将HttpServletRequest到coyote.Request中
req.setNote(ADAPTER_NOTES, request);
//将HttpServletResponse设置到coyote.Response中
res.setNote(ADAPTER_NOTES, response);

// 设置query参数编码
req.getParameters().setQueryStringCharset(connector.getURICharset());
}
//...
//解析和设置Catalina并配置特定的请求参数
boolean postParseSuccess = postParseRequest(req, request, res, response);
if (postParseSuccess) {
//check valves if we support async
request.setAsyncSupported(
connector.getService().getContainer().getPipeline().isAsyncSupported());
// Calling the container
//Connector->StandardService->StandardEngine>StandardPipeline->StandardEngineValve.invoke
connector.getService().getContainer().getPipeline().getFirst().invoke(
request, response);
}

}
}

寻找host

调用容器对象Engine寻找host,找不到返回404,找到则调用下一个组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
final class StandardEngineValve extends ValveBase {
@Override
public final void invoke(Request request, Response response)
throws IOException, ServletException {

// 根据请求的服务器名称,选择适当的子Host来处理此请求。如果没有找到匹配的Host,则返回适当的HTTP错误。
Host host = request.getHost();
if (host == null) {
// HTTP 0.9 or HTTP 1.0 request without a host when no default host
// is defined.
// Don't overwrite an existing error
if (!response.isError()) {
//没有
response.sendError(404);
}
return;
}
if (request.isAsyncSupported()) {
request.setAsyncSupported(host.getPipeline().isAsyncSupported());
}

// Ask this Host to process this request
//StandardHost->AccessLogValve.invoke
host.getPipeline().getFirst().invoke(request, response);
}
}

记录请求和响应信息

记录总结指定请求和响应的消息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public abstract class AbstractAccessLogValve extends ValveBase implements AccessLog {
@Override
public void invoke(Request request, Response response) throws IOException,
ServletException {
if (tlsAttributeRequired) {
// The log pattern uses TLS attributes. Ensure these are populated
// before the request is processed because with NIO2 it is possible
// for the connection to be closed (and the TLS info lost) before
// the access log requests the TLS info. Requesting it now causes it
// to be cached in the request.
request.getAttribute(Globals.CERTIFICATES_ATTR);
}
if (cachedElements != null) {
for (CachedElement element : cachedElements) {
element.cache(request);
}
}
//ErrorReportValve.invoke
getNext().invoke(request, response);
}
}

输出错误页面

输出HTML错误页面的Valve实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class ErrorReportValve extends ValveBase {
@Override
public void invoke(Request request, Response response) throws IOException, ServletException {

// Perform the request
//StandardHostValve.invoke,根据指定的请求URI,选择适当的子Context来处理此请求
getNext().invoke(request, response);
//...
//ERROR_EXCEPTION = "javax.servlet.error.exception"
Throwable throwable = (Throwable) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION);
//...
try {
//打印错误报告
report(request, response, throwable);
} catch (Throwable tt) {
ExceptionUtils.handleThrowable(tt);
}
}
}

匹配合适的Context处理

根据指定的请求URI,选择适当的子Context来处理此请求。如果找不到匹配的Context,则返回适当的HTTP错误

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
final class StandardHostValve extends ValveBase {
@Override
public final void invoke(Request request, Response response)
throws IOException, ServletException {

// Select the Context to be used for this Request
Context context = request.getContext();
if (context == null) {
// Don't overwrite an existing error
if (!response.isError()) {
response.sendError(404);
}
return;
}
//通知所有的javax.servlet.ServletRequestListener请求启动
if (!asyncAtStart && !context.fireRequestInitEvent(request.getRequest())) {
// Don't fire listeners during async processing (the listener
// fired for the request that called startAsync()).
// If a request init listener throws an exception, the request
// is aborted.
return;
}
//...

try {
if (!response.isErrorReportRequired()) {
//StandardPipeline->StandardContextValve.invoke
context.getPipeline().getFirst().invoke(request, response);
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
container.getLogger().error("Exception Processing " + request.getRequestURI(), t);
// If a new error occurred while trying to report a previous
// error allow the original error to be reported.
if (!response.isErrorReportRequired()) {
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t);
throwable(request, response, t);
}
}
}
}

匹配合适的Wrapper处理

根据指定的请求URI,选择适当的子Wrapper来处理此请求。如果没有找到匹配的Wrapper,则返回适当的HTTP错误。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
final class StandardContextValve extends ValveBase {
@Override
public final void invoke(Request request, Response response)
throws IOException, ServletException {

//禁止直接访问WEB-INF或META-INF下的资源
MessageBytes requestPathMB = request.getRequestPathMB();
if ((requestPathMB.startsWithIgnoreCase("/META-INF/", 0))
|| (requestPathMB.equalsIgnoreCase("/META-INF"))
|| (requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0))
|| (requestPathMB.equalsIgnoreCase("/WEB-INF"))) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}

// 选择要用于此请求的包装器
Wrapper wrapper = request.getWrapper();
if (wrapper == null || wrapper.isUnavailable()) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}

// Acknowledge the request
try {
response.sendAcknowledgement(ContinueResponseTiming.IMMEDIATELY);
} catch (IOException ioe) {
container.getLogger().error(sm.getString(
"standardContextValve.acknowledgeException"), ioe);
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, ioe);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
}

if (request.isAsyncSupported()) {
request.setAsyncSupported(wrapper.getPipeline().isAsyncSupported());
}
//StandardPipeline->StandardWrapperValve.invoke
wrapper.getPipeline().getFirst().invoke(request, response);
}
}

分配Servlet、构建过滤器链

获取StandardWrapper的Servlet(解析web.xml时封装指定的DispatcherServlet),如果没有则实例并初始化,并为请求构建一个过滤器链,调用执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
final class StandardWrapperValve extends ValveBase {
@Override
public final void invoke(Request request, Response response)
throws IOException, ServletException {
boolean unavailable = false;

requestCount.incrementAndGet();
StandardWrapper wrapper = (StandardWrapper) getContainer();
Servlet servlet = null;
Context context = (Context) wrapper.getParent();
//...
if (!unavailable) {
//默认情况下Tomcat懒加载,到此处创建Servlet;但一般集成SpringMVC时我们会在web.xml指定自定义Servlet,在StandardContext启动时创建
//如果没有实例化过此Servlet,则实例初始化后返回
servlet = wrapper.allocate();
}
//为这个请求创建过滤器链,构造一个FilterChain实现,它将包装指定servlet实例的执行
ApplicationFilterChain filterChain =
ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);


filterChain.doFilter(request.getRequest(),
response.getResponse());
}
}


public final class ApplicationFilterFactory {
public static ApplicationFilterChain createFilterChain(ServletRequest request,
Wrapper wrapper, Servlet servlet) {

ApplicationFilterChain filterChain = (ApplicationFilterChain) req.getFilterChain();
if (filterChain == null) {
filterChain = new ApplicationFilterChain();
req.setFilterChain(filterChain);
}
filterChain.setServlet(servlet);
//获取此上下文的过滤器映射
StandardContext context = (StandardContext) wrapper.getParent();
FilterMap filterMaps[] = context.findFilterMaps();

//将相关的路径映射过滤器添加到此过滤器链中
for (FilterMap filterMap : filterMaps) {
if (!matchDispatcher(filterMap, dispatcher)) {
continue;
}
if (!matchFiltersURL(filterMap, requestPath)) {
continue;
}
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
context.findFilterConfig(filterMap.getFilterName());
if (filterConfig == null) {
// FIXME - log configuration problem
continue;
}
filterChain.addFilter(filterConfig);
}

// 添加与servlet名称匹配的过滤器
for (FilterMap filterMap : filterMaps) {
if (!matchDispatcher(filterMap, dispatcher)) {
continue;
}
if (!matchFiltersServlet(filterMap, servletName)) {
continue;
}
ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)
context.findFilterConfig(filterMap.getFilterName());
if (filterConfig == null) {
// FIXME - log configuration problem
continue;
}
filterChain.addFilter(filterConfig);
}
// Return the completed filter chain
return filterChain;
}
}

执行过滤器链

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public final class ApplicationFilterChain implements FilterChain {


@Override
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
//...
internalDoFilter(request,response);
//...
}

private void internalDoFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
//已调用的过滤器链索引位置 < 过滤器数量
if (pos < n) {
ApplicationFilterConfig filterConfig = filters[pos++];
Filter filter = filterConfig.getFilter();
//...
if( Globals.IS_SECURITY_ENABLED ) {
} else {
//调用过滤器,最后会回调回来,chain.doFilter(request, response);
filter.doFilter(request, response, this);
}
}

//执行完过滤器链后,调用servlet的service方法
servlet.service(request, response);

}
}

调用类service实现

HttpServlet调用service方法实现,最终调用子类实现的doXXX方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
public abstract class HttpServlet extends GenericServlet {
@Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {

HttpServletRequest request;
HttpServletResponse response;

try {
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (ClassCastException e) {
throw new ServletException(lStrings.getString("http.non_http"));
}
//调用子类实现
service(request, response);
}

protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {

String method = req.getMethod();

if (method.equals(METHOD_GET)) {
long lastModified = getLastModified(req);
if (lastModified == -1) {
// servlet doesn't support if-modified-since, no reason
// to go through further expensive logic
doGet(req, resp);
} else {
long ifModifiedSince;
try {
ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);
} catch (IllegalArgumentException iae) {
// Invalid date header - proceed as if none was set
ifModifiedSince = -1;
}
if (ifModifiedSince < (lastModified / 1000 * 1000)) {
// If the servlet mod time is later, call doGet()
// Round down to the nearest second for a proper compare
// A ifModifiedSince of -1 will always be less
maybeSetLastModified(resp, lastModified);
doGet(req, resp);
} else {
resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
}
}

} else if (method.equals(METHOD_HEAD)) {
long lastModified = getLastModified(req);
maybeSetLastModified(resp, lastModified);
doHead(req, resp);

} else if (method.equals(METHOD_POST)) {
doPost(req, resp);

} else if (method.equals(METHOD_PUT)) {
doPut(req, resp);

} else if (method.equals(METHOD_DELETE)) {
doDelete(req, resp);

} else if (method.equals(METHOD_OPTIONS)) {
doOptions(req,resp);

} else if (method.equals(METHOD_TRACE)) {
doTrace(req,resp);

} else {
//
// Note that this means NO servlet supports whatever
// method was requested, anywhere on this server.
//

String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[1];
errArgs[0] = method;
errMsg = MessageFormat.format(errMsg, errArgs);

resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);
}
}
}

以SpringMVC为例,最终都调用了processRequest,详细处理看SpringMVC篇

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {

@Override
protected final void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

processRequest(request, response);
}

@Override
protected final void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {

processRequest(request, response);
}
}