承接上一篇,这篇来看 getInputStream() 和 getReader() 源码分析
直接在 org.apache.catalina.connector.RequestFacade 中找到 getInputStream() 和 getReader()
@Override
public ServletInputStream getInputStream() throws IOException {
if (request == null) {
throw new IllegalStateException(
sm.getString("requestFacade.nullRequest"));
}
return request.getInputStream();
}
@Override
public BufferedReader getReader() throws IOException {
if (request == null) {
throw new IllegalStateException(
sm.getString("requestFacade.nullRequest"));
}
return request.getReader();
}
这里的 request 是 org.apache.catalina.connector.Request,直接来看看其中的getInputStream() 和 getReader()方法。
/**
* @return the servlet input stream for this Request. The default
* implementation returns a servlet input stream created by
* <code>createInputStream()</code>.
*
* @exception IllegalStateException if <code>getReader()</code> has
* already been called for this request
* @exception IOException if an input/output error occurs
*/
@Override
public ServletInputStream getInputStream() throws IOException {
if (usingReader) {
throw new IllegalStateException
(sm.getString("coyoteRequest.getInputStream.ise"));
}
usingInputStream = true;
if (inputStream == null) {
inputStream = new CoyoteInputStream(inputBuffer);
}
return inputStream;
}
/**
* Read the Reader wrapping the input stream for this Request. The
* default implementation wraps a <code>BufferedReader</code> around the
* servlet input stream returned by <code>createInputStream()</code>.
*
* @return a buffered reader for the request
* @exception IllegalStateException if <code>getInputStream()</code>
* has already been called for this request
* @exception IOException if an input/output error occurs
*/
@Override
public BufferedReader getReader() throws IOException {
if (usingInputStream) {
throw new IllegalStateException
(sm.getString("coyoteRequest.getReader.ise"));
}
usingReader = true;
inputBuffer.checkConverter();
if (reader == null) {
reader = new CoyoteReader(inputBuffer);
}
return reader;
}
其中 这两个方法利用 usingInputStream 和 usingReader 互斥。
这里可以看到 关键缓冲区 inputBuffer (接收到的请求内容)
/**
* The associated input buffer.
*/
protected final InputBuffer inputBuffer = new InputBuffer();
在 org.apache.catalina.connector.Request 中还有一个setCoyoteRequest方法
/**
* Coyote request.
*/
protected org.apache.coyote.Request coyoteRequest;
/**
* Set the Coyote request.
*
* @param coyoteRequest The Coyote request
*/
public void setCoyoteRequest(org.apache.coyote.Request coyoteRequest) {
this.coyoteRequest = coyoteRequest;
inputBuffer.setRequest(coyoteRequest);
}
在这个方法中 inputBuffer set了一个org.apache.coyote.Request , 这里说明请求信息实际上是从org.apache.coyote.Request中拿到的,那么问题来了, org.apache.coyote.Request 是有谁创建的呢?
我们直接找到 tomcat-coyote.jar包 下的 org.apache.coyote.http11.Http11Processor类其中有一个核心构造方法 Http11Processor
public Http11Processor(int maxHttpHeaderSize, boolean allowHostHeaderMismatch,
boolean rejectIllegalHeaderName, AbstractEndpoint<?> endpoint, int maxTrailerSize,
Set<String> allowedTrailerHeaders, int maxExtensionSize, int maxSwallowSize,
Map<String,UpgradeProtocol> httpUpgradeProtocols, boolean sendReasonPhrase,
String relaxedPathChars, String relaxedQueryChars) {
super(endpoint);
httpParser = new HttpParser(relaxedPathChars, relaxedQueryChars);
inputBuffer = new Http11InputBuffer(request, maxHttpHeaderSize, rejectIllegalHeaderName, httpParser);
request.setInputBuffer(inputBuffer);
outputBuffer = new Http11OutputBuffer(response, maxHttpHeaderSize, sendReasonPhrase);
response.setOutputBuffer(outputBuffer);
// Create and add the identity filters.
inputBuffer.addFilter(new IdentityInputFilter(maxSwallowSize));
outputBuffer.addFilter(new IdentityOutputFilter());
// Create and add the chunked filters.
inputBuffer.addFilter(new ChunkedInputFilter(maxTrailerSize, allowedTrailerHeaders,
maxExtensionSize, maxSwallowSize));
outputBuffer.addFilter(new ChunkedOutputFilter());
// Create and add the void filters.
inputBuffer.addFilter(new VoidInputFilter());
outputBuffer.addFilter(new VoidOutputFilter());
// Create and add buffered input filter
inputBuffer.addFilter(new BufferedInputFilter());
// Create and add the chunked filters.
//inputBuffer.addFilter(new GzipInputFilter());
outputBuffer.addFilter(new GzipOutputFilter());
pluggableFilterIndex = inputBuffer.getFilters().length;
this.httpUpgradeProtocols = httpUpgradeProtocols;
this.allowHostHeaderMismatch = allowHostHeaderMismatch;
}
这里通过调用其继承抽象类 AbstractProcessor super(endpoint) 明确的创建一个请求和一个响应,且分别注入 inputBuffer 和 outputBuffer 请求信息(这个信息是socket注入的信息)。不过
这里的请求和响应并不是 org.apache.catalina.connector.RequestFacade 中使用的是 org.apache.catalina.connector.Request 和 org.apache.catalina.connector.Response 类型,而是 org.apache.coyote.Request 和 org.apache.coyote.Response
那org.apache.catalina.connector.Request 和 org.apache.catalina.connector.Response 有是有谁创建,并且又是由谁做了setCoyoteRequest()动作呢?
我们找到 org.apache.catalina.connector.Connector 类 其中的 createRequest() 和 createResponse() 方法
/**
* Create (or allocate) and return a Request object suitable for
* specifying the contents of a Request to the responsible Container.
*
* @return a new Servlet request object
*/
public Request createRequest() {
Request request = new Request();
request.setConnector(this);
return (request);
}
/**
* Create (or allocate) and return a Response object suitable for
* receiving the contents of a Response from the responsible Container.
*
* @return a new Servlet response object
*/
public Response createResponse() {
Response response = new Response();
response.setConnector(this);
return (response);
}
这里面都做了setConnector(this)操作,关联此connector,下面来看看 Connector 的构造方法
/**
* Coyote Protocol handler class name.
* Defaults to the Coyote HTTP/1.1 protocolHandler.
*/
protected String protocolHandlerClassName =
"org.apache.coyote.http11.Http11NioProtocol";
public Connector(String protocol) {
setProtocol(protocol);
// Instantiate protocol handler
ProtocolHandler p = null;
try {
Class<?> clazz = Class.forName(protocolHandlerClassName);
p = (ProtocolHandler) clazz.getConstructor().newInstance();
} catch (Exception e) {
log.error(sm.getString(
"coyoteConnector.protocolHandlerInstantiationFailed"), e);
} finally {
this.protocolHandler = p;
}
if (Globals.STRICT_SERVLET_COMPLIANCE) {
uriCharset = StandardCharsets.ISO_8859_1;
} else {
uriCharset = StandardCharsets.UTF_8;
}
}
方法中主要实例了一个 ProtocolHandler 类 ,如果没有配置的话使用的是 org.apache.coyote.http11.Http11NioProtocol,
直接去查看 org.apache.coyote.http11.Http11NioProtocol 类 其中调用父类的 getEndpoint()方法,一自往父类溯源,最后可以找到
org.apache.coyote.http11.AbstractHttp11Protocol<S> 类 其中一个核心方法 createProcessor() 中创建了 org.apache.coyote.http11.Http11Processor实例
@SuppressWarnings("deprecation")
@Override
protected Processor createProcessor() {
Http11Processor processor = new Http11Processor(getMaxHttpHeaderSize(),
getAllowHostHeaderMismatch(), getRejectIllegalHeaderName(), getEndpoint(),
getMaxTrailerSize(), allowedTrailerHeaders, getMaxExtensionSize(),
getMaxSwallowSize(), httpUpgradeProtocols, getSendReasonPhrase(),
relaxedPathChars, relaxedQueryChars);
processor.setAdapter(getAdapter());
processor.setMaxKeepAliveRequests(getMaxKeepAliveRequests());
processor.setConnectionUploadTimeout(getConnectionUploadTimeout());
processor.setDisableUploadTimeout(getDisableUploadTimeout());
processor.setCompressionMinSize(getCompressionMinSize());
processor.setCompression(getCompression());
processor.setNoCompressionUserAgents(getNoCompressionUserAgents());
processor.setCompressibleMimeTypes(getCompressibleMimeTypes());
processor.setRestrictedUserAgents(getRestrictedUserAgents());
processor.setMaxSavePostSize(getMaxSavePostSize());
processor.setServer(getServer());
processor.setServerRemoveAppProvidedValues(getServerRemoveAppProvidedValues());
return processor;
}
现在有了 Http11Processor 也就有了 org.apache.coyote.Request 和 org.apache.coyote.Response 方法。
现在我们需要找到是谁调用了 org.apache.catalina.connector.Request setCoyoteRequest方法呢,将 org.apache.coyote.Request 转化为 org.apache.catalina.connector.Request?
直接去看 org.apache.catalina.connector.CoyoteAdapter 的 service()方法
@Override
public void service(org.apache.coyote.Request req, org.apache.coyote.Response res)
throws Exception {
Request request = (Request) req.getNote(ADAPTER_NOTES);
Response response = (Response) res.getNote(ADAPTER_NOTES);
if (request == null) {
// Create objects
request = connector.createRequest(); // 创建org.apache.catalina.connector.Request
request.setCoyoteRequest(req); // 转化
response = connector.createResponse(); // 创建org.apache.catalina.connector.Response
response.setCoyoteResponse(res); //转化
// Link objects
request.setResponse(response);
response.setRequest(request);
// Set as notes
req.setNote(ADAPTER_NOTES, request);
res.setNote(ADAPTER_NOTES, response);
// Set query string encoding
req.getParameters().setQueryStringCharset(connector.getURICharset());
}
// .... 省略 ....
}
这这个方法里进行了转化调用。
通过 tomcat的源码,我们可以总结出:
Tomcat 创建Connector连接器时,实例化了 ProtocolHandler类 (Tomcat协议接口),Connector使用ProtocolHandler来处理请求 。ProtocolHandler包含了三个部件:Endpoint、Processor、Adapter。
- Endpoint是通信端点,即通信监听的接口,是具体的Socket接收处理类,是对传输层的抽象 获取 scoket流
- Processor是协议处理接口,负责构造Request和Response对象(这里是指org.apache.coyote.Request 和 org.apache.coyote.Response),并通过Adapter将其提交到Catalina容器处理,是对应用层协议的抽象。
- Adapter是适配器,将Processor构造的Request对象转换为ServletRequest交给Container进行具体的处理。(转化)