Coyote连接器的org.apache.coyote.Processor<S>是主要负责请求的预处理.并通过它将请求转发给Adapter.不同的Protocol有不同的实现方式,那么自然其对应的Processor实现也不同.其中AbstractProcessor对为这些不同的Processor提供了一个基础的实现.它实现了HTTP和AJP所需要的共同功能和属性.
首先看下Processor是一个接口.它定义了几个重要的方法.
/**
* Common interface for processors of all protocols.
*/
public interface Processor<S> {
Executor getExecutor();
SocketState process(SocketWrapper<S> socketWrapper) throws IOException;
SocketState event(SocketStatus status) throws IOException;
SocketState asyncDispatch(SocketStatus status);
SocketState asyncPostProcess();
UpgradeInbound getUpgradeInbound();
SocketState upgradeDispatch() throws IOException;
boolean isComet();
boolean isAsync();
boolean isUpgrade();
Request getRequest();
void recycle(boolean socketClosing);
void setSslSupport(SSLSupport sslSupport);
}
Processor定义了请求的处理等方法.AbstractProcessor最主要还是最一些协议共有的属性进行封装.而没有对方法进行实现.目前具体的实现只针对AJP和HTTP.这两个类分别为AbstractAjpProcessor和AbstractHttp11Processor它们对协议的方法请求处理方式进行了实现.以AbstractHttp11Processor的process方法为例.
public SocketState process(SocketWrapper<S> socketWrapper)
throws IOException {
.....
while (!error && keepAlive && !comet && !isAsync() &&
upgradeInbound == null && !endpoint.isPaused()) {
// Parsing the request header
try {
setRequestLineReadTimeout();
if (!getInputBuffer().parseRequestLine(keptAlive)) {
if (handleIncompleteRequestLineRead()) {
break;
}
}
if (endpoint.isPaused()) {
// 503 - Service unavailable
response.setStatus(503);
error = true;
} else {
request.setStartTime(System.currentTimeMillis());
keptAlive = true;
// Set this every time in case limit has been changed via JMX
request.getMimeHeaders().setLimit(endpoint.getMaxHeaderCount());
// Currently only NIO will ever return false here
if (!getInputBuffer().parseHeaders()) {
// We've read part of the request, don't recycle it
// instead associate it with the socket
openSocket = true;
readComplete = false;
break;
}
if (!disableUploadTimeout) {
setSocketTimeout(connectionUploadTimeout);
}
}
} catch (IOException e) {
...
} catch (Throwable t) {
....
}
if (!error) {
// Setting up filters, and parse some request headers
rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);
try {
prepareRequest();
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
if (getLog().isDebugEnabled()) {
getLog().debug(sm.getString(
"http11processor.request.prepare"), t);
}
// 400 - Internal Server Error
response.setStatus(400);
adapter.log(request, response, 0);
error = true;
}
}
....
// Process the request in the adapter
if (!error) {
try {
rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
adapter.service(request, response);
// Handle when the response was committed before a serious
// error occurred. Throwing a ServletException should both
// set the status to 500 and set the errorException.
// If we fail here, then the response is likely already
// committed, so we can't try and set headers.
if(keepAlive && !error) { // Avoid checking twice.
error = response.getErrorException() != null ||
(!isAsync() &&
statusDropsConnection(response.getStatus()));
}
setCometTimeouts(socketWrapper);
} catch (InterruptedIOException e) {
error = true;
} catch (HeadersTooLargeException e) {
error = true;
// The response should not have been committed but check it
// anyway to be safe
if (!response.isCommitted()) {
response.reset();
response.setStatus(500);
response.setHeader("Connection", "close");
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
getLog().error(sm.getString(
"http11processor.request.process"), t);
// 500 - Internal Server Error
response.setStatus(500);
adapter.log(request, response, 0);
error = true;
}
}
// Finish the handling of the request
rp.setStage(org.apache.coyote.Constants.STAGE_ENDINPUT);
if (!isAsync() && !comet) {
if (error) {
// If we know we are closing the connection, don't drain
// input. This way uploading a 100GB file doesn't tie up the
// thread if the servlet has rejected it.
getInputBuffer().setSwallowInput(false);
}
endRequest();
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDOUTPUT);
// If there was an error, make sure the request is counted as
// and error, and update the statistics counter
if (error) {
response.setStatus(500);
}
request.updateCounters();
if (!isAsync() && !comet || error) {
getInputBuffer().nextRequest();
getOutputBuffer().nextRequest();
}
if (!disableUploadTimeout) {
setSocketTimeout(endpoint.getSoTimeout());
}
rp.setStage(org.apache.coyote.Constants.STAGE_KEEPALIVE);
if (breakKeepAliveLoop(socketWrapper)) {
break;
}
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
if (error || endpoint.isPaused()) {
return SocketState.CLOSED;
} else if (isAsync() || comet) {
return SocketState.LONG;
} else if (isUpgrade()) {
return SocketState.UPGRADING;
} else {
if (sendfileInProgress) {
return SocketState.SENDFILE;
} else {
if (openSocket) {
if (readComplete) {
return SocketState.OPEN;
} else {
return SocketState.LONG;
}
} else {
return SocketState.CLOSED;
}
}
}
}
上述process方法的作用有3点,第一是解析请求header也就是HTTP协议的报文头.主要是通过调用方法prepareRequest.在该方法中会检查HTTP协议报文头的user-agent,transfer-encoding以及URI等.此部分处理会倘若异常的话则返回400 – Internal Server Error.这是通过设置response状态来实现的,即语句response.setStatus(400).第二就是通过调用连接适配器的service方法,来处理请求(具体如何处理后续说明).最后,当请求处理完成以后.则使用endRequest方法来结束请求,且返回处理状态,也就是Protocol能识别的状态SocketStatus.
AbstractAjpProcessor和AbstractHttp11Processor只是针对AJP和HTTP协议通用处理方式进行实现.但是针对这2个协议的具体实现版本处理的Processor需要进行特性补充处理.如AbstractHttp11Processor的子类Http11Processor,Http11NioProcessor,Http11AprProcessor分别对应了Java Old IO,NIO,APR的协议实现方式的Processor,有兴趣可以详细阅读.