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,有兴趣可以详细阅读.