Tomcat默认连接器必须实现org.apache.catalina.Connector接口,接口中最重要是以下四个方法:
1、setContainer()用于将连接器和某个servlet容器相关联。
2、getContainer()返回与当前连接器相关联的容器。
3、createRequest()方法会为引入的HTTP请求创建request对象
4、createResponse()会创建一个response对象
以下是Tomcat默认连接器的UML简图:
HttpConnector类作用:
1、通过工厂类(ServerSocketFactory或DefaultServerSocketFactory)创建服务套接字
//HttpConnector类的open()方法
private ServerSocket open()
throws IOException, KeyStoreException, NoSuchAlgorithmException,
CertificateException, UnrecoverableKeyException,
KeyManagementException
{
ServerSocketFactory factory = getFactory();
if (address == null) {
log(sm.getString("httpConnector.allAddresses"));
try {
return (factory.createSocket(port, acceptCount));
} catch (BindException be) {
throw new BindException(be.getMessage() + ":" + port);
}
}
try {
InetAddress is = InetAddress.getByName(address);
log(sm.getString("httpConnector.anAddress", address));
try {
return (factory.createSocket(port, acceptCount, is));
} catch (BindException be) {
throw new BindException(be.getMessage() + ":" + address +
":" + port);
}
} catch (Exception e) {
log(sm.getString("httpConnector.noAddress", address));
try {
return (factory.createSocket(port, acceptCount));
} catch (BindException be) {
throw new BindException(be.getMessage() + ":" + port);
}
}
}
2、维护HttpProcessor实例,避免每次都为新的Http请求创建HttpProcessor实例,减少系统开销。
private Stack processors = new Stack()//用一个栈来存放若干个HttpProcessor实例,需要时便从栈中弹出一个HttpProcessor,使用完以后由从新压入栈内。
HttpProcessor类的作用
在上一节中,HttpProcessor没有实现Runnable,因此当有多个Http请求同时到达服务器时,必须每个请求依次处理
以下是上一节HttpConnector类的部分代码:
public void run() {
ServerSocket serverSocket = null;
int port = 8080;
try {
serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1"));
}
catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
while (!stopped) {
Socket socket = null;
try {
socket = serverSocket.accept();
}
catch (Exception e) {
continue;
}
HttpProcessor processor = new HttpProcessor(this);
processor.process(socket);//HttpProcessor没有实现Runnable,所以processor.process(socket)是运行在当前线程
}
}
在Tomcat默认连器中,HttpProcessor类实现类java.iang.Runnable接口,因此当有多个请求同时访问服务器的时候,HttpConnector会为每个请求新起一个线程用以执行HttpProcessor。以下是HttpProcessor类的run()方法。
public void run() {
while (!stopped) {
Socket socket = await();//获取套接字
if (socket == null)
continue;
try {
process(socket);//进行处理
} catch (Throwable t) {
log("process.invoke", t);
}
connector.recycle(this);//将当前HttpProcessor实例压回processors桟中
}
synchronized (threadSync) {
threadSync.notifyAll();
}
}
HttpConnector和HttpProcessor分在不同的线程中运行,因此需要保证先执行HttpConnector类中processor.assign(socket)方法,将socket传给传递给HttpProcessor;在没有传递socket之前,HttpProcessor线程必须处于等待状态。当socket传递给HttpProcessor后,HttpProcessor线程再开始执行。具体流程如下: