目录
在阅读本篇笔记前请先看(三)Tomcat架构及运行原理之Connector源码分析文章。
1. 请求的处理及Container通信
1.1 Processor
在上篇笔记中,我们已经介绍过了Connector中是如何从Container调用到Connector中,而Connector又是如何创建Socket监听机制以及和本篇需要讲的对具体请求进行处理入口。本篇着重于从handler到Servlet整个流程的通信。先看到关键的processor接口源码:
public interface Processor {
SocketState process(SocketWrapperBase<?> socketWrapper,
SocketEvent status) throws IOException;
UpgradeToken getUpgradeToken();
boolean isUpgrade();
boolean isAsync();
void timeoutAsync(long now);
Request getRequest();
void recycle();
void setSslSupport(SSLSupport sslSupport);
ByteBuffer getLeftoverInput();
void pause();
boolean checkAsyncTimeoutGeneration();
}
本接口process接口无疑是最重要的,但是getRequest方法和recycle方法也是需要注意的。
1.1.1 AbstractProcessorLight
首先看到Processor接口的实现子类AbstractProcessorLight。其部分关键源码如下:
public abstract class AbstractProcessorLight implements Processor {
@Override
public SocketState process(SocketWrapperBase<?> socketWrapper,
SocketEvent status)
throws IOException {
// 设置为CLOSED是为了等下不用再设置状态而可以直接跳出do-while循环
SocketState state = SocketState.CLOSED;
Iterator<DispatchType> dispatches = null;
do {
// 中间的调用dispatch可以忽略,因为和HTTP请求无关
// Websocket才会用到
if (dispatches != null) {
...
} else if (status == SocketEvent.OPEN_READ){
// 执行HTTP请求方法,具体实现交给子类实现
state = service(socketWrapper);
} else {
state = SocketState.CLOSED;
}
// 异步执行
if (state != SocketState.CLOSED && isAsync()) {
state = asyncPostProcess();
}
if (dispatches == null || !dispatches.hasNext()) {
dispatches = getIteratorAndClearDispatches();
}
} while (state == SocketState.ASYNC_END ||
dispatches != null && state != SocketState.CLOSED);
return state;
}
protected abstract SocketState service(
SocketWrapperBase<?> socketWrapper) throws IOException;
protected abstract SocketState dispatch(SocketEvent status)
throws IOException;
}
本类也只是一个模板方法,在父类中确定根据哪些状态去执行哪些方法。普通的HTTP请求和service相关,而诸如Websocket和dispatch相关。
1.1.2 AbstractProcessor
这个类起到承上启下的作用。其部分关键源码如下:
public abstract class AbstractProcessor extends AbstractProcessorLight
implements ActionHook {
protected final Adapter adapter;
protected final Request request;
protected final Response response;
protected volatile SocketWrapperBase<?> socketWrapper = null;
protected volatile SSLSupport sslSupport;
public AbstractProcessor(Adapter adapter) {
this(adapter, new Request(), new Response());
}
protected AbstractProcessor(Adapter adapter, Request coyoteRequest,
Response coyoteResponse) {
this.adapter = adapter;
asyncStateMachine = new AsyncStateMachine(this);
request = coyoteRequest;
response = coyoteResponse;
response.setHook(this);
request.setResponse(response);
request.setHook(this);
userDataHelper = new UserDataHelper(getLog());
}
}
可以看到,这个类关键的代码很少(指的是在启动Tomcat时和普通的HTTP请求进来时,关键部分只是这一部分代码)。其关键则是设置Adapter、request和response对象,需要注意的是此时的request和response是org.apache.coyote包下的,和我们平时见到的不是同一个。
1.1.3 Http11Processor
其部分关键源码如下:
public class Http11Processor extends AbstractProcessor {
private final AbstractHttp11Protocol<?> protocol;
private final Http11InputBuffer inputBuffer;
private final Http11OutputBuffer outputBuffer;
private final HttpParser httpParser;
public Http11Processor(AbstractHttp11Protocol<?> protocol,
Adapter adapter) {
super(adapter);
this.protocol = protocol;
httpParser = new HttpParser(protocol.getRelaxedPathChars(),
protocol.getRelaxedQueryChars());
inputBuffer = new Http11InputBuffer(request,
protocol.getMaxHttpHeaderSize(),
protocol.getRejectIllegalHeaderName(), httpParser);
request.setInputBuffer(inputBuffer);
outputBuffer = new Http11OutputBuffer(response,
protocol.getMaxHttpHeaderSize());
response.setOutputBuffer(outputBuffer);
inputBuffer.addFilter(new IdentityInputFilter(
protocol.getMaxSwallowSize()));
outputBuffer.addFilter(new IdentityOutputFilter());
inputBuffer.addFilter(new ChunkedInputFilter(protocol
.getMaxTrailerSize(),
protocol.getAllowedTrailerHeadersInternal(),
protocol.getMaxExtensionSize(),
protocol.getMaxSwallowSize()));
outputBuffer.addFilter(new ChunkedOutputFilter());
inputBuffer.addFilter(new VoidInputFilter());
outputBuffer.addFilter(new VoidOutputFilter());
inputBuffer.addFilter(new BufferedInputFilter());
outputBuffer.addFilter(new GzipOutputFilter());
pluggableFilterIndex = inputBuffer.getFilters().length;
}
@Override
public SocketState service(SocketWrapperBase<?> socketWrapper)
throws IOException {
// 先对参数进行初始化,略过
...
while (!getErrorState().isError() && keepAlive && !isAsync() &&
upgradeToken == null &&
sendfileState == SendfileState.DONE &&
!protocol.isPaused()) {
// 中间验证request、设置request和判断Upgrade的流程便略过
...
if (getErrorState().isIoAllowed()) {
try {
rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);
// 获得Adapter去调用service
// 这里的Adapter实则是CoyoteAdapter类型
getAdapter().service(request, response);
if(keepAlive && !getErrorState().isError() &&
!isAsync() &&
statusDropsConnection(response.getStatus())) {
setErrorState(ErrorState.CLOSE_CLEAN, null);
}
} catch (InterruptedIOException e) {
...
}
}
// 状态的判断略过
...
sendfileState = processSendfile(socketWrapper);
}
rp.setStage(org.apache.coyote.Constants.STAGE_ENDED);
// 状态返回略过
...
}
@Override
public final void recycle() {
getAdapter().checkRecycled(request, response);
super.recycle();
inputBuffer.recycle();
outputBuffer.recycle();
upgradeToken = null;
socketWrapper = null;
sendfileData = null;
sslSupport = null;
}
}
该类中一共只有三个方法需要留意:构造函数,service方法和recycle。构造函数确定了类中对象的具体类型,而recycle方法则是将类中的各个属性设置为最开始的状态。service方法在代码中进行了说明,其它流程都是对状态和结果的判断,最重要的便是调用adapter的service方法。
1.2 Adapter
终于到了Adapter来了,这个类的作用便是将Connector组件的类调用到Container类中,当然Container中的组件通信都是使用管道来通信的,因此Adapter实际上对接的是Connector和Pipeline。
其部分关键源码如下:
public class CoyoteAdapter implements Adapter {
private final Connector connector;
public CoyoteAdapter(Connector connector) {
super();
this.connector = connector;
}
@Override
public void service(org.apache.coyote.Request req,
org.apache.coyote.Response res)
throws Exception {
// 将org.apache.coyote包下的request和response转换成
// org.apache.catalina.connector包下继承HttpServletRequest类型
Request request = (Request) req.getNote(ADAPTER_NOTES);
Response response = (Response) res.getNote(ADAPTER_NOTES);
if (request == null) {
request = connector.createRequest();
request.setCoyoteRequest(req);
response = connector.createResponse();
response.setCoyoteResponse(res);
request.setResponse(response);
response.setRequest(request);
req.setNote(ADAPTER_NOTES, request);
res.setNote(ADAPTER_NOTES, response);
req.getParameters().setQueryStringCharset(
connector.getURICharset());
}
// 中间略过
...
try {
// 解析并设置Catalina核心属性和特定请求配置,如host、context、
// 参数、请求方式、允许的请求方式和版本等信息
// 当然,非常重要的信息就是根据请求路径来判断由哪个
// StandardWrapper处理这个请求也是在这里面完成的
postParseSuccess =
postParseRequest(req, request, res, response);
if (postParseSuccess) {
// 检查是否支持异步止回阀
request.setAsyncSupported(
connector.getService().getContainer()
.getPipeline().isAsyncSupported());
// 调用进Container中,这里是关键,由Connector部分调用进了
// Container,完成两者的适配
connector.getService().getContainer().getPipeline()
.getFirst().invoke(request, response);
}
...
} catch (IOException e) {
...
} finally {
...
}
}
}
可以看到,Adapter从名字便可以看出来这是个适配器,从其关键源码的实现可以看出来其适配了Connector和Container,使Connector能够成功的调用进Container。在这里面也完成了request和response的类型转换,将Connector组件中的转换成了Container中的。
1.3 StandardPipeline
各个容器都是使用StandardPipeline管道类来进行连通的,同时管道中又保存了Valve阈的关联关系,可以看到其关键部分源码:
public class StandardPipeline extends LifecycleBase implements Pipeline {
protected Container container = null;
protected Valve basic = null;
protected Valve first = null;
@Override
public Valve getFirst() {
if (first != null) {
return first;
}
return basic;
}
}
从其关键源码中便可以得知这个类只是一个中介类(主要负责连接的管道当然只负责连接对方,而不需要进行逻辑操作),保存了Container和处理管道对应的valve阈。
1.4 StandardEngineValve
Container的运行架构图便不再这里赘述,看过前面总体架构分析便能得知。其关键源码如下:
final class StandardEngineValve extends ValveBase {
protected Container container = null;
protected Valve next = null;
@Override
public final void invoke(Request request, Response response)
throws IOException, ServletException {
Host host = request.getHost();
if (host == null) {
return;
}
if (request.isAsyncSupported()) {
request.setAsyncSupported(host.getPipeline()
.isAsyncSupported());
}
host.getPipeline().getFirst().invoke(request, response);
}
}
该类实际上只对host进行了某些判断,并直接获得host调用其管道进行下个容器的流程。
1.5 StandardHostValve
其关键源码如下:
final class StandardHostValve extends ValveBase {
protected Container container = null;
protected Valve next = null;
@Override
public final void invoke(Request request, Response response)
throws IOException, ServletException {
Context context = request.getContext();
if (context == null) {
return;
}
if (request.isAsyncSupported()) {
request.setAsyncSupported(context.getPipeline()
.isAsyncSupported());
}
boolean asyncAtStart = request.isAsync();
try {
context.bind(Globals.IS_SECURITY_ENABLED, MY_CLASSLOADER);
if (!asyncAtStart &&
!context.fireRequestInitEvent(request.getRequest())) {
return;
}
try {
if (!response.isErrorReportRequired()) {
// 继续执行管道连接的下个Container方法
context.getPipeline().getFirst()
.invoke(request, response);
}
} catch (Throwable t) {
...
}
// 后置处理
...
} finally {
if (ACCESS_SESSION) {
request.getSession(false);
}
context.unbind(Globals.IS_SECURITY_ENABLED, MY_CLASSLOADER);
}
}
}
该阈和上一个差不了多少,也只是对request和response进行一些状态处理。
1.6 StandardContextValve
其关键源码如下:
final class StandardContextValve extends ValveBase {
protected Container container = null;
protected Valve next = null;
@Override
public final void invoke(Request request, Response response)
throws IOException, ServletException {
// 如果不允许直接访问WEB-INF或META-INF下的资源
MessageBytes requestPathMB = request.getRequestPathMB();
if ((requestPathMB.startsWithIgnoreCase("/META-INF/", 0))
|| (requestPathMB.equalsIgnoreCase("/META-INF"))
|| (requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0))
|| (requestPathMB.equalsIgnoreCase("/WEB-INF"))) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
Wrapper wrapper = request.getWrapper();
if (wrapper == null || wrapper.isUnavailable()) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
try {
// 确认请求
response.sendAcknowledgement();
} catch (IOException ioe) {
...
}
if (request.isAsyncSupported()) {
request.setAsyncSupported(wrapper.getPipeline()
.isAsyncSupported());
}
wrapper.getPipeline().getFirst().invoke(request, response);
}
}
执行一些判断是否有权限访问WEB-INF或者META-INF文件夹下的资源,确认请求等操作。接着往下调用Wrapper对应管道的阈。
1.7 StandardWrapperValve
其关键源码如下:
final class StandardWrapperValve extends ValveBase {
protected Container container = null;
protected Valve next = null;
@Override
public final void invoke(Request request, Response response)
throws IOException, ServletException {
// 初始化本地方法可能会用到的参数
boolean unavailable = false;
Throwable throwable = null;
requestCount.incrementAndGet();
StandardWrapper wrapper = (StandardWrapper) getContainer();
Servlet servlet = null;
Context context = (Context) wrapper.getParent();
// 检查标记为不可用的应用程序
if (!context.getState().isAvailable()) {
...
}
// servlet被标记为不可用
if (!unavailable && wrapper.isUnavailable()) {
...
}
// 分配一个servlet实例来处理请求
try {
if (!unavailable) {
// allocate实际上会调用StandardWrapper的initServlet方法
// 去实例化一个Servlet,并调用Servlet的init方法。
servlet = wrapper.allocate();
}
} catch (Throwable e) {
...
}
...
// 为此请求创建过滤器链
ApplicationFilterChain filterChain = ApplicationFilterFactory
.createFilterChain(request, wrapper, servlet);
// 为此请求调用过滤器链
Container container = this.container;
try {
if ((servlet != null) && (filterChain != null)) {
if (context.getSwallowOutput()) {
try {
SystemLogHandler.startCapture();
if (request.isAsyncDispatching()) {
request.getAsyncContextInternal()
.doInternalDispatch();
} else {
filterChain.doFilter(request.getRequest(),
response.getResponse());
}
} finally {
String log = SystemLogHandler.stopCapture();
if (log != null && log.length() > 0) {
context.getLogger().info(log);
}
}
} else {
if (request.isAsyncDispatching()) {
request.getAsyncContextInternal()
.doInternalDispatch();
} else {
filterChain.doFilter
(request.getRequest(), response.getResponse());
}
}
}
} catch (Throwable e) {
...
} finally {
...
}
}
}
可以看到这个阈中除了对request的请求进行校验外,还在其中初始化了StaddardWrapper封装的Servlet,并且从request中获得过滤器链并初始化,最后调用过滤器链。
1.8 ApplicationFilterChain
Servlet的过滤器链实在太多,因此我们只挑其中统筹兼顾的一个来进行分析。其关键源码如下:
public final class ApplicationFilterChain implements FilterChain {
private static final ThreadLocal<ServletRequest> lastServicedRequest;
private static final ThreadLocal<ServletResponse> lastServicedResponse;
private Servlet servlet = null;
// 当前读取的过滤器位置
private int pos = 0;
// 过滤器数量
private int n = 0;
@Override
public void doFilter(ServletRequest request, ServletResponse response)
throws IOException, ServletException {
if( Globals.IS_SECURITY_ENABLED ) {
// 可以忽略
...
} else {
internalDoFilter(request,response);
}
}
private void internalDoFilter(ServletRequest request,
ServletResponse response)
throws IOException, ServletException {
//
if (pos < n) {
// 获得过滤器链中的过滤器
ApplicationFilterConfig filterConfig = filters[pos++];
try {
Filter filter = filterConfig.getFilter();
// 忽略
...
if( Globals.IS_SECURITY_ENABLED ) {
// 忽略
...
} else {
// 调用过滤器链中的过滤器
filter.doFilter(request, response, this);
}
} catch (Throwable e) {
...
}
return;
}
// 到这里代表前面的过滤器已经全部执行完毕,是时候该执行Servlet了
try {
if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
lastServicedRequest.set(request);
lastServicedResponse.set(response);
}
if (request.isAsyncSupported() && !servletSupportsAsync) {
request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR,
Boolean.FALSE);
}
// Use potentially wrapped request from this point
if ((request instanceof HttpServletRequest) &&
(response instanceof HttpServletResponse) &&
Globals.IS_SECURITY_ENABLED ) {
// 忽略
...
} else {
// 执行Servlet的service方法
servlet.service(request, response);
}
} catch (Throwable e) {
...
} finally {
if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
lastServicedRequest.set(null);
lastServicedResponse.set(null);
}
}
}
}
暂且把这个调用其它过滤器的类交模板过滤器,在这个过滤器关键方法中可以分成两部分,一部分是前面的调用各个过滤器逻辑,一个则是后续调用Servlet的逻辑。调用到过滤器和servlet后便无需多言了。