过滤器是指拦截请求,并对传给被请求资源的ServletRequest 或 ServletResponse 进行处理的一个对象。过滤器可以用于登录、加密和解密、会话检查等等。过滤器可以配置为拦截一个或多个资源。如果同一个资源或同一组资源中应用了多个过滤器,则调用顺序有显示显得比较重要,这时候就需要部署描述符(web.xml)来控制其先后顺序。
filter过滤器中使用的接口包括Filter、FilterConfig和FilterChain。每个接口中包含若干方法,接下来我们按照filter的生命周期来介绍接口及中间对应的方法。
过滤器类必须实现javax.servlet.Filter接口。这个接口为每个过滤器暴露3个生命周期方法,init、doFilter 和 destory。
- package javax.servlet;
- import java.io.IOException;
- /**
- * A filter is an object that performs filtering tasks on either the request to
- * a resource (a servlet or static content), or on the response from a resource,
- * or both. <br>
- * @since Servlet 2.3
- */
- public interface Filter {
- /**
- * Called by the web container to indicate to a filter that it is being
- * placed into service. The servlet container calls the init method exactly
- * once after instantiating the filter. The init method must complete
- * successfully before the filter is asked to do any filtering work. <br>
- * <br>
- * The web container cannot place the filter into service if the init method
- * either<br>
- * 1.Throws a ServletException <br>
- * 2.Does not return within a time period defined by the web container
- */
- public void init(FilterConfig filterConfig) throws ServletException;
- /**
- * The <code>doFilter</code> method of the Filter is called by the container
- * each time a request/response pair is passed through the chain due to a
- * client request for a resource at the end of the chain. The FilterChain
- * passed in to this method allows the Filter to pass on the request and
- * response to the next entity in the chain.
- * <p>
- * A typical implementation of this method would follow the following
- * pattern:- <br>
- * 1. Examine the request<br>
- * 2. Optionally wrap the request object with a custom implementation to
- * filter content or headers for input filtering <br>
- * 3. Optionally wrap the response object with a custom implementation to
- * filter content or headers for output filtering <br>
- * 4. a) <strong>Either</strong> invoke the next entity in the chain using
- * the FilterChain object (<code>chain.doFilter()</code>), <br>
- * 4. b) <strong>or</strong> not pass on the request/response pair to the
- * next entity in the filter chain to block the request processing<br>
- * 5. Directly set headers on the response after invocation of the next
- * entity in the filter chain.
- **/
- public void doFilter(ServletRequest request, ServletResponse response,
- FilterChain chain) throws IOException, ServletException;
- /**
- * Called by the web container to indicate to a filter that it is being
- * taken out of service. This method is only called once all threads within
- * the filter's doFilter method have exited or after a timeout period has
- * passed. After the web container calls this method, it will not call the
- * doFilter method again on this instance of the filter. <br>
- * <br>
- *
- * This method gives the filter an opportunity to clean up any resources
- * that are being held (for example, memory, file handles, threads) and make
- * sure that any persistent state is synchronized with the filter's current
- * state in memory.
- */
- public void destroy();
- }
当过滤器启动服务的时候,比如应用程序启动时,servlet容器就会调用init方法。换句话说,不用等到调用与被过滤器相关的资源之后,才调用init方法。这个方法只调用一次,并且应该包含该过滤器的初始化代码。
init方法的签名如下:
void init(FilterConfig filterConfig)
注意:servlet容器给init方法传递了一个FilterConfig。
FilterConfig 接口
- package javax.servlet;
- import java.util.Enumeration;
- /**
- * A filter configuration object used by a servlet container to pass information
- * to a filter during initialization.
- */
- public interface FilterConfig {
- /**
- * Returns the filter-name of this filter as defined in the deployment
- * descriptor.
- */
- public String getFilterName();
- /**
- * Returns a reference to the {@link ServletContext} in which the caller is
- * executing.
- */
- public ServletContext getServletContext();
- /**
- * Returns a <code>String</code> containing the value of the named
- * initialization parameter, or <code>null</code> if the parameter does not
- * exist.
- */
- public String getInitParameter(String name);
- /**
- * Returns the names of the filter's initialization parameters as an
- * <code>Enumeration</code> of <code>String</code> objects, or an empty
- * <code>Enumeration</code> if the filter has no initialization parameters.
- */
- public Enumeration<String> getInitParameterNames();
- }
每次调用与过滤器相关的资源时,servlet容器都会调用Filter实例的doFilter方法。该方法会收到一个ServletRequest、ServletResponse和FilterChain。
doFilter方法的签名如下:
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
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
- package com.filter;
- import java.io.IOException;
- import java.util.Enumeration;
- import javax.servlet.Filter;
- import javax.servlet.FilterChain;
- import javax.servlet.FilterConfig;
- import javax.servlet.ServletException;
- import javax.servlet.ServletRequest;
- import javax.servlet.ServletResponse;
- import javax.servlet.http.HttpServletRequest;
- public class HttpFilter implements Filter {
- @Override
- public void destroy() {
- System.out.println("过滤器生命终止");
- }
- @Override
- public void doFilter(ServletRequest arg0, ServletResponse arg1,
- FilterChain arg2) throws IOException, ServletException {
- HttpServletRequest req = (HttpServletRequest)arg0;
- // 打印请求的URL
- System.out.println("filter1 " + req.getRequestURL());
- arg2.doFilter(arg0, arg1);
- }
- @Override
- public void init(FilterConfig arg0) throws ServletException {
- System.out.println("过滤器生命开始");
- String filterName = arg0.getFilterName();
- System.out.println("过滤器名为 " + filterName);
- // 遍历过滤器中的参数和对应值
- Enumeration<String> initParas = arg0.getInitParameterNames();
- String paraName;
- String paraValue;
- while (initParas.hasMoreElements()) {
- paraName = initParas.nextElement();
- paraValue = arg0.getInitParameter(paraName);
- System.out.println(paraName + " = " + paraValue);
- }
- }
- }
部署描述符web.xml中配置为
- <filter>
- <filter-name>httpFilter</filter-name>
- <filter-class>com.filter.HttpFilter</filter-class>
- <init-param>
- <param-name>creater</param-name>
- <param-value>zhangqi</param-value>
- </init-param>
- <init-param>
- <param-name>createrDate</param-name>
- <param-value>2017-05-20</param-value>
- </init-param>
- </filter>
- <filter-mapping>
- <filter-name>httpFilter</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
服务器启动时,可以在控制台中看到
- 过滤器生命开始
- 过滤器名为 httpFilter
- creater = zhangqi
- createrDate = 2017-05-20
然后我们访问下初始化页面,控制台可以看到
- filter1 http://localhost:8080/servletDemo/
最后,我们停止tomcat服务器,控制台可以看到
- 过滤器生命终止
转载至: http://blog.csdn.net/magi1201/article/details/43839117