您的位置:首页 > 运维架构 > Tomcat

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

2014-01-23 14:13 543 查看
请求在Tomcat中传到了CoyoteAdapter的#service()方法中后,就要准备进入Pipeline了,如#service()方法中的这句所示:

connector.getContainer().getPipeline().getFirst().invoke(request, response);

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

Java代码



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()方法,源代码如下所示:

Java代码



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,源代码如下:

Java代码



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)。

Java代码



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方式以后再详细看。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: