日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

詳解Tomcat中Filter的執行流程

瀏覽:391日期:2023-09-08 20:45:27
目錄前言1、Filter接口2、FilterChain接口執行流程1、創建filterChain2、執行dofilter前言

Filter是什么?Filter是servlet規范中定義的java web組件, 在所有支持java web的容器中都可以使用 它是位于前端請求到servlet之間的一系列過濾器,也可以稱之為中間件,它主要是對請求到達servlet之前做一些額外的動作:

1、權限控制2、監控3、日志管理4、等等

這里涉及到兩個接口:Filter和FilterChain

Filter和FilterChain密不可分, Filter可以實現依次調用正是因為有了FilterChain。

1、Filter接口public interface Filter { // 容器創建的時候調用, 即啟動tomcat的時候調用 public void init(FilterConfig filterConfig) throws ServletException; // 由FilterChain調用, 并且傳入FilterChain本身, 最后回調FilterChain的doFilter()方法 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException; // 容器銷毀的時候調用, 即關閉tomcat的時候調用 public void destroy(); }2、FilterChain接口public interface FilterChain { // 由Filter.doFilter()中的chain.doFilter調用 public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException;}執行流程

在前面的文章中,我們知道,tomcat啟動會執行StandardWrapperValve.java類的invoke方法:

public final void invoke(Request request, Response response){ ...... 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 ApplicationFilterChain filterChain = ApplicationFilterFactory.createFilterChain(request, wrapper, servlet); // Call the filter chain for this request // NOTE: This also calls the servlet's service() method Container container = this.container; try { if ((servlet != null) && (filterChain != null)) { // Swallow output if needed if (context.getSwallowOutput()) {try { SystemLogHandler.startCapture(); if (request.isAsyncDispatching()) { request.getAsyncContextInternal().doInternalDispatch(); } else { 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 { filterChain.doFilter (request.getRequest(), response.getResponse());} } } } catch (ClientAbortException | CloseNowException e) { } ......}

上面的代碼做了如下一些動作:

1、每次請求過來都會創建一個過濾器鏈(filterChain),并把待執行的servlet對象存放到過濾器鏈中。對于每個url,對應的filter個數都是不固定的,filterchain需要保存每個請求所對應的一個filter數組,以及調用到的filter的position,以便繼續向下調用filter。2、創建了filterChain之后,就開始執行doFilter進行請求的鏈式處理。1、創建filterChain

下面我們具體來看看filterChain是怎么創建的

public static ApplicationFilterChain createFilterChain(ServletRequest request, Wrapper wrapper, Servlet servlet) { // If there is no servlet to execute, return null if (servlet == null) return null; // Create and initialize a filter chain object ApplicationFilterChain filterChain = null; if (request instanceof Request) { Request req = (Request) request; if (Globals.IS_SECURITY_ENABLED) { // Security: Do not recycle filterChain = new ApplicationFilterChain(); } 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.setServletSupportsAsync(wrapper.isAsyncSupported()); // 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 DispatcherType dispatcher = (DispatcherType) request.getAttribute(Globals.DISPATCHER_TYPE_ATTR); String requestPath = null; Object attribute = request.getAttribute(Globals.DISPATCHER_REQUEST_PATH_ATTR); if (attribute != null){ requestPath = attribute.toString(); } String servletName = wrapper.getName(); // Add the relevant path-mapped filters to this filter chain for (FilterMap filterMap : filterMaps) { if (!matchDispatcher(filterMap, dispatcher)) { continue; } if (!matchFiltersURL(filterMap, requestPath)) continue; ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)context.findFilterConfig(filterMap.getFilterName()); if (filterConfig == null) { // FIXME - log configuration problem continue; } filterChain.addFilter(filterConfig); } // Add filters that match on servlet name second for (FilterMap filterMap : filterMaps) { if (!matchDispatcher(filterMap, dispatcher)) { continue; } if (!matchFiltersServlet(filterMap, servletName)) continue; ApplicationFilterConfig filterConfig = (ApplicationFilterConfig)context.findFilterConfig(filterMap.getFilterName()); if (filterConfig == null) { // FIXME - log configuration problem continue; } filterChain.addFilter(filterConfig); } // Return the completed filter chain return filterChain;}

上面的代碼做了一下幾件事:

1、把要執行的servlet存放到過濾器鏈中。2、如果沒有配置過濾器則return一個空的過濾器鏈(只包含上面設置的servlet)。3、如果配置url-pattern過濾器,則把匹配的過濾器加入到過濾器鏈中4、如果配置servlet-name過濾器,則把匹配的過濾器加入到過濾器鏈中

注意: filterChain.addFilter()順序與web.xml中定義的Filter順序一致,所以過濾器的執行順序是按定義的上下順序決定的。

2、執行dofilter

創建了chain之后,就開始執行鏈式請求了,具體的邏輯如下:

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++]; try { Filter filter = filterConfig.getFilter(); if (request.isAsyncSupported() && 'false'.equalsIgnoreCase( filterConfig.getFilterDef().getAsyncSupported())) {request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE); } 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); } else {filter.doFilter(request, response, this); } } catch (IOException | ServletException | RuntimeException e) { throw e; } catch (Throwable e) { e = ExceptionUtils.unwrapInvocationTargetException(e); ExceptionUtils.handleThrowable(e); throw new ServletException(sm.getString('filterChain.filter'), e); } return; } // We fell off the end of the chain -- call the servlet instance try { if (ApplicationDispatcher.WRAP_SAME_OBJECT) { lastServicedRequest.set(request); lastServicedResponse.set(response); } if (request.isAsyncSupported() && !servletSupportsAsync) { request.setAttribute(Globals.ASYNC_SUPPORTED_ATTR, Boolean.FALSE); } // Use potentially wrapped request from this point if ((request instanceof HttpServletRequest) &&(response instanceof HttpServletResponse) &&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); } else { servlet.service(request, response); } } catch (IOException | ServletException | RuntimeException e) { throw e; } catch (Throwable e) { e = ExceptionUtils.unwrapInvocationTargetException(e); ExceptionUtils.handleThrowable(e); throw new ServletException(sm.getString('filterChain.servlet'), e); } finally { if (ApplicationDispatcher.WRAP_SAME_OBJECT) { lastServicedRequest.set(null); lastServicedResponse.set(null); } }}

上面的代碼邏輯如下:

1、通過position索引判斷是否執行完了所有的filter2、如果沒有,取出當前待執行的索引filter,調用其doFilter方法,在上面的接口說明中,我們看到,所有的filter類都繼承了filter接口,都實現了dofilter方法;我們也注意到,該方法接收一個filterChain對象。在這段代碼中,filter.doFilter(request, response, this);可以看到,將自身引用傳遞進去了,那么各個filter在dofilter的方法中,可以根據自身業務需要,來判斷是否需要繼續進行下面的filter鏈式執行,如果需要,就執行filterChain.doFilter方法,此時就又回到了此代碼中。如果反復3、如果執行完了所有的filter,則開始執行servlet業務模塊servlet.service(request, response);

以上就是詳解Tomcat中Filter是怎樣執行的的詳細內容,更多關于Tomcat Filter執行的資料請關注好吧啦網其它相關文章!

標簽: Tomcat
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
久久精品av| 亚洲免费福利一区| 国产探花一区二区| 亚洲精品中文字幕乱码| 久草免费在线视频| 欧美成人a交片免费看| 国产一区精品福利| 蜜桃精品在线| 精品中文一区| 日韩精品一区二区三区中文在线 | 久久亚洲视频| 日韩av一区二区在线影视| 欧美亚洲综合视频| 久久av中文| 久久久久网站| 亚洲一区有码| 久久精品国产亚洲aⅴ| 亚洲精品在线影院| 亚洲一区有码| 中文在线а√天堂| 麻豆久久精品| 国产精品色在线网站| 国产伦久视频在线观看| 久久国产99| 国产探花一区在线观看| 亚洲a一区二区三区| 91成人小视频| 91成人超碰| 国产一区二区精品福利地址| 亚洲一区亚洲| 精品99在线| 免费在线观看视频一区| 老牛国内精品亚洲成av人片| 爽好久久久欧美精品| 亚洲国产福利| 国产精品永久| 免费观看在线色综合| 三级小说欧洲区亚洲区| 麻豆国产精品| 亚洲欧美网站| 成人一二三区| 国产精品白丝久久av网站| 国产亚洲一区在线| 婷婷激情一区| 国产高清不卡| 精品国产18久久久久久二百| 亚洲精品一级| 天堂成人国产精品一区| 国模 一区 二区 三区| 高清av不卡| a国产在线视频| 国产66精品| 国产精品成久久久久| 欧美国产日本| 日韩欧美四区| 亚洲免费专区| 伊人影院久久| 蜜桃tv一区二区三区| 久久精品高清| 亚洲特级毛片| 国产亚洲高清视频| 蜜桃久久精品一区二区| 日韩专区在线视频| 蜜臀久久99精品久久久久久9| 久久国产福利| 四虎精品一区二区免费| 中文字幕亚洲精品乱码| 日韩精品午夜视频| 国产精品videossex| 你懂的国产精品永久在线| 日本精品国产| 国产九一精品| 日韩黄色大片| 婷婷激情图片久久| 蜜臀久久99精品久久久久久9| 亚洲三级av| 久久久久九九精品影院| 久久久久国产精品一区三寸 | 激情五月综合| 免费视频最近日韩| 国产精品欧美大片| 人人香蕉久久| 日韩**一区毛片| 日韩精品免费观看视频| 亚洲精品成人图区| 另类av一区二区| 国产欧美三级| 久久国产中文字幕| 久久精品999| 亚洲深夜福利| 欧美a一区二区| 天堂av在线一区| 麻豆mv在线观看| 日韩有吗在线观看| 成人小电影网站| 日韩欧美高清一区二区三区| 久久久天天操| 国产伦乱精品| 久久久蜜桃一区二区人| 国产精品网站在线看| 亚洲一区欧美激情| 99久久九九| 精品国产欧美| 欧美精品国产| 视频一区日韩| 亚洲免费激情| 中文字幕在线高清| 精品国产精品国产偷麻豆| 日韩一区二区三区精品 | 蜜臀av免费一区二区三区| 欧美经典一区| 久久电影一区| av一区二区高清| 蜜桃精品在线| 色网在线免费观看| 久久精品福利| 国产高清亚洲| 鲁大师精品99久久久| 国产亚洲一区| 国产亚洲精aa在线看| 午夜久久av| 日本少妇一区二区| 日韩国产一区二| 欧美片第1页综合| 久久av免费| 正在播放日韩精品| 日韩av片子| 成人福利视频| 久久婷婷丁香| 亚洲精品网址| 亚洲精品影院在线观看| 在线精品一区| 欧美精品三级在线| 蜜桃久久久久| 亚洲黄色中文字幕| 99re国产精品| 日韩欧美在线精品| 国产精品毛片久久久| 九九99久久精品在免费线bt| 98精品视频| 国产一区91| 国产日韩亚洲| 久久中文字幕av| 在线精品国产亚洲| 麻豆精品99| 亚洲午夜在线| 国产亚洲精品美女久久| 桃色一区二区| 婷婷五月色综合香五月| 麻豆视频在线看| 中文字幕日本一区二区| 国精品产品一区| 亚洲一区黄色| 亚洲伊人av| 日本天堂一区| 欧美日韩一二三四| 亚洲一区欧美| 亚洲va中文在线播放免费| 日韩精品社区| 蜜桃tv一区二区三区| 国产精品亚洲片在线播放| 国产精品88久久久久久| 国产精品.xx视频.xxtv| 美女91精品| 欧美日韩视频网站| 国产精品亚洲综合色区韩国| 伊人久久婷婷| 日韩欧美1区| 国产精品久久久久久久久久妞妞 | 免费日本视频一区| 色黄视频在线观看| 精品欠久久久中文字幕加勒比| 久久国产精品亚洲77777| 成人羞羞在线观看网站| 免费看久久久| 国产三级一区| 日韩高清在线不卡| 日韩午夜高潮| 日韩精品水蜜桃| 首页国产精品| 免费在线播放第一区高清av| 日韩1区2区3区| 性色一区二区| 亚洲精品一区二区妖精| 久久国产电影| 在线日韩电影| 欧美日韩国产在线观看网站| 欧美成人a交片免费看| 精品三级av| 97精品国产| av资源中文在线| 91精品国产91久久久久久黑人| 丝袜美腿一区| 国产一区二区三区自拍| 欧洲精品一区二区三区| 久久美女性网| 亚洲天堂成人| 国产一级久久| 蜜臀a∨国产成人精品| 蜜臀av亚洲一区中文字幕|