&emps; 连接器最主要的作用就是等待HTTP请求,并依据请求创建Request和Response对象。所以连接器也包含两个部分:
- 等待HTTP请求的Connector;
- 依据请求创建Request和Response的Processor
org.apache.catalina.connector.http.HttpConnector类
在Tomcat4中仍存在的一个类,后面已经舍弃了,但基本思路仍在沿用
public final class HttpConnector
implements Connector, Lifecycle, Runnable {
//1. 初始化
public void initialize()
throws LifecycleException {
//....
// Establish a server socket on the specified port
//开启侦听端口
serverSocket = open();
//...
}
//启动
public void start() throws LifecycleException {
//...
// Start our background thread
threadStart();
// Create the specified minimum number of processors
//会启动一定初始数目的线程处理请求
while (curProcessors < minProcessors) {
if ((maxProcessors > 0) && (curProcessors >= maxProcessors))
break;
HttpProcessor processor = newProcessor();
//使用堆栈来存储空闲的processor
recycle(processor);
}
//...
}
//启动自身的线程
private void threadStart() {
log(sm.getString("httpConnector.starting"));
thread = new Thread(this, threadName);
thread.setDaemon(true);
thread.start();
}
public void run() {
// Loop until we receive a shutdown command
while (!stopped) {
// Accept the next incoming connection from the server socket
Socket socket = null;
try {
socket = serverSocket.accept();
if (connectionTimeout > 0)
socket.setSoTimeout(connectionTimeout);
socket.setTcpNoDelay(tcpNoDelay);
} catch (IOException e) {
//...
continue;
}
// Hand this socket off to an appropriate processor
// 调用processor
HttpProcessor processor = createProcessor();
if (processor == null) {
try {
log(sm.getString("httpConnector.noProcessor"));
socket.close();
} catch (IOException e) {
;
}
continue;
}
//通知processor去执行
processor.assign(socket);
}
// Notify the threadStop() method that we have shut ourselves down
// if (debug >= 3)
// log("run: Notifying threadStop() that we have shut down");
synchronized (threadSync) {
threadSync.notifyAll();
}
}
private HttpProcessor newProcessor() {
//穿件Processor
HttpProcessor processor = new HttpProcessor(this, curProcessors++);
if (processor instanceof Lifecycle) {
try {
((Lifecycle) processor).start();
} catch (LifecycleException e) {
log("newProcessor", e);
return (null);
}
}
created.addElement(processor);
return (processor);
}
}
HttpConnector主要包含以下几个内容:
- 初始化,开启侦听端口,监听传入的协议;
- 启动,开启HttpConnecotr自身的线程,开启一定数量的Processor线程,用于处理不同的连接请求;
- HttpConnector自身线程将建立连接的socket分配给空闲的Processor去处理。
HttpProcessor
这个类主要关注两点:
- HttpConnector和HttpProcessor的交互(connector将socket交给processor的配合);
- HttpProcessor读取socket将请求转换为Request和Response;
final class HttpProcessor
implements Lifecycle, Runnable {
public void start() throws LifecycleException {
//重复启动判断
threadStart();
}
private void threadStart() {
log(sm.getString("httpProcessor.starting"));
thread = new Thread(this, threadName);
thread.setDaemon(true);
thread.start();
if (debug >= 1)
log(" Background thread has been started");
}
public void run() {
// Process requests until we receive a shutdown signal
while (!stopped) {
// Wait for the next socket to be assigned
Socket socket = await();
if (socket == null)
continue;
// Process the request from this socket
try {
process(socket);
} catch (Throwable t) {
log("process.invoke", t);
}
// Finish up this request
connector.recycle(this);
}
// Tell threadStop() we have shut ourselves down successfully
synchronized (threadSync) {
threadSync.notifyAll();
}
}
private synchronized Socket await() {
// Wait for the Connector to provide a new Socket
while (!available) {
try {
wait();
} catch (InterruptedException e) {
}
}
// Notify the Connector that we have received this Socket
Socket socket = this.socket;
available = false;
notifyAll();
if ((debug >= 1) && (socket != null))
log(" The incoming request has been awaited");
return (socket);
}
synchronized void assign(Socket socket) {
// Wait for the Processor to get the previous Socket
while (available) {
try {
wait();
} catch (InterruptedException e) {
}
}
// Store the newly available Socket and notify our thread
this.socket = socket;
available = true;
notifyAll();
if ((debug >= 1) && (socket != null))
log(" An incoming request is being assigned");
}
}
available的初始值为false,流程如下:
- 当线程开始执行run(), 直接调用await()函数,进入wait()状态,放开对象锁;
- Connecotr调用processor.assign(), 先获得锁,因为availabe为false,跳过while循环,设置socket, available=true, 通知其他所有正在等待的地方;
- await()得到通知,因为此时available为true,跳出循环,置available为fasle,通知所有wait()的地方(此时没有),run执行后续的处理流程;
- 处理完了,connector回收这个processor,然后又进入run()的循环,进入await(), 进入wait();
若3和4之间的时候,connector再次调用assign(), 也不会有问题的. available为false,设置其为true,通知其他地方,但若前一次未处理完,此时是没有进入到await()函数里面的;并且,对于仍在处理中的processor,不可用,也不能调用其assign()
HttpProcessor.process(socket)
处理流程,将接口的请求转换为Request和Response的过程.
转换的依据就是HTTP协议内容。
HTTP请求转换为Request和Response的源码分析
//TODO
//TODO
转换成功后,通过connector.getContainer().invoke(request, response);
便可调用servlet容器来处理http请求了,后面讲详细介绍关于容器的知识。
后记
门面模式
Tomcat4中有org.apache.catalina.connector.HttpRequestFacade,Tomcat7中是org.apache.catalina.connector.RequestFacade
//Tomcat4
public final class HttpRequestFacade
extends RequestFacade
implements HttpServletRequest {
}
public class RequestFacade implements ServletRequest {
}
//Tomcat7
public class RequestFacade implements HttpServletRequest {
}
public interface HttpServletRequest extends ServletRequest {
}