public class SimpleWrapper implements Wrapper, Pipeline { // the servlet instance private Servlet instance = null; private String servletClass; private Loader loader; private String name; private SimplePipeline pipeline = new SimplePipeline(this); protected Container parent = null; public SimpleWrapper() { pipeline.setBasic(new SimpleWrapperValve()); } public synchronized void addValve(Valve valve) { pipeline.addValve(valve); } ... }既然說到了容器,就得說說管道(每一級容器中,都有一個管道);把咱們的命令比做流水,在(流水)命令接觸終於的servlet以前,會有一個長長的管道(SimplePipeline),管道里有一個一個的閥(Valve),每一個閥都會作一個任務!就這麼簡單,在管道里面有一個基礎閥(SimpleWrapperValve),而這個基礎閥就用來生成servlet,調用其service方法。
wrapper程序的類圖例如如下:
流程例如如下
先是調用wrapper的invoke;
java
SimpleWrapper.java public void invoke(Request request, Response response) throws IOException, ServletException { pipeline.invoke(request, response); }再調用管道的invoke;
SimplePipeline.java public void invoke(Request request, Response response) throws IOException, ServletException { // Invoke the first Valve in this pipeline for this request (new SimplePipelineValveContext()).invokeNext(request, response); } SimplePipelineValveContext爲SimplePipeline的內部類,做用就是循環所有的閥,最後調用基礎閥(就是如下代碼中的basic) SimplePipelineValveContext.java public void invokeNext(Request request, Response response) throws IOException, ServletException { int subscript = stage; stage = stage + 1; // Invoke the requested Valve for the current request thread if (subscript < valves.length) { valves[subscript].invoke(request, response, this); } else if ((subscript == valves.length) && (basic != null)) { basic.invoke(request, response, this); } else { throw new ServletException("No valve"); } }
所以就有了mapper接口,咱們這裏用的是事實上現類,simplecontextmapper。其map方法就能返回對應的wrapper。
web
public Container map(Request request, boolean update) { String requestURI = ((HttpRequest) request).getDecodedRequestURI(); String relativeURI = requestURI.substring(contextPath.length()); Wrapper wrapper = null; String name = context.findServletMapping(relativeURI); if (name != null) wrapper = (Wrapper) context.findChild(name); return (wrapper); }找到wrapper就和上一部分的過程同樣了。
本章類圖:
tomcat是組件化的軟件。所有的組件都實現了Lifecycle接口,裏面有start與stop方法;咱們現在想要的效果就是,我僅僅用啓動一個組件系統就能幫我把所有的都啓動,關閉也是同樣。apache
看上去很是複雜,事實上很是easy
tomcat
public synchronized void start() throws LifecycleException { if (started) throw new LifecycleException("SimpleContext has already started"); // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null); started = true; try { // Start our subordinate components, if any if ((loader != null) && (loader instanceof Lifecycle)) ((Lifecycle) loader).start(); // Start our child containers, if any Container children[] = findChildren(); for (int i = 0; i < children.length; i++) { if (children[i] instanceof Lifecycle) ((Lifecycle) children[i]).start(); } // Start the Valves in our pipeline (including the basic), // if any if (pipeline instanceof Lifecycle) ((Lifecycle) pipeline).start(); // Notify our interested LifecycleListeners lifecycle.fireLifecycleEvent(START_EVENT, null); } catch (Exception e) { e.printStackTrace(); }SimpleContext裏面的各個組件依次啓動就ok;
Bootstrap.java LifecycleListener listener = new SimpleContextLifecycleListener(); ((Lifecycle) context).addLifecycleListener(listener); simplecontext.java protected LifecycleSupport lifecycle = new LifecycleSupport(this); public void addLifecycleListener(LifecycleListener listener) { lifecycle.addLifecycleListener(listener); }執行時,如下的代碼就是告訴所有關心SimpleContext的監聽者:SimpleContext類作了BEFORE_START_EVENT這個動做!
lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null); LifecycleSupport.java public void fireLifecycleEvent(String type, Object data) { LifecycleEvent event = new LifecycleEvent(lifecycle, type, data); LifecycleListener interested[] = null; synchronized (listeners) { interested = (LifecycleListener[]) listeners.clone(); } for (int i = 0; i < interested.length; i++) //循環通知所有關注者 interested[i].lifecycleEvent(event); } // 一個詳細的關注者 public class SimpleContextLifecycleListener implements LifecycleListener { @SuppressWarnings("unused") public void lifecycleEvent(LifecycleEvent event) { Lifecycle lifecycle = event.getLifecycle(); System.out.println("SimpleContextLifecycleListener's event " +event.getType().toString()); if (Lifecycle.START_EVENT.equals(event.getType())) { System.out.println("Starting context."); } else if (Lifecycle.STOP_EVENT.equals(event.getType())) { System.out.println("Stopping context."); } } }