感谢作者:本文内容复制于https://www.runoob.com/w3cnote/filter-filterchain-filterconfig-intro.html
1. Filter程序是一个实现了特殊接口的Java类,与Servlet类似,也是有Servlet容器进行调用和执行的。
2. 当web.xml注册了一个Filter来对某个Servlet进行拦截处理时,他可以决定是否将请求传递给Servlet程序,以及对请求和响应消息是否进行修改。
3. 当Servlet 容器开始调用某个Servlet程序时,如果发现由一个Filter程序对该Servlet进行拦截。而是调用Filter的doFilter()方法,再由doFilter()方法决定是否去激活service()方法。
4. 但是Filter.doFilter()方法不能直接调用Servlet的service()方法,而是调用FilterChain.doFilter方法来激活servlet的service()方法,FilterChain对象时通过Filter.doFilter方法的参数传递进来的。
5. 只要在Filter.doFilter()方法中调用FilterChain.doFilter方法的语句前后增加某些程序代码,这样就可以在Servlet进行响应前后实现某些特殊的功能。
6. 如果filter.dofilter中没有调用FilterChain.doFilter()方法,那么Servlet的service方法就不回被执行。这样通过Filter就可以阻止某些菲方的访问求情。
二:FilterChain
1. 在一个web应用程序中可以注册多个Filter程序,每个Filter都可以对一个或一组Servlet程序进行拦截。如果有多个Filter对某个Servlet程序进行拦截,当针对该Servlet的访问请求到达时,Web容器将把这多个Filter组合成一个FilterChian。也叫过滤器链
2. Filter链中的各个Filter的蓝机器顺序与他们在web.xml文件中的映射顺序时一致的。上一个Filter.doFilter()方法调用FilterChain.doFilter方法将激活下一个Filter.doFilter方法。最后一个Filter.doFilter方法中调用FilterChain.doFilter方法激活Servlet中的service方法。
3. 只要Filterchain中任意一个Filter没有调用FilterChain.doFilter方法,则目标Servlet的service方法就不回执行。
三:Filter接口
一个Filter程序就是一个java类,这个类必须实现Filter接口。javax.servlet.Filter接口中定义了三个方法:int,doFilter,destory.
init方法
在web应用程序启动时,web服务器将根据器web.xml文件的配置信息来创建每个注册的Filter的实例对象。并将其保存在内存中。
Web容器在创建Filter对象之后,立即执行Filter对象的init方法。init方法在生命周期内仅仅被执行一次。Web容器在调用int的方法时会传递一个包含Filter配置和运行环境信息的FilterConfig对象。
public voic init(FilterConfig filterConfig) throws ServletException
开发人员可以在init方法中完成于构造方法类似的初始化功能。要注意的时如果初始化代码要使用FilterConfig对象,这些代码只能在init方法中编写,而不能在构造方法中编写。
doFilter
当一个Filter对象能够拦截访问请求时,Servlet容器将调用Filter容器将调用Filter对象的doFilter方法。
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException.ServletException
destory
该方法在web容器卸载Filter对象之前被调用,也仅执行一次。可以完成于init方法相反的功能。释放Filter对象打开的资源,例如:关闭数据库连接和IO流。
四: FilterChain接口
该接口用于定义一个Filter链对象应该对外提供的方法,这个接口只有一个doFilter方法
public void doFilter(ServletRequest request, ServletResponse response) throws java.io.IOException.ServletException
FilterChain接口的doFilter方法用于通知Web容器把请求交给Filter链中的下一个Filter去处理。如果当前调用此方法Filter链中的最后一个Filter,那么将把请求交给目标Servlet程序处理。
五:FilterConfig接口
1. 与普通的servlet程序一样,Filter程序可能需要访问Servlet容器。Servlet规范将代表ServletContext对象和Filter的配置参数信息封装到一个称之为FilterConfig的对象中。
2. FilterConfig 接口则用于定义FilterConfig对象应该对外提供的方法。以便在Filter程序中可以调用这些方法来获取ServletContext对象,以及获取web.xml文件中Filter设置友好名称和初始化参数
3. FilterConfig 接口定义的各个方法:
a) getFilterName 方法,返回<filter-name>元素设置值
b) getServletContext 方法,返回FilterConfig 对象中所封装的ServletContext引用
c) getInitParameter方法,用于返回web.xml文件中为Filter所设置的某个名称的初始化参数值
d) getInitParameterNames方法,返回一个Enumeration集合对象。
六:Filter 的注册于反射
1. 注册Filter
一个<filter>元素用于注册一个Filter。其中<filter-name>时必须的,<filter-classes>元素也是必须的。<init-param>元素时可选的,可以有多个<init_param>元素
<filter> <filter-name>FirstFilter</filter-name> <filter-class>FirstFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>GB2312</param-value> </init-param> </filter>
2. 映射Filter
<filter-mapping>元素用于设置一个Filter所负责拦截器资源。一个Filter拦截器的资源可以通过两种方式来指定:资源的访问请求路径和Servlet名称
指定资源的访问路径
<filter-mapping> <filter-name>FirstFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
<url-pattern> 元素中的访问路径的设置遵循Servlet URL映射规范
/*:表示拦截所有的访问路径
/filter/*:表示拦截filter目录下的所有的访问请求,如:http://localhost:8888/testFilter-000/filter/xxxxxxx.
/text.html:表示拦截根目录下以test.html为资源名的访问请求,访问链接只会是:http://localhost:8888/text.html
2.1 指定servlet名称
<filter-mapping>
<filter-name>FirstFilter</filter-name>
<servlet-name>default></servlet-name>
<dispatcher>INCLUDE</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
<servlet-name>元素于<url-pattern>元素是二选一的关系,其值是某个Servlet在web.xml文件中的注册名称
<dispatcher>元素有4钟:REQUEST,INCLUDE,FORWARDERROR分别对应Servlet容器调用资源的四种方式
正常调用
通过RequestDispatche.include方法调用
通过RequestDispatcher.forward方法调用
作为错误响应资源调用
七一个传统的Filter程序示例
FitstFilter.java import java.io.IOException; import java.io.PrintWriter; 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 FirstFilter implements Filter { private FilterConfig filterConfig = null; String paramValue = null; @Override public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; paramValue = filterConfig.getInitParameter("encoding"); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("begin headers-------------------"); Enumeration<?> headerNames = ((HttpServletRequest)request).getHeaderNames(); while(headerNames.hasMoreElements()) { String headerName = (String)headerNames.nextElement(); System.out.println(headerName + ": " + ((HttpServletRequest)request).getHeader(headerName)); } System.out.println("end headers-------------------"); //在调用目标前写入响应内容 response.setContentType("text/html; charset=gb2312"); PrintWriter out = response.getWriter(); out.println("IP地址为:" + request.getRemoteHost() + "<br>"); chain.doFilter(request, response); //在目标返回后写入响应内容 out.println("<br>名称为encoding的初始化参数的值为:" + paramValue); out.println("<br>当前Web程序的真实路径为:" + filterConfig.getServletContext().getRealPath("/")); //out.println("<br>修改了test.html文件!"); } @Override public void destroy() { this.filterConfig = null; } }
<filter> <filter-name>FirstFilter</filter-name> <filter-class>FirstFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>GB2312</param-value> </init-param> </filter> <filter-mapping> <filter-name>FirstFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
test.html(位于WebContent路径的filter目录中) <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> 这就是test.html页面的原始内容! </body> </html>
访问:http://localhost:8888/testFilter_001/filter/test.html