Filter的生命周期同servlet的生命周期是一样的。它们都提供了init(FilterConfig arg0)和destroy()方法来控制。当web容器(如Tomcat、Jboss等)启动的时候,就会自动调用init(FilterConfig arg0)来对filter进行初始化,当关闭web容器,关机,或者reload整个应用时,都会调用destroy()来关闭filter。也就是说,当web容器启动时,filter就被加载到内存,并在destroy()调用之前都常驻内存。Filter只会初始化一次,web容器过滤的时候,都是调用同一个Filter!
发送Http请求——》服务器处理——》返回数据到客户端(浏览器),在这个过程中,都是在同一个线程中处理的!所以可以通过ThreadLocal来实现请求上下文,见博客:http://blog.youkuaiyun.com/yh_zeng2/article/details/73611819
下面通过demo来看看Filter的生命周期:
TestFilter.java:
package filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class TestFilter implements Filter{
@Override
public void destroy() {
System.out.println("调用TestFilter.destroy(),TestFilter对象的HashCode="+this.hashCode()+",当前线程对象HashCode=" + Thread.currentThread().hashCode());
}
@Override
public void doFilter(ServletRequest arg0, ServletResponse arg1,
FilterChain arg2) throws IOException, ServletException {
System.out.println("调用TestFilter.doFilter(),TestFilter对象的HashCode="+this.hashCode()+",当前线程对象HashCode=" + Thread.currentThread().hashCode());
arg2.doFilter(arg0, arg1);
}
@Override
public void init(FilterConfig arg0) throws ServletException {
System.out.println("调用TestFilter.init(),TestFilter对象的HashCode="+this.hashCode()+",当前线程对象HashCode=" + Thread.currentThread().hashCode());
}
}
在web.xml配置Filter:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name></display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<filter>
<filter-name>TestFilter</filter-name>
<filter-class>filter.TestFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>TestFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
index.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
index 页面 <br>
当前线程HashCode=<%=Thread.currentThread().hashCode()%>
MyJsp.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
MyJsp页面 <br>
当前线程HashCode=<%=Thread.currentThread().hashCode()%>
效果:
控制台的打印信息就可以看到,项目启动的时候,就会初始化Fitler!
2017-6-22 22:07:57 org.apache.catalina.startup.HostConfig deployDirectory
信息: Deploying web application directory TestFilter
调用TestFilter.init(),TestFilter对象的HashCode=582407851,当前线程对象HashCode=118572128
2017-6-22 22:07:57 org.apache.coyote.http11.Http11Protocol start
信息: Starting Coyote HTTP/1.1 on http-8080
2017-6-22 22:07:57 org.apache.jk.common.ChannelSocket init
信息: JK: ajp13 listening on /0.0.0.0:8009
2017-6-22 22:07:57 org.apache.jk.server.JkMain start
信息: Jk running ID=0 time=0/24 config=null
2017-6-22 22:07:57 org.apache.catalina.startup.Catalina start
信息: Server startup in 1480 ms
访问http://localhost:8080/TestFilter/ ,页面效果和后台控制台输出如:
调用TestFilter.doFilter(),TestFilter对象的HashCode=582407851,当前线程对象HashCode=81035498
访问http://localhost:8080/TestFilter/MyJsp.jsp,页面效果和后台控制台输出如下图:
调用TestFilter.doFilter(),TestFilter对象的HashCode=582407851,当前线程对象HashCode=1742602365
停止Tomcat服务,通过后台打印信息,就可以看到会调用Filter的destroy方法,如下图:
2017-6-22 22:15:15 org.apache.coyote.http11.Http11Protocol pause
信息: Pausing Coyote HTTP/1.1 on http-8080
2017-6-22 22:15:16 org.apache.catalina.core.StandardService stop
信息: Stopping service Catalina
调用TestFilter.destroy(),TestFilter对象的HashCode=582407851,当前线程对象HashCode=118572128
2017-6-22 22:15:16 org.apache.catalina.core.ApplicationContext log
信息: SessionListener: contextDestroyed()
2017-6-22 22:15:16 org.apache.catalina.core.ApplicationContext log
信息: ContextListener: contextDestroyed()
2017-6-22 22:15:16 org.apache.coyote.http11.Http11Protocol destroy
信息: Stopping Coyote HTTP/1.1 on http-8080