本文接下來介紹tomcat的默認連接器,Tomcat中的默認連接器必須滿足以下要求:
-
實現org.apache.catalina.Connector接口
-
負責創建實現org.apache.catalina.Request接口的Request對象
-
負責創建實現org.apache.catalina.Response接口的Response對象
org.apache.catalina.Connector接口最重要的方法是getContainer() 、setContainer()、creatRequest()、 creatResponse(),setContainer()方法用于設置相關聯的servlet容器,getContainer()方法獲取相關連的servlet容器,creatRequest()方法為http請求創建request對象,creatResponse()方法創建response對象
下面來分析HttpConnector類實現,HttpConnector類同時實現了org.apache.catalina.Connector接口org.apache.catalina.Lifecycle接口(用于生命周期管理)、java.lang.Runnable接口(多線程接口)
在HttpConnector對象的初始化方法initialize()里面,調用私有方法open(),創建ServerSocket實例
private
ServerSocket open()
throws
IOException, KeyStoreException, NoSuchAlgorithmException,
CertificateException, UnrecoverableKeyException,
KeyManagementException
{
//
Acquire the server socket factory for this Connector
ServerSocketFactory factory =
getFactory();
//
If no address is specified, open a connection on all addresses
if
(address ==
null
) {
log(sm.getString(
"httpConnector.allAddresses"
));
try
{
return
(factory.createSocket(port, acceptCount));
}
catch
(BindException be) {
throw
new
BindException(be.getMessage() + ":" +
port);
}
}
//
Open a server socket on the specified address
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);
}
}
}
上面的ServerSocketFactory factory = getFactory()顯然是創建ServerSocket實例的工廠,方法如下
/**
* Return the server socket factory used by this Container.
*/
public
ServerSocketFactory getFactory() {
if
(
this
.factory ==
null
) {
synchronized
(
this
) {
this
.factory =
new
DefaultServerSocketFactory();
}
}
return
(
this
.factory);
}
工廠類DefaultServerSocketFactory實現了ServerSocketFactory接口
public
final
class
DefaultServerSocketFactory
implements
ServerSocketFactory {
public
ServerSocket createSocket (
int
port)
throws
IOException, KeyStoreException, NoSuchAlgorithmException,
CertificateException, UnrecoverableKeyException,
KeyManagementException {
return
(
new
ServerSocket(port));
}
public
ServerSocket createSocket (
int
port,
int
backlog)
throws
IOException, KeyStoreException, NoSuchAlgorithmException,
CertificateException, UnrecoverableKeyException,
KeyManagementException {
return
(
new
ServerSocket(port, backlog));
}
public
ServerSocket createSocket (
int
port,
int
backlog,
InetAddress ifAddress)
throws
IOException, KeyStoreException, NoSuchAlgorithmException,
CertificateException, UnrecoverableKeyException,
KeyManagementException {
return
(
new
ServerSocket(port, backlog, ifAddress));
}
}
下面接著分析用于生命周期的start()方法
/**
* Begin processing requests via this Connector.
*
*
@exception
LifecycleException if a fatal startup error occurs
*/
public
void
start()
throws
LifecycleException {
//
Validate and update our current state
if
(started)
throw
new
LifecycleException
(sm.getString(
"httpConnector.alreadyStarted"
));
threadName
= "HttpConnector[" + port + "]"
;
lifecycle.fireLifecycleEvent(START_EVENT,
null
);
started
=
true
;
//
Start our background thread
threadStart();
//
Create the specified minimum number of processors
while
(curProcessors <
minProcessors) {
if
((maxProcessors > 0) && (curProcessors >=
maxProcessors))
break
;
HttpProcessor processor
=
newProcessor();
recycle(processor);
}
}
首先是啟動HttpConnector連接器線程,然后是初始化最少數量的HttpProcessor處理器入棧
/**
* Start the background processing thread.
*/
private
void
threadStart() {
log(sm.getString(
"httpConnector.starting"
));
thread
=
new
Thread(
this
, threadName);
thread.setDaemon(
true
);
thread.start();
}
由于HttpConnector連接器實現了java.lang.Runnable接口,我們分析它的run()方法實現
/**
* The background thread that listens for incoming TCP/IP connections and
* hands them off to an appropriate processor.
*/
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
{
//
if (debug >= 3)
//
log("run: Waiting on serverSocket.accept()");
socket =
serverSocket.accept();
//
if (debug >= 3)
//
log("run: Returned from serverSocket.accept()");
if
(connectionTimeout > 0
)
socket.setSoTimeout(connectionTimeout);
socket.setTcpNoDelay(tcpNoDelay);
}
catch
(AccessControlException ace) {
log(
"socket accept security exception"
, ace);
continue
;
}
catch
(IOException e) {
//
if (debug >= 3)
//
log("run: Accept returned IOException", e);
try
{
//
If reopening fails, exit
synchronized
(threadSync) {
if
(started && !
stopped)
log(
"accept error: "
, e);
if
(!
stopped) {
//
if (debug >= 3)
//
log("run: Closing server socket");
serverSocket.close();
//
if (debug >= 3)
//
log("run: Reopening server socket");
serverSocket =
open();
}
}
//
if (debug >= 3)
//
log("run: IOException processing completed");
}
catch
(IOException ioe) {
log(
"socket reopen, io problem: "
, ioe);
break
;
}
catch
(KeyStoreException kse) {
log(
"socket reopen, keystore problem: "
, kse);
break
;
}
catch
(NoSuchAlgorithmException nsae) {
log(
"socket reopen, keystore algorithm problem: "
, nsae);
break
;
}
catch
(CertificateException ce) {
log(
"socket reopen, certificate problem: "
, ce);
break
;
}
catch
(UnrecoverableKeyException uke) {
log(
"socket reopen, unrecoverable key: "
, uke);
break
;
}
catch
(KeyManagementException kme) {
log(
"socket reopen, key management problem: "
, kme);
break
;
}
continue
;
}
//
Hand this socket off to an appropriate processor
HttpProcessor processor =
createProcessor();
if
(processor ==
null
) {
try
{
log(sm.getString(
"httpConnector.noProcessor"
));
socket.close();
}
catch
(IOException e) {
;
}
continue
;
}
//
if (debug >= 3)
//
log("run: Assigning socket to processor " + processor);
processor.assign(socket);
//
The processor will recycle itself when it finishes
}
//
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();
}
}
上面方法中,監聽客戶端的http請求,當監聽到http請求時,獲取Socket實例,然后委派給HttpProcessor對象進行處理(處理器線程吧),最后是如果收到停止連接器線程命令, 則事件通知可以停止線程了
在上面我們還沒有來得及分析HttpProcessor對象的初始化相關,所以要重新回到start()方法(源碼分析有時要跟蹤方法中對多個其他方法的調用,深度優先則顧此失彼,難以兼顧;而廣度優先則不便縱向深入)
//
Create the specified minimum number of processors
while
(curProcessors <
minProcessors) {
if
((maxProcessors > 0) && (curProcessors >=
maxProcessors))
break
;
HttpProcessor processor
=
newProcessor();
recycle(processor);
}
這里是創建最少數量的HttpProcessor處理器并入棧,我們先分析newProcessor()方法的實現
/**
* Create and return a new processor suitable for processing HTTP
* requests and returning the corresponding responses.
*/
private
HttpProcessor newProcessor() {
//
if (debug >= 2)
//
log("newProcessor: Creating new 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);
}
我們可以看到,這里主要是實例化HttpProcessor對象,傳入HttpConnector實例本身(里面要用到HttpConnector對象的創建Request對象方法和創建Response對象方法),然后向上轉型為Lifecycle接口類型,并調用它的start()方法,接著Vector created = new Vector()成員變量添加該HttpProcessor對象(Vector實現List接口,內部采用數組實現,其操作方法支持線程同步),最后返回實例
/**
* Recycle the specified Processor so that it can be used again.
*
*
@param
processor The processor to be recycled
*/
void
recycle(HttpProcessor processor) {
//
if (debug >= 2)
//
log("recycle: Recycling processor " + processor);
processors.push(processor);
}
這里將HttpProcessor對象入棧,成員變量Stack processors = new Stack()繼承自 Vector ,是一種先進后出的數據結構
我們現在來分析run()方法里面的相關源碼,也許更容易理解
/**
* Create (or allocate) and return an available processor for use in
* processing a specific HTTP request, if possible. If the maximum
* allowed processors have already been created and are in use, return
* <code>null</code> instead.
*/
private
HttpProcessor createProcessor() {
synchronized
(processors) {
if
(processors.size() > 0
) {
//
if (debug >= 2)
//
log("createProcessor: Reusing existing processor");
return
((HttpProcessor) processors.pop());
}
if
((maxProcessors > 0) && (curProcessors <
maxProcessors)) {
//
if (debug >= 2)
//
log("createProcessor: Creating new processor");
return
(newProcessor());
}
else
{
if
(maxProcessors < 0
) {
//
if (debug >= 2)
//
log("createProcessor: Creating new processor");
return
(newProcessor());
}
else
{
//
if (debug >= 2)
//
log("createProcessor: Cannot create new processor");
return
(
null
);
}
}
}
}
這里是從Stack processors = new Stack()成員變量里面獲取HttpProcessor對象 ,后面的代碼不用多加解釋了吧,你懂的!
后面那段代碼是干嘛的
//
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();
}
我們看到threadStop()方法里面的代碼,可以看出上面的代碼塊是用來通知線程停止的
/**
* Stop the background processing thread.
*/
private
void
threadStop() {
log(sm.getString(
"httpConnector.stopping"
));
stopped
=
true
;
try
{
threadSync.wait(
5000
);
}
catch
(InterruptedException e) {
;
}
thread
=
null
;
}
由于HttpProcessor處理器類的源碼分析相對獨立,加上篇幅還比較多,因此本文先到這里,下文繼續……
---------------------------------------------------------------------------?
本系列How Tomcat Works系本人原創?
轉載請注明出處 博客園 刺猬的溫馴?
本人郵箱: chenying998179 # 163.com ( #改為@ )
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

