| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 
 | @Overridepublic final void invoke(Request request, Response response)
 throws IOException, ServletException {
 
 // Initialize local variables we may need
 boolean unavailable = false;
 Throwable throwable = null;
 // This should be a Request attribute...
 long t1=System.currentTimeMillis();
 requestCount.incrementAndGet();
 StandardWrapper wrapper = (StandardWrapper) getContainer();
 Servlet servlet = null;
 Context context = (Context) wrapper.getParent();
 
 // Check for the application being marked unavailable
 if (!context.getState().isAvailable()) {
 response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
 sm.getString("standardContext.isUnavailable"));
 unavailable = true;
 }
 
 // Check for the servlet being marked unavailable
 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;
 }
 
 // Allocate a servlet instance to process this request
 try {
 // 关键点1:这儿调用Wrapper的allocate()方法分配一个Servlet实例
 if (!unavailable) {
 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);
 } catch (Throwable e) {
 ExceptionUtils.handleThrowable(e);
 container.getLogger().error(sm.getString("standardWrapper.allocateException",
 wrapper.getName()), e);
 throwable = e;
 exception(request, response, e);
 servlet = null;
 }
 
 MessageBytes requestPathMB = request.getRequestPathMB();
 DispatcherType dispatcherType = DispatcherType.REQUEST;
 if (request.getDispatcherType()==DispatcherType.ASYNC) dispatcherType = DispatcherType.ASYNC;
 request.setAttribute(Globals.DISPATCHER_TYPE_ATTR,dispatcherType);
 request.setAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR,
 requestPathMB);
 // Create the filter chain for this request
 // 关键点2,创建过滤器链,类似于Pipeline的功能
 ApplicationFilterChain filterChain =
 ApplicationFilterFactory.createFilterChain(request, wrapper, servlet);
 
 // Call the filter chain for this request
 // NOTE: This also calls the servlet's service() method
 try {
 if ((servlet != null) && (filterChain != null)) {
 // Swallow output if needed
 if (context.getSwallowOutput()) {
 try {
 SystemLogHandler.startCapture();
 if (request.isAsyncDispatching()) {
 request.getAsyncContextInternal().doInternalDispatch();
 } else {
 // 关键点3,调用过滤器链的doFilter,最终会调用到Servlet的service方法
 filterChain.doFilter(request.getRequest(),
 response.getResponse());
 }
 } finally {
 String log = SystemLogHandler.stopCapture();
 if (log != null && log.length() > 0) {
 context.getLogger().info(log);
 }
 }
 } else {
 if (request.isAsyncDispatching()) {
 request.getAsyncContextInternal().doInternalDispatch();
 } else {
 // 关键点3,调用过滤器链的doFilter,最终会调用到Servlet的service方法
 filterChain.doFilter
 (request.getRequest(), response.getResponse());
 }
 }
 
 }
 } catch (ClientAbortException e) {
 throwable = e;
 exception(request, response, e);
 } catch (IOException e) {
 container.getLogger().error(sm.getString(
 "standardWrapper.serviceException", wrapper.getName(),
 context.getName()), e);
 throwable = e;
 exception(request, response, e);
 } catch (UnavailableException e) {
 container.getLogger().error(sm.getString(
 "standardWrapper.serviceException", wrapper.getName(),
 context.getName()), e);
 //            throwable = e;
 //            exception(request, response, 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()));
 }
 // Do not save exception in 'throwable', because we
 // do not want to do exception(request, response, e) processing
 } catch (ServletException e) {
 Throwable rootCause = StandardWrapper.getRootCause(e);
 if (!(rootCause instanceof ClientAbortException)) {
 container.getLogger().error(sm.getString(
 "standardWrapper.serviceExceptionRoot",
 wrapper.getName(), context.getName(), e.getMessage()),
 rootCause);
 }
 throwable = e;
 exception(request, response, e);
 } catch (Throwable e) {
 ExceptionUtils.handleThrowable(e);
 container.getLogger().error(sm.getString(
 "standardWrapper.serviceException", wrapper.getName(),
 context.getName()), e);
 throwable = e;
 exception(request, response, e);
 }
 
 // Release the filter chain (if any) for this request
 // 关键点4,释放掉过滤器链及其相关资源
 if (filterChain != null) {
 filterChain.release();
 }
 
 // 关键点5,释放掉Servlet及相关资源
 // Deallocate the allocated servlet instance
 try {
 if (servlet != null) {
 wrapper.deallocate(servlet);
 }
 } catch (Throwable e) {
 ExceptionUtils.handleThrowable(e);
 container.getLogger().error(sm.getString("standardWrapper.deallocateException",
 wrapper.getName()), e);
 if (throwable == null) {
 throwable = e;
 exception(request, response, e);
 }
 }
 
 // If this servlet has been marked permanently unavailable,
 // unload it and release this instance
 // 关键点6,如果servlet被标记为永远不可达,则需要卸载掉它,并释放这个servlet实例
 try {
 if ((servlet != null) &&
 (wrapper.getAvailable() == Long.MAX_VALUE)) {
 wrapper.unload();
 }
 } catch (Throwable e) {
 ExceptionUtils.handleThrowable(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;
 }
 
 |