Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截。
拦截原理
1、Filter接口中有一个doFilter方法,开发人员编写的Filter需要实现此方法WEB服务器每次在调用 servlet的service方法之前,会在xml文件中查找当前url地址是否被拦截,如果有,会调用对应的 filter对象的doFilter方法
2、编写好的Filter必须在web.xml中做映射,说明拦截的url地址,此filter才能起作用
3、web服务器在调用doFilter方法时,会传递一个filterChain对象进来,filterChain对象是filter接口中 最重要的一个对象,它也提供了一个doFilter方法,开发人员可以根据需求决定是否调用此方法, 调用该方法,相当于过滤器放行,web服务器就会继续调用servlet的service方法,即web资源就 会被访问,否则web资源不会被访问。
例:public class Filter1 implements Filter {
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System.out.println("before");
//此方法为放行方法,调用了为拦截后执行下面的代码
chain.doFilter(request, response);
System.out.println("after");
}
}
在web.xml文件中进行配置
<filter>
<filter-name>filter1</filter-name>
<filter-class>cn.itcast.filter.Filter1</filter-class>
</filter>
<filter-mapping>
<filter-name>filter1</filter-name>
<url-pattern>/*</url-pattern> 拦截的url地址可以使用 /* *.扩展名
</filter-mapping>
Filter 与Servlet比较
Filter就像一个特殊的Servlet
Filter在web容器启动是就初始化
Filter可以实现拦截功能,因为有个 FilterChain 对象,有个 doFilter方法可以实现对访问资源的放行
Filter可以替代Servlet所有的功能,还多一个放行功能
Filter细节
生命周期
实现Filter的init和destroy方法就可以观察Filter的生命周期web容器启动时,会读web.xml文件, 将所有的Filter都初始化,Filter对象创建后会驻留在内存,当web应用移除或服务器停止时才销 毁。当web应用重新发布的时候,会先调用销毁方法,再初始化Filter。
Filter链中所有的Filter的拦截顺序
按照在web.xml文件中的配置的<filter-mapping>先后顺序来进行拦截。
获得 Filter 的初始化参数
在 web.xml 文件中为Filter 配置初始化参数
<init-param>
<param-name>name</param-name>
<param-value>xxxx</param-value>
</init-param>
Filter拦截方式
Filter的dispatcher元素有4种取值,分别代表四种拦截方式
REQUEST拦截直接的请求方式
INCLUDE拦截页面包含的访问方式
FORWARD拦截请求转发访问方式
ERROR拦截出错页面的访问方式
实现抽象父类
由于Filter没有HttpFilter,这样我们就的在doFilter方法中强转
HttpServletRequest request =(HttpServletRequest) req;
HttpServletResponseresponse = (HttpServletResponse) resp;
并且我们在Fileter中获取FilterConfig还必须将其声明为成员变量,否则在doFilter方法中无法使用,因此, 为了方便期间我们可以写一个抽象父类。
//此案例就交叫做模板方法设计模式:
// 默认的实现类 将来的Filter通过继承此类来实现Filter接口
public abstract class HttpFilter implements Filter {
private FilterConfig filterConfig;
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig = filterConfig;
}
//此方法在设计模式中叫模板方法
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
// 调用子类的方法,由于父类无法知道子类的特有方法,因此声明一个抽象方法,让子类去覆盖,这样就知道子类必定有这个方法
doFilter(request, response, chain);
}
//doFilter方法声明为抽象
//此方法在设计模式中叫做功能方法
public abstract void doFilter(HttpServletRequest request,HttpServletResponse response, FilterChain chain) throws IOException, ServletException ;
public void destroy() {
}
public FilterConfig getFilterConfig() {
return filterConfig;
}
}