JavaWeb中過濾器Filter的用法詳解
過濾器Filter
過濾器通常對一些web資源進行攔截,做完一些處理器再交給下一個過濾器處理,直到所有的過濾器處理器,再調(diào)用servlet實例的service方法進行處理。過濾器可以對request進行處理也可以對response進行處理。
處理順序
如果過濾器鏈順序如上圖所示,那么對request請求的處理順序為1、2、3,對response響應(yīng)的處理順序為3、2、1.
使用場景
用戶權(quán)限驗證
防止亂碼統(tǒng)一對請求和響應(yīng)設(shè)置編碼
對響應(yīng)數(shù)據(jù)壓縮等等
自定義過濾器
實現(xiàn)接口 Filter
public interface Filter { // 由web容器調(diào)用在filter實例化后調(diào)用一次,可以用來配置filter的初始信息等 public void init(FilterConfig filterConfig) throws ServletException; // 執(zhí)行該過濾器邏輯,由ApplicationFilterChain過濾器鏈統(tǒng)一調(diào)用 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException; // 有web容器調(diào)用進行銷毀 public void destroy(); }
寫一個簡單的過濾器,當(dāng)用戶已登錄或者請求的頁面是首頁時不進行過濾攔截繼續(xù)請求下一個過濾器,否則跳轉(zhuǎn)回首頁進行登錄??梢钥吹浇oLoginFilter類加了WebFilter注解,表明過濾器的名稱、作用的servlet以及需要攔截的請求路徑表達式,后續(xù)會將這個過濾器注冊添加到web容器的過濾器鏈中。
@Slf4j(topic = "e") @WebFilter(filterName = "loginFilter", servletNames = "dispatcher", urlPatterns = "*") public class LoginFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { log.info("LoginFilter init"); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { log.info("LoginFilter doFilter"); HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; // 判斷用戶是否登錄 HttpSession session = req.getSession(); String uri = req.getRequestURI(); log.info("requestUri:" + uri); // 已經(jīng)登錄 | 首頁 | 登錄接口不攔截,其他情況重定向回首頁 if (LoginUtil.isLogin(session.getAttribute("username"))) { log.info("用戶已登錄"); chain.doFilter(req, res); } else if (uri.equals(req.getContextPath() + "/") || uri.contains("login")) { log.info("請求首頁/登錄接口"); chain.doFilter(req, res); } else { log.info("未登錄請求轉(zhuǎn)發(fā)到登錄頁"); RequestDispatcher requestDispatcher = req.getRequestDispatcher("/"); requestDispatcher.forward(req, res); } } @Override public void destroy() { } }
當(dāng)然也可以在web.xml文件中配置此過濾器同使用注解是相同的效果,如下:
<filter> <filter-name>LoginFilter</filter-name> <filter-class>com.monian.study.filter.LoginFilter</filter-class> </filter> <filter-mapping> <filter-name>LoginFilter</filter-name> <servlet-name>dispatcher</servlet-name> <url-pattern>*</url-pattern> </filter-mapping>
請求接口日志如下
源碼分析
FilterDef
這個類定義了過濾器的名稱、全限定名、初始化參數(shù)等信息,有了這些信息web容器就可以實例化這個過濾器并進行一些初始化的配置操作,用來生成后續(xù)的ApplicationFilterConfig對象
?public class FilterDef implements Serializable { private static final long serialVersionUID = 1L; private static final StringManager sm = StringManager.getManager(Constants.PACKAGE_NAME); // ------------------------------------------------------------- Properties /** * The description of this filter. */ private String description = null; public String getDescription() { return this.description; } public void setDescription(String description) { this.description = description; } /** * The display name of this filter. */ private String displayName = null; public String getDisplayName() { return this.displayName; } public void setDisplayName(String displayName) { this.displayName = displayName; } /** * The filter instance associated with this definition */ private transient Filter filter = null; public Filter getFilter() { return filter; } public void setFilter(Filter filter) { this.filter = filter; } /** * The fully qualified name of the Java class that implements this filter. */ private String filterClass = null; public String getFilterClass() { return this.filterClass; } public void setFilterClass(String filterClass) { this.filterClass = filterClass; } /** * The name of this filter, which must be unique among the filters * defined for a particular web application. */ private String filterName = null; public String getFilterName() { return this.filterName; } public void setFilterName(String filterName) { if (filterName == null || filterName.equals("")) { throw new IllegalArgumentException( sm.getString("filterDef.invalidFilterName", filterName)); } this.filterName = filterName; } /** * The large icon associated with this filter. */ private String largeIcon = null; public String getLargeIcon() { return this.largeIcon; } public void setLargeIcon(String largeIcon) { this.largeIcon = largeIcon; } /** * The set of initialization parameters for this filter, keyed by * parameter name. */ private final Map<String, String> parameters = new HashMap<>(); public Map<String, String> getParameterMap() { return this.parameters; } /** * The small icon associated with this filter. */ private String smallIcon = null; public String getSmallIcon() { return this.smallIcon; } public void setSmallIcon(String smallIcon) { this.smallIcon = smallIcon; } private String asyncSupported = null; public String getAsyncSupported() { return asyncSupported; } public void setAsyncSupported(String asyncSupported) { this.asyncSupported = asyncSupported; } // --------------------------------------------------------- Public Methods /** * Add an initialization parameter to the set of parameters associated * with this filter. * * @param name The initialization parameter name * @param value The initialization parameter value */ public void addInitParameter(String name, String value) { if (parameters.containsKey(name)) { // The spec does not define this but the TCK expects the first // definition to take precedence return; } parameters.put(name, value); } /** * Render a String representation of this object. */ @Override public String toString() { StringBuilder sb = new StringBuilder("FilterDef["); sb.append("filterName="); sb.append(this.filterName); sb.append(", filterClass="); sb.append(this.filterClass); sb.append("]"); return sb.toString(); } }
FilterMap
這個類主要定義了過濾器的名稱、作用的serlvet、攔截的路徑以及調(diào)度類型等信息,主要用來作為判斷過濾器是否能應(yīng)用在request上。
?public class FilterMap extends XmlEncodingBase implements Serializable { // ------------------------------------------------------------- Properties private static final long serialVersionUID = 1L; /** * The name of this filter to be executed when this mapping matches * a particular request. */ public static final int ERROR = 1; public static final int FORWARD = 2; public static final int INCLUDE = 4; public static final int REQUEST = 8; public static final int ASYNC = 16; // represents nothing having been set. This will be seen // as equal to a REQUEST private static final int NOT_SET = 0; private int dispatcherMapping = NOT_SET; private String filterName = null; public String getFilterName() { return this.filterName; } public void setFilterName(String filterName) { this.filterName = filterName; } // 過濾器作用的servlet的名稱 private String[] servletNames = new String[0]; public String[] getServletNames() { if (matchAllServletNames) { return new String[] {}; } else { return this.servletNames; } } public void addServletName(String servletName) { if ("*".equals(servletName)) { this.matchAllServletNames = true; } else { String[] results = new String[servletNames.length + 1]; System.arraycopy(servletNames, 0, results, 0, servletNames.length); results[servletNames.length] = servletName; servletNames = results; } } /** * The flag that indicates this mapping will match all url-patterns */ private boolean matchAllUrlPatterns = false; public boolean getMatchAllUrlPatterns() { return matchAllUrlPatterns; } /** * The flag that indicates this mapping will match all servlet-names */ private boolean matchAllServletNames = false; public boolean getMatchAllServletNames() { return matchAllServletNames; } /** * 過濾器作用攔截的路徑 */ private String[] urlPatterns = new String[0]; public String[] getURLPatterns() { if (matchAllUrlPatterns) { return new String[] {}; } else { return this.urlPatterns; } } public void addURLPattern(String urlPattern) { addURLPatternDecoded(UDecoder.URLDecode(urlPattern, getCharset())); } public void addURLPatternDecoded(String urlPattern) { if ("*".equals(urlPattern)) { this.matchAllUrlPatterns = true; } else { String[] results = new String[urlPatterns.length + 1]; System.arraycopy(urlPatterns, 0, results, 0, urlPatterns.length); results[urlPatterns.length] = UDecoder.URLDecode(urlPattern); urlPatterns = results; } } /** * This method will be used to set the current state of the FilterMap * representing the state of when filters should be applied. * @param dispatcherString the dispatcher type which should * match this filter */ public void setDispatcher(String dispatcherString) { String dispatcher = dispatcherString.toUpperCase(Locale.ENGLISH); if (dispatcher.equals(DispatcherType.FORWARD.name())) { // apply FORWARD to the global dispatcherMapping. dispatcherMapping |= FORWARD; } else if (dispatcher.equals(DispatcherType.INCLUDE.name())) { // apply INCLUDE to the global dispatcherMapping. dispatcherMapping |= INCLUDE; } else if (dispatcher.equals(DispatcherType.REQUEST.name())) { // apply REQUEST to the global dispatcherMapping. dispatcherMapping |= REQUEST; } else if (dispatcher.equals(DispatcherType.ERROR.name())) { // apply ERROR to the global dispatcherMapping. dispatcherMapping |= ERROR; } else if (dispatcher.equals(DispatcherType.ASYNC.name())) { // apply ERROR to the global dispatcherMapping. dispatcherMapping |= ASYNC; } } public int getDispatcherMapping() { // per the SRV.6.2.5 absence of any dispatcher elements is // equivalent to a REQUEST value if (dispatcherMapping == NOT_SET) return REQUEST; return dispatcherMapping; } public String[] getDispatcherNames() { ArrayList<String> result = new ArrayList<>(); if ((dispatcherMapping & FORWARD) != 0) { result.add(DispatcherType.FORWARD.name()); } if ((dispatcherMapping & INCLUDE) != 0) { result.add(DispatcherType.INCLUDE.name()); } if ((dispatcherMapping & REQUEST) != 0) { result.add(DispatcherType.REQUEST.name()); } if ((dispatcherMapping & ERROR) != 0) { result.add(DispatcherType.ERROR.name()); } if ((dispatcherMapping & ASYNC) != 0) { result.add(DispatcherType.ASYNC.name()); } return result.toArray(new String[result.size()]); } // --------------------------------------------------------- Public Methods /** * Render a String representation of this object. */ @Override public String toString() { StringBuilder sb = new StringBuilder("FilterMap["); sb.append("filterName="); sb.append(this.filterName); for (int i = 0; i < servletNames.length; i++) { sb.append(", servletName="); sb.append(servletNames[i]); } for (int i = 0; i < urlPatterns.length; i++) { sb.append(", urlPattern="); sb.append(urlPatterns[i]); } sb.append("]"); return sb.toString(); } }
初始化過濾器
org.apache.catalina.core.StandardContext#filterStart
? /** * Configure and initialize the set of filters for this Context. * 為此上下文配置和初始化過濾器 * @return <code>true</code> if all filter initialization completed * successfully, or <code>false</code> otherwise. */ public boolean filterStart() { if (getLogger().isDebugEnabled()) { getLogger().debug("Starting filters"); } // Instantiate and record a FilterConfig for each defined filter boolean ok = true; synchronized (filterConfigs) { filterConfigs.clear(); // 遍歷過濾器定義 for (Entry<String,FilterDef> entry : filterDefs.entrySet()) { String name = entry.getKey(); if (getLogger().isDebugEnabled()) { getLogger().debug(" Starting filter '" + name + "'"); } try { // 實例化應(yīng)用過濾器配置 ApplicationFilterConfig filterConfig = new ApplicationFilterConfig(this, entry.getValue()); filterConfigs.put(name, filterConfig); } catch (Throwable t) { t = ExceptionUtils.unwrapInvocationTargetException(t); ExceptionUtils.handleThrowable(t); getLogger().error(sm.getString( "standardContext.filterStart", name), t); ok = false; } } } return ok; }
通過構(gòu)建ApplicationFilterConfig主要是實例化filter,以及初始化init(只會調(diào)用一次),并且該類實現(xiàn)了FilterConfig接口,可以通過ApplicationFilterConfig實例獲取過濾器的名稱、全限定名以及配置的一些初始化參數(shù)信息。
public final class ApplicationFilterConfig implements FilterConfig, Serializable { private static final long serialVersionUID = 1L; static final StringManager sm = StringManager.getManager(Constants.Package); private transient Log log = LogFactory.getLog(ApplicationFilterConfig.class); // must not be static /** * Empty String collection to serve as the basis for empty enumerations. */ private static final List<String> emptyString = Collections.emptyList(); // ----------------------------------------------------------- Constructors // 構(gòu)造方法 ApplicationFilterConfig(Context context, FilterDef filterDef) throws ClassCastException, ClassNotFoundException, IllegalAccessException, InstantiationException, ServletException, InvocationTargetException, NamingException, IllegalArgumentException, NoSuchMethodException, SecurityException { super(); this.context = context; this.filterDef = filterDef; // 過濾器初始化 if (filterDef.getFilter() == null) { getFilter(); } else { this.filter = filterDef.getFilter(); getInstanceManager().newInstance(filter); initFilter(); } } // ----------------------------------------------------- Instance Variables /** * The Context with which we are associated. */ private final transient Context context; /** * The application Filter we are configured for. */ private transient Filter filter = null; /** * The <code>FilterDef</code> that defines our associated Filter. */ private final FilterDef filterDef; /** * the InstanceManager used to create and destroy filter instances. */ private transient InstanceManager instanceManager; /** * JMX registration name */ private ObjectName oname; // --------------------------------------------------- FilterConfig Methods /** * Return the name of the filter we are configuring. */ @Override public String getFilterName() { return filterDef.getFilterName(); } /** * @return The class of the filter we are configuring. */ public String getFilterClass() { return filterDef.getFilterClass(); } /** * Return a <code>String</code> containing the value of the named * initialization parameter, or <code>null</code> if the parameter * does not exist. * * @param name Name of the requested initialization parameter */ @Override public String getInitParameter(String name) { Map<String,String> map = filterDef.getParameterMap(); if (map == null) { return null; } return map.get(name); } /** * Return an <code>Enumeration</code> of the names of the initialization * parameters for this Filter. */ @Override public Enumeration<String> getInitParameterNames() { Map<String,String> map = filterDef.getParameterMap(); if (map == null) { return Collections.enumeration(emptyString); } return Collections.enumeration(map.keySet()); } /** * Return the ServletContext of our associated web application. */ @Override public ServletContext getServletContext() { return this.context.getServletContext(); } /** * Return a String representation of this object. */ @Override public String toString() { StringBuilder sb = new StringBuilder("ApplicationFilterConfig["); sb.append("name="); sb.append(filterDef.getFilterName()); sb.append(", filterClass="); sb.append(filterDef.getFilterClass()); sb.append("]"); return sb.toString(); } // --------------------------------------------------------- Public Methods public Map<String, String> getFilterInitParameterMap() { return Collections.unmodifiableMap(filterDef.getParameterMap()); } // -------------------------------------------------------- Package Methods Filter getFilter() throws ClassCastException, ClassNotFoundException, IllegalAccessException, InstantiationException, ServletException, InvocationTargetException, NamingException, IllegalArgumentException, NoSuchMethodException, SecurityException { // Return the existing filter instance, if any if (this.filter != null) return this.filter; // 根據(jù)過濾器的全限定名通過反射實例化 String filterClass = filterDef.getFilterClass(); this.filter = (Filter) getInstanceManager().newInstance(filterClass); // 初始化過濾器 initFilter(); return this.filter; } // 調(diào)用過濾器的init()方法,我們自定義的過濾器該init方法也由我們自定義 private void initFilter() throws ServletException { if (context instanceof StandardContext && context.getSwallowOutput()) { try { SystemLogHandler.startCapture(); filter.init(this); } finally { String capturedlog = SystemLogHandler.stopCapture(); if (capturedlog != null && capturedlog.length() > 0) { getServletContext().log(capturedlog); } } } else { filter.init(this); } // Expose filter via JMX registerJMX(); } /** * Return the filter definition we are configured for. */ FilterDef getFilterDef() { return this.filterDef; } private InstanceManager getInstanceManager() { if (instanceManager == null) { if (context instanceof StandardContext) { instanceManager = ((StandardContext)context).getInstanceManager(); } else { instanceManager = new DefaultInstanceManager(null, new HashMap<String, Map<String, String>>(), context, getClass().getClassLoader()); } } return instanceManager; } }
創(chuàng)建過濾器鏈 ApplicationFilterChain
web容器會為request創(chuàng)建過濾器鏈,并且經(jīng)過過濾器鏈中每個過濾器的處理后才會繼續(xù)執(zhí)行到servlet
org.apache.catalina.core.ApplicationFilterFactory#createFilterChain
?public static ApplicationFilterChain createFilterChain(ServletRequest request, Wrapper wrapper, Servlet servlet) { // If there is no servlet to execute, return null if (servlet == null) return null; // 創(chuàng)建并初始化一個攔截器對象 ApplicationFilterChain filterChain = null; if (request instanceof Request) { Request req = (Request) request; if (Globals.IS_SECURITY_ENABLED) { // Security: Do not recycle filterChain = new ApplicationFilterChain(); } else { // 從請求中取,復(fù)用過濾器鏈 filterChain = (ApplicationFilterChain) req.getFilterChain(); if (filterChain == null) { filterChain = new ApplicationFilterChain(); req.setFilterChain(filterChain); } } } else { // Request dispatcher in use filterChain = new ApplicationFilterChain(); } // 設(shè)置servlet 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 // 未設(shè)置過濾器直接返回 if ((filterMaps == null) || (filterMaps.length == 0)) return filterChain; // Acquire the information we will need to match filter mappings // 從request獲取dispatcher以匹配 (REQUEST) 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(); } // 獲取servlet名稱 String servletName = wrapper.getName(); // Add the relevant path-mapped filters to this filter chain // 過濾器鏈中添加路徑匹配的過濾器 for (int i = 0; i < filterMaps.length; i++) { // 先匹配dispatcher類型,默認是REQUEST if (!matchDispatcher(filterMaps[i] ,dispatcher)) { continue; } // 再匹配請求路徑 if (!matchFiltersURL(filterMaps[i], requestPath)) continue; ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) context.findFilterConfig(filterMaps[i].getFilterName()); if (filterConfig == null) { // FIXME - log configuration problem continue; } // 添加到過濾器鏈中 filterChain.addFilter(filterConfig); } // Add filters that match on servlet name second // 在根據(jù)servlet名稱匹配過濾器添加到過濾器鏈中 for (int i = 0; i < filterMaps.length; i++) { if (!matchDispatcher(filterMaps[i] ,dispatcher)) { continue; } if (!matchFiltersServlet(filterMaps[i], servletName)) continue; ApplicationFilterConfig filterConfig = (ApplicationFilterConfig) context.findFilterConfig(filterMaps[i].getFilterName()); if (filterConfig == null) { // FIXME - log configuration problem continue; } filterChain.addFilter(filterConfig); } // Return the completed filter chain // 返回完整的過濾器鏈對象 return filterChain; }
執(zhí)行過濾器鏈
ApplicationFilterChain執(zhí)行過濾器方法
?public final class ApplicationFilterChain implements FilterChain { // Used to enforce requirements of SRV.8.2 / SRV.14.2.5.1 private static final ThreadLocal<ServletRequest> lastServicedRequest; private static final ThreadLocal<ServletResponse> lastServicedResponse; static { if (ApplicationDispatcher.WRAP_SAME_OBJECT) { lastServicedRequest = new ThreadLocal<>(); lastServicedResponse = new ThreadLocal<>(); } else { lastServicedRequest = null; lastServicedResponse = null; } } // -------------------------------------------------------------- Constants public static final int INCREMENT = 10; // ----------------------------------------------------- Instance Variables /** * Filters. */ private ApplicationFilterConfig[] filters = new ApplicationFilterConfig[0]; /** * The int which is used to maintain the current position * in the filter chain. */ private int pos = 0; /** * The int which gives the current number of filters in the chain. */ private int n = 0; /** * The servlet instance to be executed by this chain. */ private Servlet servlet = null; /** * Does the associated servlet instance support async processing? */ private boolean servletSupportsAsync = false; /** * The string manager for our package. */ private static final StringManager sm = StringManager.getManager(Constants.Package); /** * Static class array used when the SecurityManager is turned on and * <code>doFilter</code> is invoked. */ private static final Class<?>[] classType = new Class[]{ ServletRequest.class, ServletResponse.class, FilterChain.class}; /** * Static class array used when the SecurityManager is turned on and * <code>service</code> is invoked. */ private static final Class<?>[] classTypeUsedInService = new Class[]{ ServletRequest.class, ServletResponse.class}; // ---------------------------------------------------- FilterChain Methods /** * Invoke the next filter in this chain, passing the specified request * and response. If there are no more filters in this chain, invoke * the <code>service()</code> method of the servlet itself. * * @param request The servlet request we are processing * @param response The servlet response we are creating * * @exception IOException if an input/output error occurs * @exception ServletException if a servlet exception occurs */ // 執(zhí)行過濾器 @Override public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { if( Globals.IS_SECURITY_ENABLED ) { final ServletRequest req = request; final ServletResponse res = response; try { java.security.AccessController.doPrivileged( new java.security.PrivilegedExceptionAction<Void>() { @Override public Void run() throws ServletException, IOException { internalDoFilter(req,res); return null; } } ); } catch( PrivilegedActionException pe) { Exception e = pe.getException(); if (e instanceof ServletException) throw (ServletException) e; else if (e instanceof IOException) throw (IOException) e; else if (e instanceof RuntimeException) throw (RuntimeException) e; else throw new ServletException(e.getMessage(), e); } } else { internalDoFilter(request,response); } } private void internalDoFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { // Call the next filter if there is one // pos表示當(dāng)前正在使用的過濾器在過濾器數(shù)組filters中的序號,每執(zhí)行一次加1 // n表示過濾器數(shù)目 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 { // 調(diào)用doFilter執(zhí)行過濾器的方法 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 // 當(dāng)所有過濾器執(zhí)行完后,調(diào)用servlet的service()方法 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); } } } /** * The last request passed to a servlet for servicing from the current * thread. * * @return The last request to be serviced. */ public static ServletRequest getLastServicedRequest() { return lastServicedRequest.get(); } /** * The last response passed to a servlet for servicing from the current * thread. * * @return The last response to be serviced. */ public static ServletResponse getLastServicedResponse() { return lastServicedResponse.get(); } // -------------------------------------------------------- Package Methods /** * Add a filter to the set of filters that will be executed in this chain. * * @param filterConfig The FilterConfig for the servlet to be executed */ // 添加過濾器配置信息到過濾器鏈 void addFilter(ApplicationFilterConfig filterConfig) { // Prevent the same filter being added multiple times for(ApplicationFilterConfig filter:filters) if(filter==filterConfig) return; if (n == filters.length) { ApplicationFilterConfig[] newFilters = new ApplicationFilterConfig[n + INCREMENT]; System.arraycopy(filters, 0, newFilters, 0, n); filters = newFilters; } filters[n++] = filterConfig; } /** * Release references to the filters and wrapper executed by this chain. */ void release() { for (int i = 0; i < n; i++) { filters[i] = null; } n = 0; pos = 0; servlet = null; servletSupportsAsync = false; } /** * Prepare for reuse of the filters and wrapper executed by this chain. */ void reuse() { pos = 0; } /** * Set the servlet that will be executed at the end of this chain. * * @param servlet The Wrapper for the servlet to be executed */ void setServlet(Servlet servlet) { this.servlet = servlet; } void setServletSupportsAsync(boolean servletSupportsAsync) { this.servletSupportsAsync = servletSupportsAsync; } /** * Identifies the Filters, if any, in this FilterChain that do not support * async. * * @param result The Set to which the fully qualified class names of each * Filter in this FilterChain that does not support async will * be added */ public void findNonAsyncFilters(Set<String> result) { for (int i = 0; i < n ; i++) { ApplicationFilterConfig filter = filters[i]; if ("false".equalsIgnoreCase(filter.getFilterDef().getAsyncSupported())) { result.add(filter.getFilterClass()); } } } }
到此這篇關(guān)于JavaWeb中過濾器Filter的用法詳解的文章就介紹到這了,更多相關(guān)JavaWeb過濾器Filter內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring常用注解 使用注解來構(gòu)造IoC容器的方法
下面小編就為大家分享一篇Spring常用注解 使用注解來構(gòu)造IoC容器的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-01-01Spring中@ConfigurationProperties的用法解析
這篇文章主要介紹了Spring中@ConfigurationProperties的用法解析,傳統(tǒng)的Spring一般都是基本xml配置的,后來spring3.0新增了許多java config的注解,特別是spring boot,基本都是清一色的java config,需要的朋友可以參考下2023-11-11