请求在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方式以后再详细看.