[Tomcat6.0源码]请求的处理四Pipeline、Valve、FilterChain
2012-09-27 11:29
375 查看
CoyoteAdapter.service()中调用postParseRequest对请求进行封装,匹配相关的Host、Context、Wrapper等。接着执行:
程序将按Connector(N-1)Engine(1-N)Host(1-N)Context(1-N)Wrapper这种顺序执行下去。
connector.getContainer()返回StandardEngine对象,这在Connector实例化的时候赋值的。
connector.getContainer().getPipeline()既是StandardEngine.getPipeline(),StandardEngine继承ContainerBase,ContainerBase在属性中创建StandardPipeline对象。
传入的参数是StandardEngine对象,将保存在StandardPipeline.container属性中。
connector.getContainer().getPipeline().getFirst()既是执行StandardPipeline.getFirst():
取不到first就取basic,这个是什么时候赋值的?StandardEngine的构造方法:
那么StandardPipeline.getFirst()返回的就是StandardEngineValve()对象。而
执行的就是StandardEngineValve.invoke():
request.getHost()是在CoyoteAdapter.postParseRequest()解析request的时候设置好的。host.getPipeline().getFirst().invoke(request, response);调用过程和前面的类似,既是执行StandardHostValve.invoke():
同样context.getPipeline().getFirst().invoke(request, response);既是执行StandardContextValve.invoke():
wrapper.getPipeline().getFirst().invoke(request, response);执行StandardWrapperValve.invoke(),经过设置参数后,需要取出StandardWrapper对象中相关联的Servlet:
wrapper.allocate() 返回的是StandardWrapper.instance属性。那这个instance是什么时候赋值的?
回到StandardWrapper的上一级组件StandardContext启动时候,StandardContext.start():
findChildren()返回注册到Context.children中的StandardWrapper,这种使用HashMap的方式到是可以看看:
StandardContext.loadOnStartup():
wrapper.load()既是StandardWrapper.load():
调用loadServlet()方法为StandardWrapper的instance属性创建一个Servlet:
classClass来自web.xml文件中的:
经过WebRuleSet的规则解析:
将对classClass的来源变量StandardWrapper.servletClass进行赋值。
StandardWrapperValve.invoke()中的servlet已经查到源头了,这个servlet就是最终处理业务的servlet。我们知道执行servlet前会一层层的先执行过滤器,越来越接近水面。
ApplicationFilterFactory.createFilterChain():
先new出一个filterChain,再filterChain.setServlet(servlet);再取过滤器:
Context实例化的时候,ContextConfig.applicationWebConfig()解析WebRuleSet类中配置规则,实例化Filter添加到StandardContext的filterMap中。
先匹配符合路径的过滤器,再匹配符合类名的过滤器,将添加到filterChain.addFilter(filterConfig);
接下来就是执行过滤器了:
ApplicationFilterChain.doFilter():
ApplicationFilterChain.internalDoFilter():
filter.doFilter(request, response, this);当filter数组中还有过滤器的时候,就创建过滤器,并调用它:
这个就到了我们平时写的filter了,filter实现Filter接口,其doFilter中必须有一行,filterChain.doFilter(request, response);这个filterChain就是上边调用的this。
这样的话,只要没有执行完所有的过滤器,就会不断的创建过滤器,一直调用执行。
过滤器执行完后,会执行:
我们编写的servlet一般继承至HttpServlet,servlet.service()既是执行HttpServlet.service():
判断请求的方法,到了我们熟悉的doPost()、doGet()了,这两个方法在业务Servlet中我们一般会重写,处理业务。
connector.getContainer().getPipeline().getFirst().invoke(request, response);
程序将按Connector(N-1)Engine(1-N)Host(1-N)Context(1-N)Wrapper这种顺序执行下去。
connector.getContainer()返回StandardEngine对象,这在Connector实例化的时候赋值的。
connector.getContainer().getPipeline()既是StandardEngine.getPipeline(),StandardEngine继承ContainerBase,ContainerBase在属性中创建StandardPipeline对象。
传入的参数是StandardEngine对象,将保存在StandardPipeline.container属性中。
protected Pipeline pipeline = new StandardPipeline(this);
connector.getContainer().getPipeline().getFirst()既是执行StandardPipeline.getFirst():
public Valve getFirst() { if (first != null) { return first; } else { return basic; } }
取不到first就取basic,这个是什么时候赋值的?StandardEngine的构造方法:
/** * Create a new StandardEngine component with the default basic Valve. */ public StandardEngine() { super(); pipeline.setBasic(new StandardEngineValve()); /* Set the jmvRoute using the system property jvmRoute */ try { setJvmRoute(System.getProperty("jvmRoute")); } catch(Exception ex) { } // By default, the engine will hold the reloading thread backgroundProcessorDelay = 10; }
那么StandardPipeline.getFirst()返回的就是StandardEngineValve()对象。而
connector.getContainer().getPipeline().getFirst().invoke(request, response);
执行的就是StandardEngineValve.invoke():
public final void invoke(Request request, Response response) throws IOException, ServletException { // Select the Host to be used for this Request Host host = request.getHost(); if (host == null) { response.sendError (HttpServletResponse.SC_BAD_REQUEST, sm.getString("standardEngine.noHost", request.getServerName())); return; } // Ask this Host to process this request host.getPipeline().getFirst().invoke(request, response); }
request.getHost()是在CoyoteAdapter.postParseRequest()解析request的时候设置好的。host.getPipeline().getFirst().invoke(request, response);调用过程和前面的类似,既是执行StandardHostValve.invoke():
public final void invoke(Request request, Response response) throws IOException, ServletException { // Select the Context to be used for this Request Context context = request.getContext(); if (context == null) { response.sendError (HttpServletResponse.SC_INTERNAL_SERVER_ERROR, sm.getString("standardHost.noContext")); return; } // Bind the context CL to the current thread if( context.getLoader() != null ) { // Not started - it should check for availability first // This should eventually move to Engine, it's generic. Thread.currentThread().setContextClassLoader (context.getLoader().getClassLoader()); } // Ask this Context to process this request context.getPipeline().getFirst().invoke(request, response); // Access a session (if present) to update last accessed time, based on a // strict interpretation of the specification if (Globals.STRICT_SERVLET_COMPLIANCE) { request.getSession(false); } // Error page processing response.setSuspended(false); Throwable t = (Throwable) request.getAttribute(Globals.EXCEPTION_ATTR); if (t != null) { throwable(request, response, t); } else { status(request, response); } // Restore the context classloader Thread.currentThread().setContextClassLoader (StandardHostValve.class.getClassLoader()); }
同样context.getPipeline().getFirst().invoke(request, response);既是执行StandardContextValve.invoke():
public final void invoke(Request request, Response response) throws IOException, ServletException { // Disallow any direct access to resources under WEB-INF or 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"))) { notFound(response); return; } // Wait if we are reloading boolean reloaded = false; while (context.getPaused()) { reloaded = true; try { Thread.sleep(1000); } catch (InterruptedException e) { ; } } // Reloading will have stopped the old webappclassloader and // created a new one if (reloaded && context.getLoader() != null && context.getLoader().getClassLoader() != null) { Thread.currentThread().setContextClassLoader( context.getLoader().getClassLoader()); } // Select the Wrapper to be used for this Request Wrapper wrapper = request.getWrapper(); if (wrapper == null) { notFound(response); return; } else if (wrapper.isUnavailable()) { // May be as a result of a reload, try and find the new wrapper wrapper = (Wrapper) container.findChild(wrapper.getName()); if (wrapper == null) { notFound(response); return; } } // Normal request processing Object instances[] = context.getApplicationEventListeners(); ServletRequestEvent event = null; if ((instances != null) && (instances.length > 0)) { event = new ServletRequestEvent (((StandardContext) container).getServletContext(), request.getRequest()); // create pre-service event 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.getPipeline().getFirst().invoke(request, response); if ((instances !=null ) && (instances.length > 0)) { // create post-service event 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); } } } }
wrapper.getPipeline().getFirst().invoke(request, response);执行StandardWrapperValve.invoke(),经过设置参数后,需要取出StandardWrapper对象中相关联的Servlet:
// Allocate a servlet instance to process this request try { if (!unavailable) { servlet = wrapper.allocate(); } } catch (UnavailableException e) {......}
wrapper.allocate() 返回的是StandardWrapper.instance属性。那这个instance是什么时候赋值的?
回到StandardWrapper的上一级组件StandardContext启动时候,StandardContext.start():
// Load and initialize all "load on startup" servlets if (ok) { loadOnStartup(findChildren()); }
findChildren()返回注册到Context.children中的StandardWrapper,这种使用HashMap的方式到是可以看看:
public Container[] findChildren() { synchronized (children) { Container results[] = new Container[children.size()]; return ((Container[]) children.values().toArray(results)); } }
StandardContext.loadOnStartup():
/** * Load and initialize all servlets marked "load on startup" in the * web application deployment descriptor. * * @param children Array of wrappers for all currently defined * servlets (including those not declared load on startup) */ public void loadOnStartup(Container children[]) { // Collect "load on startup" servlets that need to be initialized TreeMap map = new TreeMap(); for (int i = 0; i < children.length; i++) { Wrapper wrapper = (Wrapper) children[i]; int loadOnStartup = wrapper.getLoadOnStartup(); if (loadOnStartup < 0) continue; Integer key = Integer.valueOf(loadOnStartup); ArrayList list = (ArrayList) map.get(key); if (list == null) { list = new ArrayList(); map.put(key, list); } list.add(wrapper); } // Load the collected "load on startup" servlets Iterator keys = map.keySet().iterator(); while (keys.hasNext()) { Integer key = (Integer) keys.next(); ArrayList list = (ArrayList) map.get(key); Iterator wrappers = list.iterator(); while (wrappers.hasNext()) { Wrapper wrapper = (Wrapper) wrappers.next(); try { wrapper.load(); } catch (ServletException e) { getLogger().error(sm.getString("standardWrapper.loadException", getName()), StandardWrapper.getRootCause(e)); // NOTE: load errors (including a servlet that throws // UnavailableException from tht init() method) are NOT // fatal to application startup } } } }
wrapper.load()既是StandardWrapper.load():
public synchronized void load() throws ServletException { instance = loadServlet(); }
调用loadServlet()方法为StandardWrapper的instance属性创建一个Servlet:
servlet = (Servlet) classClass.newInstance();
classClass来自web.xml文件中的:
<servlet> <servlet-name>helloServlet</servlet-name> <servlet-class>HelloServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>helloServlet</servlet-name> <url-pattern>/helloServlet</url-pattern> </servlet-mapping>
经过WebRuleSet的规则解析:
digester.addCallMethod(prefix + "web-app/servlet/servlet-class", "setServletClass", 0); digester.addCallMethod(prefix + "web-app/servlet/servlet-name", "setName", 0);
将对classClass的来源变量StandardWrapper.servletClass进行赋值。
StandardWrapperValve.invoke()中的servlet已经查到源头了,这个servlet就是最终处理业务的servlet。我们知道执行servlet前会一层层的先执行过滤器,越来越接近水面。
// Create the filter chain for this request ApplicationFilterFactory factory = ApplicationFilterFactory.getInstance(); ApplicationFilterChain filterChain = factory.createFilterChain(request, wrapper, servlet);
ApplicationFilterFactory.createFilterChain():
/** * Construct and return a FilterChain implementation that will wrap the * execution of the specified servlet instance. If we should not execute * a filter chain at all, return <code>null</code>. * * @param request The servlet request we are processing * @param servlet The servlet instance to be wrapped */ public ApplicationFilterChain createFilterChain (ServletRequest request, Wrapper wrapper, Servlet servlet) { // get the dispatcher type int dispatcher = -1; if (request.getAttribute(DISPATCHER_TYPE_ATTR) != null) { Integer dispatcherInt = (Integer) request.getAttribute(DISPATCHER_TYPE_ATTR); dispatcher = dispatcherInt.intValue(); } String requestPath = null; Object attribute = request.getAttribute(DISPATCHER_REQUEST_PATH_ATTR); if (attribute != null){ requestPath = attribute.toString(); } HttpServletRequest hreq = null; if (request instanceof HttpServletRequest) hreq = (HttpServletRequest)request; // If there is no servlet to execute, return null if (servlet == null) return (null); boolean comet = false; // Create and initialize a filter chain object ApplicationFilterChain filterChain = null; if (request instanceof Request) { Request req = (Request) request; comet = req.isComet(); if (Globals.IS_SECURITY_ENABLED) { // Security: Do not recycle filterChain = new ApplicationFilterChain(); if (comet) { req.setFilterChain(filterChain); } } else { filterChain = (ApplicationFilterChain) req.getFilterChain(); if (filterChain == null) { filterChain = new ApplicationFilterChain(); req.setFilterChain(filterChain); } } } else { // Request dispatcher in use filterChain = new ApplicationFilterChain(); } filterChain.setServlet(servlet); filterChain.setSupport (((StandardWrapper)wrapper).getInstanceSupport()); // Acquire the filter mappings for this Context StandardContext context = (StandardContext) wrapper.getParent(); FilterMap filterMaps[] = context.findFilterMaps(); // If there are no filter mappings, we are done if ((filterMaps == null) || (filterMaps.length == 0)) return (filterChain); // Acquire the information we will need to match filter mappings String servletName = wrapper.getName(); // Add the relevant path-mapped filters to this filter chain for (int i = 0; i < filterMaps.length; i++) { if (!matchDispatcher(filterMaps[i] ,dispatcher)) { continue; } if (!matchFiltersURL(filterMaps[i], requestPath)) continue; ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) context.findFilterConfig(filterMaps[i].getFilterName()); if (filterConfig == null) { ; // FIXME - log configuration problem continue; } boolean isCometFilter = false; if (comet) { try { isCometFilter = filterConfig.getFilter() instanceof CometFilter; } catch (Exception e) { // Note: The try catch is there because getFilter has a lot of // declared exceptions. However, the filter is allocated much // earlier } if (isCometFilter) { filterChain.addFilter(filterConfig); } } else { filterChain.addFilter(filterConfig); } } // Add filters that match on servlet name second for (int i = 0; i < filterMaps.length; i++) { if (!matchDispatcher(filterMaps[i] ,dispatcher)) { continue; } if (!matchFiltersServlet(filterMaps[i], servletName)) continue; ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) context.findFilterConfig(filterMaps[i].getFilterName()); if (filterConfig == null) { ; // FIXME - log configuration problem continue; } boolean isCometFilter = false; if (comet) { try { isCometFilter = filterConfig.getFilter() instanceof CometFilter; } catch (Exception e) { // Note: The try catch is there because getFilter has a lot of // declared exceptions. However, the filter is allocated much // earlier } if (isCometFilter) { filterChain.addFilter(filterConfig); } } else { filterChain.addFilter(filterConfig); } } // Return the completed filter chain return (filterChain); }
先new出一个filterChain,再filterChain.setServlet(servlet);再取过滤器:
// Acquire the filter mappings for this Context StandardContext context = (StandardContext) wrapper.getParent(); FilterMap filterMaps[] = context.findFilterMaps();
Context实例化的时候,ContextConfig.applicationWebConfig()解析WebRuleSet类中配置规则,实例化Filter添加到StandardContext的filterMap中。
digester.addObjectCreate(prefix + "web-app/filter-mapping", "org.apache.catalina.deploy.FilterMap"); digester.addSetNext(prefix + "web-app/filter-mapping", "addFilterMap", "org.apache.catalina.deploy.FilterMap");
先匹配符合路径的过滤器,再匹配符合类名的过滤器,将添加到filterChain.addFilter(filterConfig);
接下来就是执行过滤器了:
filterChain.doFilter (request.getRequest(), response.getResponse());
ApplicationFilterChain.doFilter():
public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { if( Globals.IS_SECURITY_ENABLED ) { final ServletRequest req = request; final ServletResponse res = response; try { java.security.AccessController.doPrivileged( new java.security.PrivilegedExceptionAction() { public Object run() throws ServletException, IOException { internalDoFilter(req,res); return null; } } ); } catch( PrivilegedActionException pe) { Exception e = pe.getException(); if (e instanceof ServletException) throw (ServletException) e; else if (e instanceof IOException) throw (IOException) e; else if (e instanceof RuntimeException) throw (RuntimeException) e; else throw new ServletException(e.getMessage(), e); } } else { internalDoFilter(request,response); } }
ApplicationFilterChain.internalDoFilter():
private void internalDoFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { // Call the next filter if there is one if (pos < n) { ApplicationFilterConfig filterConfig = filters[pos++]; Filter filter = null; try { filter = filterConfig.getFilter(); support.fireInstanceEvent(InstanceEvent.BEFORE_FILTER_EVENT, filter, request, response); if( Globals.IS_SECURITY_ENABLED ) { final ServletRequest req = request; final ServletResponse res = response; Principal principal = ((HttpServletRequest) req).getUserPrincipal(); Object[] args = new Object[]{req, res, this}; SecurityUtil.doAsPrivilege ("doFilter", filter, classType, args, principal); args = null; } else { filter.doFilter(request, response, this); } support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request, response); } catch (IOException e) { if (filter != null) support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request, response, e); throw e; } catch (ServletException e) { if (filter != null) support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request, response, e); throw e; } catch (RuntimeException e) { if (filter != null) support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request, response, e); throw e; } catch (Throwable e) { if (filter != null) support.fireInstanceEvent(InstanceEvent.AFTER_FILTER_EVENT, filter, request, response, e); throw new ServletException (sm.getString("filterChain.filter"), e); } return; } // We fell off the end of the chain -- call the servlet instance try { if (Globals.STRICT_SERVLET_COMPLIANCE) { lastServicedRequest.set(request); lastServicedResponse.set(response); } support.fireInstanceEvent(InstanceEvent.BEFORE_SERVICE_EVENT, servlet, request, response); if ((request instanceof HttpServletRequest) && (response instanceof HttpServletResponse)) { if( Globals.IS_SECURITY_ENABLED ) { final ServletRequest req = request; final ServletResponse res = response; Principal principal = ((HttpServletRequest) req).getUserPrincipal(); Object[] args = new Object[]{req, res}; SecurityUtil.doAsPrivilege("service", servlet, classTypeUsedInService, args, principal); args = null; } else { servlet.service((HttpServletRequest) request, (HttpServletResponse) response); } } else { servlet.service(request, response); } support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response); } catch (IOException e) { support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response, e); throw e; } catch (ServletException e) { support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response, e); throw e; } catch (RuntimeException e) { support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response, e); throw e; } catch (Throwable e) { support.fireInstanceEvent(InstanceEvent.AFTER_SERVICE_EVENT, servlet, request, response, e); throw new ServletException (sm.getString("filterChain.servlet"), e); } finally { if (Globals.STRICT_SERVLET_COMPLIANCE) { lastServicedRequest.set(null); lastServicedResponse.set(null); } } }
filter.doFilter(request, response, this);当filter数组中还有过滤器的时候,就创建过滤器,并调用它:
filter.doFilter(request, response, this);
这个就到了我们平时写的filter了,filter实现Filter接口,其doFilter中必须有一行,filterChain.doFilter(request, response);这个filterChain就是上边调用的this。
这样的话,只要没有执行完所有的过滤器,就会不断的创建过滤器,一直调用执行。
过滤器执行完后,会执行:
servlet.service((HttpServletRequest) request, (HttpServletResponse) response);
我们编写的servlet一般继承至HttpServlet,servlet.service()既是执行HttpServlet.service():
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getMethod(); if (method.equals(METHOD_GET)) { long lastModified = getLastModified(req); if (lastModified == -1) { // servlet doesn't support if-modified-since, no reason // to go through further expensive logic doGet(req, resp); } else { long ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE); if (ifModifiedSince < (lastModified / 1000 * 1000)) { // If the servlet mod time is later, call doGet() // Round down to the nearest second for a proper compare // A ifModifiedSince of -1 will always be less maybeSetLastModified(resp, lastModified); doGet(req, resp); } else { resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED); } } } else if (method.equals(METHOD_HEAD)) { long lastModified = getLastModified(req); maybeSetLastModified(resp, lastModified); doHead(req, resp); } else if (method.equals(METHOD_POST)) { doPost(req, resp); } else if (method.equals(METHOD_PUT)) { doPut(req, resp); } else if (method.equals(METHOD_DELETE)) { doDelete(req, resp); } else if (method.equals(METHOD_OPTIONS)) { doOptions(req,resp); } else if (method.equals(METHOD_TRACE)) { doTrace(req,resp); } else { // // Note that this means NO servlet supports whatever // method was requested, anywhere on this server. // String errMsg = lStrings.getString("http.method_not_implemented"); Object[] errArgs = new Object[1]; errArgs[0] = method; errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg); } }
判断请求的方法,到了我们熟悉的doPost()、doGet()了,这两个方法在业务Servlet中我们一般会重写,处理业务。
相关文章推荐
- [Tomcat6.0源码]请求的处理一Socket
- [Tomcat6.0源码]请求的处理三Mapper、JMX
- [Tomcat6.0源码]请求的处理二Request
- Tomcat源码解读系列——Tomcat对HTTP请求处理的整体流程
- Tomcat请求处理(四) -- Request, Response, 和Pipeline
- Tomcat源码解读系列(三)——Tomcat对HTTP请求处理的整体流程
- tomcat6源码分析三(请求处理过程)
- tomcat6源码分析三(请求处理过程)
- Tomcat6.0源码学习--接受并传递请求
- Tomcat请求处理过程(Tomcat源码解析五)
- Tomcat源码剖析之Pipeline-Valve
- Tomcat源码解读系列(三)——Tomcat对HTTP请求处理的整体流程
- Tomcat请求处理过程(Tomcat源码解析五)
- 浅读Tomcat源码(三)---请求处理
- Tomcat6.0源码学习--接受并传递请求
- Tomcat源码解读系列——Tomcat对HTTP请求处理的整体流程
- Tomcat7.0.42源码研读之职责链模式Pipeline与Valve(二)
- Tomcat源码阅读之处理请求
- Tomcat源码解读系列三Tomcat对HTTP请求处理的整体流程
- Tomcat目录结构及Tomcat Server处理一个http请求的过程