Tomcat请求处理(五) -- 请求在容器间的流动

请求在Tomcat中传到了CoyoteAdapter的#service()方法中后,就要准备进入Pipeline了,如#service()方法中的这句所示:
connector.getContainer().getPipeline().getFirst().invoke(request, response);

这里的Container是Engine,然后得到它的Pipeline对象,然后得到他的第一个Valve,如果没有配置的话第一个Valve就是Basic的了,这里就是org.apache.catalina.core.StandardEngineValve,最后调用了它的#invoke()方法,源代码如下所示:

	public final void invoke(Request request, Response response) throws IOException,
ServletException {

// 获得Host对象
Host host = request.getHost();
if (host == null) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST, sm.getString(
"standardEngine.noHost", request.getServerName()));
return;
}

// 将请求传递给Host
host.getPipeline().getFirst().invoke(request, response);

}


这个Valve并没做什么实质性的东西,只是将请求继续传递,当然可以定义自己的Valve实现一些特殊的行为。
还是来继续请求的处理过程,和上边Engine的情况类似,请求这次到了org.apache.catalina.core.StandardHostValve的#invoke()方法,源代码如下所示:

	public final void invoke(Request request, Response response) throws IOException,
ServletException {

// 获得Context对象
Context context = request.getContext();
if (context == null) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, sm
.getString("standardHost.noContext"));
return;
}

// 如果没有设置Loader,那么设置为context自己的ClassLoader
if (context.getLoader() != null) {
Thread.currentThread().setContextClassLoader(context.getLoader().getClassLoader());
}

// 将请求通过Pipeline给Context
context.getPipeline().getFirst().invoke(request, response);

if (Globals.STRICT_SERVLET_COMPLIANCE) {
request.getSession(false);
}

// 处理错误页
response.setSuspended(false);

Throwable t = (Throwable) request.getAttribute(Globals.EXCEPTION_ATTR);

if (t != null) {
throwable(request, response, t);
} else {
status(request, response);
}

// 恢复ClassLoader
Thread.currentThread().setContextClassLoader(StandardHostValve.class.getClassLoader());

}

不出意外的,请求下边就到了org.apache.catalina.core.StandardContextValve,源代码如下:

	public final void invoke(Request request, Response response) throws IOException,
ServletException {

// 不允许请求访问META-INF和WEB-INF文件夹下的内容。
MessageBytes requestPathMB = request.getRequestPathMB();
if ((requestPathMB.startsWithIgnoreCase("/META-INF/", 0))
|| (requestPathMB.equalsIgnoreCase("/META-INF"))
|| (requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0))
|| (requestPathMB.equalsIgnoreCase("/WEB-INF"))) {
notFound(response);
return;
}

// 如果系统正在重新载入中,那么暂停请求。
boolean reloaded = false;
while (context.getPaused()) {
reloaded = true;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
;
}
}

// 如果正在重载,停止老的WebappClassLoader并创建一个新的
if (reloaded && context.getLoader() != null && context.getLoader().getClassLoader() != null) {
Thread.currentThread().setContextClassLoader(context.getLoader().getClassLoader());
}

// 获得Wrapper对象
Wrapper wrapper = request.getWrapper();
if (wrapper == null) {
notFound(response);
return;
} else if (wrapper.isUnavailable()) {
wrapper = (Wrapper) container.findChild(wrapper.getName());
if (wrapper == null) {
notFound(response);
return;
}
}

// 获得Listener列表
Object instances[] = context.getApplicationEventListeners();

ServletRequestEvent event = null;

if ((instances != null) && (instances.length > 0)) {
event = new ServletRequestEvent(((StandardContext) container).getServletContext(),
request.getRequest());

for (int i = 0; i < instances.length; i++) {
if (instances[i] == null)
continue;
if (!(instances[i] instanceof ServletRequestListener))
continue;
ServletRequestListener listener = (ServletRequestListener) instances[i];
try {
// 调用请求初始化事件
listener.requestInitialized(event);
} catch (Throwable t) {
container.getLogger().error(
sm.getString("standardContext.requestListener.requestInit",
instances[i].getClass().getName()), t);
ServletRequest sreq = request.getRequest();
sreq.setAttribute(Globals.EXCEPTION_ATTR, t);
return;
}
}
}

// 调用Wrapper的Valve
wrapper.getPipeline().getFirst().invoke(request, response);

if ((instances != null) && (instances.length > 0)) {
for (int i = 0; i < instances.length; i++) {
if (instances[i] == null)
continue;
if (!(instances[i] instanceof ServletRequestListener))
continue;
ServletRequestListener listener = (ServletRequestListener) instances[i];
try {
// 调用请求结束事件
listener.requestDestroyed(event);
} catch (Throwable t) {
container.getLogger().error(
sm.getString("standardContext.requestListener.requestDestroy",
instances[i].getClass().getName()), t);
ServletRequest sreq = request.getRequest();
sreq.setAttribute(Globals.EXCEPTION_ATTR, t);
}
}
}

}

这个Valve重要的是包括了对Listener的调用,最后来看一下Wrapper的Valve调用(org.apache.catalina.core.StandardWrapperValve)。

public final void invoke(Request request, Response response) throws IOException,
ServletException {

boolean unavailable = false;
Throwable throwable = null;

long t1 = System.currentTimeMillis();
requestCount++;
// 获得Wrapper所关联的对象
StandardWrapper wrapper = (StandardWrapper) getContainer();
// Servlet对象
Servlet servlet = null;
// 获得Context对象
Context context = (Context) wrapper.getParent();

if (!context.getAvailable()) {
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm
.getString("standardContext.isUnavailable"));
unavailable = true;
}

if (!unavailable && wrapper.isUnavailable()) {
container.getLogger().info(
sm.getString("standardWrapper.isUnavailable", wrapper.getName()));
long available = wrapper.getAvailable();
if ((available > 0L) && (available < Long.MAX_VALUE)) {
response.setDateHeader("Retry-After", available);
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString(
"standardWrapper.isUnavailable", wrapper.getName()));
} else if (available == Long.MAX_VALUE) {
response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString(
"standardWrapper.notFound", wrapper.getName()));
}
unavailable = true;
}

try {
if (!unavailable) {
// 分配一个Servelt实例
servlet = wrapper.allocate();
}
} catch (UnavailableException e) {
container.getLogger().error(
sm.getString("standardWrapper.allocateException", wrapper.getName()), e);
long available = wrapper.getAvailable();
if ((available > 0L) && (available < Long.MAX_VALUE)) {
response.setDateHeader("Retry-After", available);
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString(
"standardWrapper.isUnavailable", wrapper.getName()));
} else if (available == Long.MAX_VALUE) {
response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString(
"standardWrapper.notFound", wrapper.getName()));
}
} catch (ServletException e) {
container.getLogger().error(
sm.getString("standardWrapper.allocateException", wrapper.getName()),
StandardWrapper.getRootCause(e));
throwable = e;
exception(request, response, e);
servlet = null;
} catch (Throwable e) {
container.getLogger().error(
sm.getString("standardWrapper.allocateException", wrapper.getName()), e);
throwable = e;
exception(request, response, e);
servlet = null;
}

boolean comet = false;
if (servlet instanceof CometProcessor
&& request.getAttribute("org.apache.tomcat.comet.support") == Boolean.TRUE) {
comet = true;
request.setComet(true);
}

// 告知Request已经收到
try {
response.sendAcknowledgement();
} catch (IOException e) {
request.removeAttribute(Globals.JSP_FILE_ATTR);
container.getLogger().warn(
sm.getString("standardWrapper.acknowledgeException", wrapper.getName()), e);
throwable = e;
exception(request, response, e);
} catch (Throwable e) {
container.getLogger().error(
sm.getString("standardWrapper.acknowledgeException", wrapper.getName()), e);
throwable = e;
exception(request, response, e);
servlet = null;
}
MessageBytes requestPathMB = null;
if (request != null) {
requestPathMB = request.getRequestPathMB();
}

request.setAttribute(ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
ApplicationFilterFactory.REQUEST_INTEGER);
request.setAttribute(ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR, requestPathMB);
// 创建FilterChain
ApplicationFilterFactory factory = ApplicationFilterFactory.getInstance();
ApplicationFilterChain filterChain = factory.createFilterChain(request, wrapper, servlet);

request.setComet(false);

try {
// web.xml中的<jsp-file>标签
String jspFile = wrapper.getJspFile();
if (jspFile != null)
request.setAttribute(Globals.JSP_FILE_ATTR, jspFile);
else
request.removeAttribute(Globals.JSP_FILE_ATTR);

// 调用Filter
if ((servlet != null) && (filterChain != null)) {
if (context.getSwallowOutput()) {
try {
SystemLogHandler.startCapture();
if (comet) {
filterChain.doFilterEvent(request.getEvent());
request.setComet(true);
} else {
filterChain.doFilter(request.getRequest(), response.getResponse());
}
} finally {
String log = SystemLogHandler.stopCapture();
if (log != null && log.length() > 0) {
context.getLogger().info(log);
}
}
} else {
if (comet) {
request.setComet(true);
filterChain.doFilterEvent(request.getEvent());
} else {
filterChain.doFilter(request.getRequest(), response.getResponse());
}
}

}
request.removeAttribute(Globals.JSP_FILE_ATTR);
} catch (ClientAbortException e) {
request.removeAttribute(Globals.JSP_FILE_ATTR);
throwable = e;
exception(request, response, e);
} catch (IOException e) {
request.removeAttribute(Globals.JSP_FILE_ATTR);
container.getLogger().error(
sm.getString("standardWrapper.serviceException", wrapper.getName()), e);
throwable = e;
exception(request, response, e);
} catch (UnavailableException e) {
request.removeAttribute(Globals.JSP_FILE_ATTR);
container.getLogger().error(
sm.getString("standardWrapper.serviceException", wrapper.getName()), e);

wrapper.unavailable(e);
long available = wrapper.getAvailable();
if ((available > 0L) && (available < Long.MAX_VALUE)) {
response.setDateHeader("Retry-After", available);
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE, sm.getString(
"standardWrapper.isUnavailable", wrapper.getName()));
} else if (available == Long.MAX_VALUE) {
response.sendError(HttpServletResponse.SC_NOT_FOUND, sm.getString(
"standardWrapper.notFound", wrapper.getName()));
}

} catch (ServletException e) {
request.removeAttribute(Globals.JSP_FILE_ATTR);
Throwable rootCause = StandardWrapper.getRootCause(e);
if (!(rootCause instanceof ClientAbortException)) {
container.getLogger().error(
sm.getString("standardWrapper.serviceException", wrapper.getName()),
rootCause);
}
throwable = e;
exception(request, response, e);
} catch (Throwable e) {
request.removeAttribute(Globals.JSP_FILE_ATTR);
container.getLogger().error(
sm.getString("standardWrapper.serviceException", wrapper.getName()), e);
throwable = e;
exception(request, response, e);
}

if (filterChain != null) {
if (request.isComet()) {
filterChain.reuse();
} else {
filterChain.release();
}
}

// 释放Servlet对象
try {
if (servlet != null) {
wrapper.deallocate(servlet);
}
} catch (Throwable e) {
container.getLogger().error(
sm.getString("standardWrapper.deallocateException", wrapper.getName()), e);
if (throwable == null) {
throwable = e;
exception(request, response, e);
}
}

try {
if ((servlet != null) && (wrapper.getAvailable() == Long.MAX_VALUE)) {
wrapper.unload();
}
} catch (Throwable e) {
container.getLogger().error(
sm.getString("standardWrapper.unloadException", wrapper.getName()), e);
if (throwable == null) {
throwable = e;
exception(request, response, e);
}
}
long t2 = System.currentTimeMillis();

long time = t2 - t1;
processingTime += time;
if (time > maxTime)
maxTime = time;
if (time < minTime)
minTime = time;

}

这段代码的关键点是Servlet实例的构建(servlet = wrapper.allocate();)和Filter Chain的调用(filterChain.doFilter(request.getRequest(), response.getResponse());),具体的还要进入方法内部去仔细看一下。comet方式以后再详细看。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值