servlet中Filter过滤器介绍

过滤器是指拦截请求,并对传给被请求资源的ServletRequest 或 ServletResponse 进行处理的一个对象。过滤器可以用于登录、加密和解密、会话检查等等。过滤器可以配置为拦截一个或多个资源。如果同一个资源或同一组资源中应用了多个过滤器,则调用顺序有显示显得比较重要,这时候就需要部署描述符(web.xml)来控制其先后顺序。

       filter过滤器中使用的接口包括Filter、FilterConfig和FilterChain。每个接口中包含若干方法,接下来我们按照filter的生命周期来介绍接口及中间对应的方法。

       过滤器类必须实现javax.servlet.Filter接口。这个接口为每个过滤器暴露3个生命周期方法,init、doFilter 和 destory。

[java]  view plain  copy
  1. package javax.servlet;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. /** 
  6.  * A filter is an object that performs filtering tasks on either the request to 
  7.  * a resource (a servlet or static content), or on the response from a resource, 
  8.  * or both. <br> 
  9.  * @since Servlet 2.3 
  10.  */  
  11. public interface Filter {  
  12.   
  13.     /** 
  14.      * Called by the web container to indicate to a filter that it is being 
  15.      * placed into service. The servlet container calls the init method exactly 
  16.      * once after instantiating the filter. The init method must complete 
  17.      * successfully before the filter is asked to do any filtering work. <br> 
  18.      * <br> 
  19.      * The web container cannot place the filter into service if the init method 
  20.      * either<br> 
  21.      * 1.Throws a ServletException <br> 
  22.      * 2.Does not return within a time period defined by the web container 
  23.      */  
  24.     public void init(FilterConfig filterConfig) throws ServletException;  
  25.   
  26.     /** 
  27.      * The <code>doFilter</code> method of the Filter is called by the container 
  28.      * each time a request/response pair is passed through the chain due to a 
  29.      * client request for a resource at the end of the chain. The FilterChain 
  30.      * passed in to this method allows the Filter to pass on the request and 
  31.      * response to the next entity in the chain. 
  32.      * <p> 
  33.      * A typical implementation of this method would follow the following 
  34.      * pattern:- <br> 
  35.      * 1. Examine the request<br> 
  36.      * 2. Optionally wrap the request object with a custom implementation to 
  37.      * filter content or headers for input filtering <br> 
  38.      * 3. Optionally wrap the response object with a custom implementation to 
  39.      * filter content or headers for output filtering <br> 
  40.      * 4. a) <strong>Either</strong> invoke the next entity in the chain using 
  41.      * the FilterChain object (<code>chain.doFilter()</code>), <br> 
  42.      * 4. b) <strong>or</strong> not pass on the request/response pair to the 
  43.      * next entity in the filter chain to block the request processing<br> 
  44.      * 5. Directly set headers on the response after invocation of the next 
  45.      * entity in the filter chain. 
  46.      **/  
  47.     public void doFilter(ServletRequest request, ServletResponse response,  
  48.             FilterChain chain) throws IOException, ServletException;  
  49.   
  50.     /** 
  51.      * Called by the web container to indicate to a filter that it is being 
  52.      * taken out of service. This method is only called once all threads within 
  53.      * the filter's doFilter method have exited or after a timeout period has 
  54.      * passed. After the web container calls this method, it will not call the 
  55.      * doFilter method again on this instance of the filter. <br> 
  56.      * <br> 
  57.      *  
  58.      * This method gives the filter an opportunity to clean up any resources 
  59.      * that are being held (for example, memory, file handles, threads) and make 
  60.      * sure that any persistent state is synchronized with the filter's current 
  61.      * state in memory. 
  62.      */  
  63.     public void destroy();  
  64.   
  65. }  

       当过滤器启动服务的时候,比如应用程序启动时,servlet容器就会调用init方法。换句话说,不用等到调用与被过滤器相关的资源之后,才调用init方法。这个方法只调用一次,并且应该包含该过滤器的初始化代码。

init方法的签名如下:

void init(FilterConfig filterConfig)

注意:servlet容器给init方法传递了一个FilterConfig。

FilterConfig 接口

[java]  view plain  copy
  1. package javax.servlet;  
  2.   
  3. import java.util.Enumeration;  
  4.   
  5. /** 
  6.  * A filter configuration object used by a servlet container to pass information 
  7.  * to a filter during initialization. 
  8.  */  
  9. public interface FilterConfig {  
  10.   
  11.     /** 
  12.      * Returns the filter-name of this filter as defined in the deployment 
  13.      * descriptor. 
  14.      */  
  15.     public String getFilterName();  
  16.   
  17.     /** 
  18.      * Returns a reference to the {@link ServletContext} in which the caller is 
  19.      * executing. 
  20.      */  
  21.     public ServletContext getServletContext();  
  22.   
  23.     /** 
  24.      * Returns a <code>String</code> containing the value of the named 
  25.      * initialization parameter, or <code>null</code> if the parameter does not 
  26.      * exist. 
  27.      */  
  28.     public String getInitParameter(String name);  
  29.   
  30.     /** 
  31.      * Returns the names of the filter's initialization parameters as an 
  32.      * <code>Enumeration</code> of <code>String</code> objects, or an empty 
  33.      * <code>Enumeration</code> if the filter has no initialization parameters. 
  34.      */  
  35.     public Enumeration<String> getInitParameterNames();  
  36.   
  37. }  

      每次调用与过滤器相关的资源时,servlet容器都会调用Filter实例的doFilter方法。该方法会收到一个ServletRequest、ServletResponse和FilterChain。

doFilter方法的签名如下:

public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)

扫描二维码关注公众号,回复: 1682511 查看本文章

      doFilter的实现可以访问ServletRequest 和 ServletResponse。因此,可以在ServletRequest中添加属性,或者在ServletResponse中添加一个标头,甚至可以对ServletRequest 或 ServletResponse进行修复,改变它们的行为。

      doFilter方法实现中最后一行代码应该是调用FilterChain中的doFilter方法,

FilterChain.doFilter方法签名为

public void doFilter(ServletRequest request, ServletResponse response)

      一个资源可以与多个过滤器关联,FilterChain.doFilter( ) 通常会引发调用链中的下一个过滤器被调用。在链中的最后一个过滤器中调用FilterChain.doFilter( )会引发资源本身被调用。如果你没有在 Filter.doFilter( )方法实现代码的最后调用FilterChain.doFilter( )方法,那么程序的处理将会在这里停止,并且不会调用请求。

注意,doFilter方法是FilterChain接口中唯一的方法,它与Filter中的doFilter方法不同。在FilterChain中,doFilter只有两个参数,而不是三个。

Filter中最后一个生命周期方法是destory,其方法签名为

void destroy()

这个方法在过滤器即将终止服务之前,由Servlet调用,一般发生在应用程序停止的时候。

Demo

[java]  view plain  copy
  1. package com.filter;  
  2.   
  3. import java.io.IOException;  
  4. import java.util.Enumeration;  
  5.   
  6. import javax.servlet.Filter;  
  7. import javax.servlet.FilterChain;  
  8. import javax.servlet.FilterConfig;  
  9. import javax.servlet.ServletException;  
  10. import javax.servlet.ServletRequest;  
  11. import javax.servlet.ServletResponse;  
  12. import javax.servlet.http.HttpServletRequest;  
  13.   
  14. public class HttpFilter implements Filter {  
  15.   
  16.     @Override  
  17.     public void destroy() {  
  18.         System.out.println("过滤器生命终止");  
  19.     }  
  20.   
  21.     @Override  
  22.     public void doFilter(ServletRequest arg0, ServletResponse arg1,  
  23.             FilterChain arg2) throws IOException, ServletException {  
  24.         HttpServletRequest req = (HttpServletRequest)arg0;  
  25.         // 打印请求的URL  
  26.         System.out.println("filter1 " + req.getRequestURL());  
  27.         arg2.doFilter(arg0, arg1);  
  28.     }  
  29.   
  30.     @Override  
  31.     public void init(FilterConfig arg0) throws ServletException {  
  32.         System.out.println("过滤器生命开始");  
  33.           
  34.         String filterName = arg0.getFilterName();  
  35.         System.out.println("过滤器名为 " + filterName);  
  36.           
  37.         // 遍历过滤器中的参数和对应值  
  38.         Enumeration<String> initParas = arg0.getInitParameterNames();  
  39.         String paraName;  
  40.         String paraValue;  
  41.         while (initParas.hasMoreElements()) {  
  42.             paraName = initParas.nextElement();  
  43.             paraValue = arg0.getInitParameter(paraName);  
  44.             System.out.println(paraName + " = " + paraValue);  
  45.         }  
  46.     }  
  47. }  

部署描述符web.xml中配置为
[html]  view plain  copy
  1. <filter>  
  2.   <filter-name>httpFilter</filter-name>  
  3.   <filter-class>com.filter.HttpFilter</filter-class>  
  4.     <init-param>  
  5.         <param-name>creater</param-name>  
  6.         <param-value>zhangqi</param-value>  
  7.     </init-param>  
  8.     <init-param>  
  9.         <param-name>createrDate</param-name>  
  10.         <param-value>2017-05-20</param-value>  
  11.     </init-param>  
  12. </filter>  
  13. <filter-mapping>  
  14.   <filter-name>httpFilter</filter-name>  
  15.   <url-pattern>/*</url-pattern>  
  16. </filter-mapping>  

服务器启动时,可以在控制台中看到
[plain]  view plain  copy
  1. 过滤器生命开始  
  2. 过滤器名为 httpFilter  
  3. creater = zhangqi  
  4. createrDate = 2017-05-20  
说明,过滤器是在服务器启动时加载,且调用了init方法。

然后我们访问下初始化页面,控制台可以看到

[plain]  view plain  copy
  1. filter1 http://localhost:8080/servletDemo/  
说明,这个请求被过滤器拦截,过滤器打印出了请求的URL。

最后,我们停止tomcat服务器,控制台可以看到

[plain]  view plain  copy
  1. 过滤器生命终止  
说明,服务器停止前,服务终止时,会调用destory方法,销毁过滤器对象。

转载至: http://blog.csdn.net/magi1201/article/details/43839117

猜你喜欢

转载自blog.csdn.net/l18848956739/article/details/79518836