/**
* The basic Valve (if any) associated with this Pipeline.
*/
protected Valve basic = null;
/**
* The Container with which this Pipeline is associated.
*/
protected Container container = null;
/**
* The first valve associated with this Pipeline.
*/
protected Valve first = null;
看下该类的 addValve 方法:
1 public void addValve(Valve valve) {
2
3 // Validate that we can add this Valve
4 if (valve instanceof Contained)
5 ((Contained) valve).setContainer(this.container);
6
7 // Start the new component if necessary
8 if (getState().isAvailable()) {
9 if (valve instanceof Lifecycle) {
10 try {
11 ((Lifecycle) valve).start();
12 } catch (LifecycleException e) {
13 log.error("StandardPipeline.addValve: start: ", e);
14 }
15 }
16 }
17
18 // Add this Valve to the set associated with this Pipeline
19 if (first == null) {
20 first = valve;
21 valve.setNext(basic);
22 } else {
23 Valve current = first;
24 while (current != null) {
25 if (current.getNext() == basic) {
26 current.setNext(valve);
27 valve.setNext(basic);
28 break;
29 }
30 current = current.getNext();
31 }
32 }
33
34 container.fireContainerEvent(Container.ADD_VALVE_EVENT, valve);
35 }
在第 18 到 32 行,每次给管道添加一个普通阀的时候如果管道内原来没有普通阀则将新添加的阀作为该管道的成员变量 first 的引用,如果管道内已有普通阀,则把新加的阀加到所有普通阀链条末端,并且将该阀的下一个阀的引用设置为管道的基础阀。这样管道内的阀结构如下图所示:
即 Pipeline 内部维护 first 和 basic 两个阀,其它相关阀通过 getNext 来获取。
看下 getFirst 方法的实现:
public Valve getFirst() {
if (first != null) {
return first;
}
return basic;
}
1 public StandardEngine() {
2
3 super();
4 pipeline.setBasic(new StandardEngineValve());
5 /* Set the jmvRoute using the system property jvmRoute */
6 try {
7 setJvmRoute(System.getProperty("jvmRoute"));
8 } catch(Exception ex) {
9 log.warn(sm.getString("standardEngine.jvmRouteFail"));
10 }
11 // By default, the engine will hold the reloading thread
12 backgroundProcessorDelay = 10;
13
14 }
1 public final void invoke(Request request, Response response)
2 throws IOException, ServletException {
3
4 // Select the Context to be used for this Request
5 Context context = request.getContext();
6 if (context == null) {
7 response.sendError
8 (HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
9 sm.getString("standardHost.noContext"));
10 return;
11 }
12
13 // Bind the context CL to the current thread
14 if( context.getLoader() != null ) {
15 // Not started - it should check for availability first
16 // This should eventually move to Engine, it's generic.
17 if (Globals.IS_SECURITY_ENABLED) {
18 PrivilegedAction pa = new PrivilegedSetTccl(
19 context.getLoader().getClassLoader());
20 AccessController.doPrivileged(pa);
21 } else {
22 Thread.currentThread().setContextClassLoader
23 (context.getLoader().getClassLoader());
24 }
25 }
26 if (request.isAsyncSupported()) {
27 request.setAsyncSupported(context.getPipeline().isAsyncSupported());
28 }
29
30 // Don't fire listeners during async processing
31 // If a request init listener throws an exception, the request is
32 // aborted
33 boolean asyncAtStart = request.isAsync();
34 // An async error page may dispatch to another resource. This flag helps
35 // ensure an infinite error handling loop is not entered
36 boolean errorAtStart = response.isError();
37 if (asyncAtStart || context.fireRequestInitEvent(request)) {
38
39 // Ask this Context to process this request
40 try {
41 context.getPipeline().getFirst().invoke(request, response);
42 } catch (Throwable t) {
43 ExceptionUtils.handleThrowable(t);
44 if (errorAtStart) {
45 container.getLogger().error("Exception Processing " +
46 request.getRequestURI(), t);
47 } else {
48 request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t);
49 throwable(request, response, t);
50 }
51 }
52
53 // If the request was async at the start and an error occurred then
54 // the async error handling will kick-in and that will fire the
55 // request destroyed event *after* the error handling has taken
56 // place
57 if (!(request.isAsync() || (asyncAtStart &&
58 request.getAttribute(
59 RequestDispatcher.ERROR_EXCEPTION) != null))) {
60 // Protect against NPEs if context was destroyed during a
61 // long running request.
62 if (context.getState().isAvailable()) {
63 if (!errorAtStart) {
64 // Error page processing
65 response.setSuspended(false);
66
67 Throwable t = (Throwable) request.getAttribute(
68 RequestDispatcher.ERROR_EXCEPTION);
69
70 if (t != null) {
71 throwable(request, response, t);
72 } else {
73 status(request, response);
74 }
75 }
76
77 context.fireRequestDestroyEvent(request);
78 }
79 }
80 }
81
82 // Access a session (if present) to update last accessed time, based on a
83 // strict interpretation of the specification
84 if (ACCESS_SESSION) {
85 request.getSession(false);
86 }
87
88 // Restore the context classloader
89 if (Globals.IS_SECURITY_ENABLED) {
90 PrivilegedAction pa = new PrivilegedSetTccl(
91 StandardHostValve.class.getClassLoader());
92 AccessController.doPrivileged(pa);
93 } else {
94 Thread.currentThread().setContextClassLoader
95 (StandardHostValve.class.getClassLoader());
96 }
97 }
public StandardContext() {
super();
pipeline.setBasic(new StandardContextValve());
broadcaster = new NotificationBroadcasterSupport();
// Set defaults
if (!Globals.STRICT_SERVLET_COMPLIANCE) {
// Strict servlet compliance requires all extension mapped servlets
// to be checked against welcome files
resourceOnlyServlets.add("jsp");
}
}
看下其基础阀的 invoke 方法代码:
1 public final void invoke(Request request, Response response)
2 throws IOException, ServletException {
3
4 // Disallow any direct access to resources under WEB-INF or META-INF
5 MessageBytes requestPathMB = request.getRequestPathMB();
6 if ((requestPathMB.startsWithIgnoreCase("/META-INF/", 0))
7 || (requestPathMB.equalsIgnoreCase("/META-INF"))
8 || (requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0))
9 || (requestPathMB.equalsIgnoreCase("/WEB-INF"))) {
10 response.sendError(HttpServletResponse.SC_NOT_FOUND);
11 return;
12 }
13
14 // Select the Wrapper to be used for this Request
15 Wrapper wrapper = request.getWrapper();
16 if (wrapper == null || wrapper.isUnavailable()) {
17 response.sendError(HttpServletResponse.SC_NOT_FOUND);
18 return;
19 }
20
21 // Acknowledge the request
22 try {
23 response.sendAcknowledgement();
24 } catch (IOException ioe) {
25 container.getLogger().error(sm.getString(
26 "standardContextValve.acknowledgeException"), ioe);
27 request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, ioe);
28 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
29 return;
30 }
31
32 if (request.isAsyncSupported()) {
33 request.setAsyncSupported(wrapper.getPipeline().isAsyncSupported());
34 }
35 wrapper.getPipeline().getFirst().invoke(request, response);
36 }