概述

Tomcat的类ApplicationFilterChain是一个Java Servlet API规范javax.servlet.FilterChain的实现,用于管理某个请求request的一组过滤器Filter的执行。当针对一个request所定义的一组过滤器Filter处理完该请求后,组后一个doFilter()调用才会执行目标Servlet的方法service(),然后响应对象response会按照相反的顺序依次被这些Filter处理,最终到达客户端。
事实上,一个Filter的逻辑可以被设计成既可以在目标servlet执行前执行,也可以在目标servlet执行之后执行,或者二者都有,甚至可以不执行目标servlet而是自己直接响应客户端。因此,在一个ApplicationFilterChain链执行到目标servlet实例的service()方法时,你可以认为此时所有Filter被设计在servlet执行之前执行的逻辑都执行完了,而所有Filter的被设计在servlet执行之后执行的逻辑都还尚未执行。

源代码分析

  1. /*
  2. * 此源代码摘自Tomcat版本9
  3. */
  4. public final class ApplicationFilterChain implements FilterChain {
  5. // Used to enforce requirements of SRV.8.2 / SRV.14.2.5.1
  6. private static final ThreadLocal<ServletRequest> lastServicedRequest;
  7. private static final ThreadLocal<ServletResponse> lastServicedResponse;
  8. static {
  9. if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
  10. lastServicedRequest = new ThreadLocal<>();
  11. lastServicedResponse = new ThreadLocal<>();
  12. } else {
  13. lastServicedRequest = null;
  14. lastServicedResponse = null;
  15. }
  16. }
  17. // -------------------------------------------------------------- Constants
  18. public static final int INCREMENT = 10;
  19. // ----------------------------------------------------- Instance Variables
  20. /**
  21. * Filters. 执行目标Servlet.service()方法前需要经历的过滤器Filter,初始化为0个元素的数组对象
  22. */
  23. private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0];
  24. /**
  25. * The int which is used to maintain the current position
  26. * in the filter chain.
  27. * 用于记录过滤器链中当前所执行的过滤器的位置,是当前过滤器在filters数组的下标,初始化为0
  28. */
  29. private int pos = 0;
  30. /**
  31. * The int which gives the current number of filters in the chain.
  32. * 过滤器链中过滤器的个数(注意:并不是数组filters的长度),初始化为0,和filters数组的初始长度一致
  33. */
  34. private int n = 0;
  35. /**
  36. * The servlet instance to be executed by this chain.
  37. * 该过滤器链执行完过滤器后最终要执行的目标Servlet
  38. */
  39. private Servlet servlet = null;
  40. /**
  41. * Does the associated servlet instance support async processing?
  42. * 所关联的Servlet实例是否支持异步处理 ? 缺省为 false,表示缺省情况下不支持异步处理。
  43. */
  44. private boolean servletSupportsAsync = false;
  45. /**
  46. * The string manager for our package.
  47. */
  48. private static final StringManager sm =
  49. StringManager.getManager(Constants.Package);
  50. /**
  51. * Static class array used when the SecurityManager is turned on and
  52. * <code>doFilter</code> is invoked.
  53. */
  54. private static final Class<?>[] classType = new Class[]{
  55. ServletRequest.class, ServletResponse.class, FilterChain.class};
  56. /**
  57. * Static class array used when the SecurityManager is turned on and
  58. * <code>service</code> is invoked.
  59. */
  60. private static final Class<?>[] classTypeUsedInService = new Class[]{
  61. ServletRequest.class, ServletResponse.class};
  62. // ---------------------------------------------------- FilterChain Methods
  63. /**
  64. * Invoke the next filter in this chain, passing the specified request
  65. * and response. If there are no more filters in this chain, invoke
  66. * the <code>service()</code> method of the servlet itself.
  67. * 执行过滤器链中的下一个过滤器Filter。如果链中所有过滤器都执行过,
  68. * 则调用servlet的service()方法。
  69. *
  70. * @param request The servlet request we are processing
  71. * @param response The servlet response we are creating
  72. *
  73. * @exception IOException if an input/output error occurs
  74. * @exception ServletException if a servlet exception occurs
  75. */
  76. @Override
  77. public void doFilter(ServletRequest request, ServletResponse response)
  78. throws IOException, ServletException {
  79. // 下面的if-else分支主要是根据Globals.IS_SECURITY_ENABLED是true还是false决定
  80. // 如何调用目标逻辑,但两种情况下,目标逻辑最终都是 internalDoFilter(req,res)
  81. if( Globals.IS_SECURITY_ENABLED ) {
  82. final ServletRequest req = request;
  83. final ServletResponse res = response;
  84. try {
  85. java.security.AccessController.doPrivileged(
  86. new java.security.PrivilegedExceptionAction<Void>() {
  87. @Override
  88. public Void run()
  89. throws ServletException, IOException {
  90. internalDoFilter(req,res);
  91. return null;
  92. }
  93. }
  94. );
  95. } catch( PrivilegedActionException pe) {
  96. Exception e = pe.getException();
  97. if (e instanceof ServletException)
  98. throw (ServletException) e;
  99. else if (e instanceof IOException)
  100. throw (IOException) e;
  101. else if (e instanceof RuntimeException)
  102. throw (RuntimeException) e;
  103. else
  104. throw new ServletException(e.getMessage(), e);
  105. }
  106. } else {
  107. internalDoFilter(request,response);
  108. }
  109. }
  110. private void internalDoFilter(ServletRequest request,
  111. ServletResponse response)
  112. throws IOException, ServletException {
  113. // Call the next filter if there is one
  114. if (pos < n) {
  115. ApplicationFilterConfig filterConfig = filters[pos++];
  116. try {
  117. // 找到目标 Filter 对象
  118. Filter filter = filterConfig.getFilter();
  119. if (request.isAsyncSupported() && "false".equalsIgnoreCase(
  120. filterConfig.getFilterDef().getAsyncSupported())) {
  121. request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE);
  122. }
  123. // 执行目标 Filter 对象的 doFilter方法,
  124. // 注意,这里当前ApplicationFilterChain对象被传递到了目标
  125. // Filter对象的doFilter方法,而目标Filter对象的doFilter在执行完自己
  126. // 被指定的逻辑之后会反过来调用这个ApplicationFilterChain对象的
  127. // doFilter方法,只是pos向前推进了一个过滤器。这个ApplicationFilterChain
  128. // 和Filter之间反复调用彼此doFilter方法的过程一直持续直到当前链发现所有的
  129. // Filter都已经被执行
  130. if( Globals.IS_SECURITY_ENABLED ) {
  131. final ServletRequest req = request;
  132. final ServletResponse res = response;
  133. Principal principal =
  134. ((HttpServletRequest) req).getUserPrincipal();
  135. Object[] args = new Object[]{req, res, this};
  136. SecurityUtil.doAsPrivilege ("doFilter", filter, classType, args, principal);
  137. } else {
  138. filter.doFilter(request, response, this);
  139. }
  140. } catch (IOException | ServletException | RuntimeException e) {
  141. throw e;
  142. } catch (Throwable e) {
  143. e = ExceptionUtils.unwrapInvocationTargetException(e);
  144. ExceptionUtils.handleThrowable(e);
  145. throw new ServletException(sm.getString("filterChain.filter"), e);
  146. }
  147. return;
  148. }
  149. // We fell off the end of the chain -- call the servlet instance
  150. // 这里是过滤器链中所有的过滤器都已经被执行的情况,现在需要调用servlet实例本身了。
  151. // !!! 注意 : 虽然这里开始调用servlet实例了,但是从当前方法执行堆栈可以看出,过滤器链
  152. // 和链中过滤器的doFilter方法的执行帧还在堆栈中并未退出,他们会在servlet实例的逻辑
  153. // 执行完后,分别执行完自己剩余的的逻辑才会逐一结束。
  154. try {
  155. if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
  156. lastServicedRequest.set(request);
  157. lastServicedResponse.set(response);
  158. }
  159. if (request.isAsyncSupported() && !servletSupportsAsync) {
  160. request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR,
  161. Boolean.FALSE);
  162. }
  163. // Use potentially wrapped request from this point
  164. if ((request instanceof HttpServletRequest) &&
  165. (response instanceof HttpServletResponse) &&
  166. Globals.IS_SECURITY_ENABLED ) {
  167. final ServletRequest req = request;
  168. final ServletResponse res = response;
  169. Principal principal =
  170. ((HttpServletRequest) req).getUserPrincipal();
  171. Object[] args = new Object[]{req, res};
  172. SecurityUtil.doAsPrivilege("service",
  173. servlet,
  174. classTypeUsedInService,
  175. args,
  176. principal);
  177. } else {
  178. servlet.service(request, response);
  179. }
  180. } catch (IOException | ServletException | RuntimeException e) {
  181. throw e;
  182. } catch (Throwable e) {
  183. e = ExceptionUtils.unwrapInvocationTargetException(e);
  184. ExceptionUtils.handleThrowable(e);
  185. throw new ServletException(sm.getString("filterChain.servlet"), e);
  186. } finally {
  187. if (ApplicationDispatcher.WRAP_SAME_OBJECT) {
  188. lastServicedRequest.set(null);
  189. lastServicedResponse.set(null);
  190. }
  191. }
  192. }
  193. /**
  194. * The last request passed to a servlet for servicing from the current
  195. * thread.
  196. *
  197. * @return The last request to be serviced.
  198. */
  199. public static ServletRequest getLastServicedRequest() {
  200. return lastServicedRequest.get();
  201. }
  202. /**
  203. * The last response passed to a servlet for servicing from the current
  204. * thread.
  205. *
  206. * @return The last response to be serviced.
  207. */
  208. public static ServletResponse getLastServicedResponse() {
  209. return lastServicedResponse.get();
  210. }
  211. // -------------------------------------------------------- Package Methods
  212. /**
  213. * Add a filter to the set of filters that will be executed in this chain.
  214. * 往当前要执行的过滤器链的过滤器集合filters中增加一个过滤器
  215. * @param filterConfig The FilterConfig for the servlet to be executed
  216. */
  217. void addFilter(ApplicationFilterConfig filterConfig) {
  218. // Prevent the same filter being added multiple times
  219. //去重处理,如果已经添加进来则避免二次添加
  220. for(ApplicationFilterConfig filter:filters)
  221. if(filter==filterConfig)
  222. return;
  223. if (n == filters.length) {
  224. // !!! 请注意:每次需要扩容时并不是增加一个元素空间,而是增加INCREMENT(默认是10)个,
  225. // 这个行为的结果是filters数组的长度和数组中过滤器的个数n并不相等
  226. ApplicationFilterConfig[] newFilters =
  227. new ApplicationFilterConfig[n + INCREMENT];
  228. System.arraycopy(filters, 0, newFilters, 0, n);
  229. filters = newFilters;
  230. }
  231. filters[n++] = filterConfig;
  232. }
  233. /**
  234. * Release references to the filters and wrapper executed by this chain.
  235. */
  236. void release() {
  237. for (int i = 0; i < n; i++) {
  238. filters[i] = null;
  239. }
  240. n = 0;
  241. pos = 0;
  242. servlet = null;
  243. servletSupportsAsync = false;
  244. }
  245. /**
  246. * Prepare for reuse of the filters and wrapper executed by this chain.
  247. */
  248. void reuse() {
  249. pos = 0;
  250. }
  251. /**
  252. * Set the servlet that will be executed at the end of this chain.
  253. *
  254. * @param servlet The Wrapper for the servlet to be executed
  255. */
  256. void setServlet(Servlet servlet) {
  257. this.servlet = servlet;
  258. }
  259. void setServletSupportsAsync(boolean servletSupportsAsync) {
  260. this.servletSupportsAsync = servletSupportsAsync;
  261. }
  262. /**
  263. * Identifies the Filters, if any, in this FilterChain that do not support
  264. * async.
  265. *
  266. * @param result The Set to which the fully qualified class names of each
  267. * Filter in this FilterChain that does not support async will
  268. * be added
  269. */
  270. public void findNonAsyncFilters(Set<String> result) {
  271. for (int i = 0; i < n ; i++) {
  272. ApplicationFilterConfig filter = filters[i];
  273. if ("false".equalsIgnoreCase(filter.getFilterDef().getAsyncSupported())) {
  274. result.add(filter.getFilterClass());
  275. }
  276. }
  277. }
  278. }