先看一下filter 的简介
web.xml 中声明的每个 filter 在每个虚拟机中仅仅只有一个实例。
(1) 加载和实例化
Web 容器启动时,即会根据 web.xml 中声明的 filter 顺序依次实例化这些 filter。
(2) 初始化
Web 容器调用 init(FilterConfig) 来初始化过滤器。容器在调用该方法时,向过滤器传递 FilterConfig 对象,FilterConfig 的用法和 ServletConfig 类似。利用 FilterConfig 对象可以得到 ServletContext 对象,以及在 web.xml 中配置的过滤器的初始化参数。在这个方法中,可以抛出 ServletException 异常,通知容器该过滤器不能正常工作。此时的 Web 容器启动失败,整个应用程序不能够被访问。实例化和初始化的操作只会在容器启动时执行,而且只会执行一次。
(3) doFilter
doFilter 方法类似于 Servlet 接口的 service 方法。当客户端请求目标资源的时候,容器会筛选出符合 filter-mapping 中的 url-pattern 的 filter,并按照声明 filter-mapping 的顺序依次调用这些 filter 的 doFilter 方法。在这个链式调用过程中,可以调用 chain.doFilter(ServletRequest, ServletResponse) 将请求传给下一个过滤器(或目标资源),也可以直接向客户端返回响应信息,或者利用 RequestDispatcher 的 forward 和 include 方法,以及 HttpServletResponse 的 sendRedirect 方法将请求转向到其它资源。需要注意的是,这个方法的请求和响应参数的类型是 ServletRequest 和 ServletResponse,也就是说,过滤器的使用并不依赖于具体的协议。
(4) 销毁
Web 容器调用 destroy 方法指示过滤器的生命周期结束。在这个方法中,可以释放过滤器使用的资源。
与开发 Servlet 不同的是,Filter 接口并没有相应的实现类可供继承,要开发过滤器,只能直接实现 Filer 接口。
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
现在进入正题,既然要实现Filer 接口,那这个接口里到底是什么样子的?
看看反编译后的接口javax.servlet.Filter
/*jadclipse*/// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
package javax.servlet;
import java.io.IOException;
// Referenced classes of package javax.servlet:
// ServletException, FilterConfig, ServletRequest, ServletResponse,
// FilterChain
public interface Filter
{
public abstract void init(FilterConfig filterconfig)
throws ServletException;
public abstract void doFilter(ServletRequest servletrequest, ServletResponse servletresponse, FilterChain filterchain)
throws IOException, ServletException;
public abstract void destroy();
}
/*
DECOMPILATION REPORT
Decompiled from: D:\j2ee-apache-tomcat-6.0.20\lib\servlet-api.jar
Total time: 46 ms
Jad reported messages/errors:
Exit status: 0
Caught exceptions:
*/
这里我们要注意一下,FilterConfig filterconfig和FilterChain filterchain,因为平时没见过,所以看看源码是啥。
javax.servlet.FilterConfig
/*jadclipse*/// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3) radix(10) lradix(10)
// Source File Name: FilterConfig.java
package javax.servlet;
import java.util.Enumeration;
// Referenced classes of package javax.servlet:
// ServletContext
public interface FilterConfig
{
public abstract String getFilterName();
public abstract ServletContext getServletContext();
public abstract String getInitParameter(String s);
public abstract Enumeration getInitParameterNames();
}
/*
DECOMPILATION REPORT
Decompiled from: D:\j2ee-apache-tomcat-6.0.20\lib\servlet-api.jar
Total time: 31 ms
Jad reported messages/errors:
Exit status: 0
Caught exceptions:
*/
javax.servlet.FilterChain
/*jadclipse*/// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
package javax.servlet;
import java.io.IOException;
// Referenced classes of package javax.servlet:
// ServletException, ServletRequest, ServletResponse
public interface FilterChain
{
public abstract void doFilter(ServletRequest servletrequest, ServletResponse servletresponse)
throws IOException, ServletException;
}
/*
DECOMPILATION REPORT
Decompiled from: D:\j2ee-apache-tomcat-6.0.20\lib\servlet-api.jar
Total time: 47 ms
Jad reported messages/errors:
Exit status: 0
Caught exceptions:
*/
光是看这两个接口中方法的名字大概就可以猜到它可以干嘛了。
下面动手写一个Filter实验一下,看看效果
MyFilter.java
package org.lsy.test.myfilter;
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 MyFilter implements Filter{
protected FilterConfig config;
protected String parameterOne=null;
@Override
public void init(FilterConfig filterconfig) throws ServletException {
// TODO Auto-generated method stub
this.config=filterconfig;//这里我们接收一下这个对象,因为其他地方可能用到。
// 接口 interface FilterConfig中有个方法 public abstract String getInitParameter(String s);
//从web.xml配置文件中获取参数
this.parameterOne = filterconfig.getInitParameter("lsy_filter_test_parameter_one");
System.out.println("getFilterName()---"+filterconfig.getFilterName());
System.out.println("getFilterName()---"+filterconfig.getInitParameterNames());
System.out.println("init方法执行... 使用方法getInitParameter(s)从web.xml配置文件中获取参数lsy_filter_test_parameter_one: "+parameterOne);
}
@Override
public void doFilter(ServletRequest servletrequest,
ServletResponse servletresponse, FilterChain filterchain)
throws IOException, ServletException {
// TODO Auto-generated method stub
//在这里做一些你想做的事,比如设置设置request的编码方式 等。
//servletrequest.setCharacterEncoding("UTF-8");
//这里我们就打印一下,看看效果。
System.out.println("doFilter方法执行......");
filterchain.doFilter(servletrequest,servletresponse); //继续
}
@Override
public void destroy() {
// TODO Auto-generated method stub
System.out.println("destroy方法执行......");
}
}
在web.xml中注册这个Filter
<filter>
<filter-name>myFilter</filter-name>
<filter-class>
org.lsy.test.myfilter.MyFilter
</filter-class>
<init-param>
<param-name>lsy_filter_test_parameter_one</param-name>
<param-value>mynameislushuaiyin</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
现在我们启动程序,发现控制台打印:
getFilterName()---myFilter
getFilterName()---org.apache.catalina.util.Enumerator@83413f
init方法执行... 使用方法getInitParameter(s)从web.xml配置文件中获取参数lsy_filter_test_parameter_one: mynameislushuaiyin
当我们执行任意一个action时注意到控制台打印:
doFilter方法执行......
这说明我们的过滤器起作用了,init方法在程序启动时就走了,也就是
加载servlet容器时就走了。而doFilter方法在有action请求时会走,这样就
起到拦截器的效果。至于destroy方法没看到打印语句,原因不太清楚。