Filter简介
Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。
Servlet
API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter。通过Filter技术,开发人员可以实现用户在访问某个目标资源之前,对访问的请求和响应进行拦截,如下所示:
Filter请求和响应
Filter是可以转换请求或响应的标头和内容 (或两者) 的对象。Filter与 web 组件的区别在于, Filter本身通常不会创建响应。相反, Filter提供了可 "附加" 到任何类型的 web 资源的功能。因此, Filter不应依赖于它充当其Filter的 web 资源。这样, 它可以由多种类型的 web 资源组成。
Filter可以执行的主要任务如下所示。
-
查询请求并采取相应的操作。
-
阻止请求和响应对通过任何进一步。
-
修改请求标头和数据。您可以通过提供请求的自定义版本来执行此操作。
-
修改响应标头和数据。您可以通过提供响应的自定义版本来执行此操作。
-
与外部资源交互。
Filter的应用包括身份验证、日志记录、图像转换、数据压缩、加密、令牌流、XML 转换等。
您可以将 web 资源配置为按特定顺序按零、一个或多个Filter链进行筛选。此链是在部署包含该组件的 web 应用程序时指定的, 并且在 web 容器加载组件时实例化。
编程Filter
筛选 APIjavax.servlet
servlet 包中的Filter
"、 FilterChain
和FilterConfig
配置" 接口定义。通过实现Filter
接口来定义Filter。
使用@WebFilter
批注在 web 应用程序中定义Filter。此批注是在类上指定的, 包含有关要声明的Filter的元数据。带注释的Filter必须至少指定一个 URL 模式。这是通过使用批注上urlPatterns
或value
属性来完成的。所有其他属性都是可选的, 具有默认设置。当批注上的唯一属性是 URL 模式时, 请使用值属性; 如果批注上的唯一属性是 url 模式, 则使用value
属性。当也使用其他属性时, 请使用urlPatterns
属性。
使用@WebFilter
批注批注进行批注的类必须实现javax.servlet.Filter
接口。
若要将配置数据添加到Filter, 请指定@WebFilter
批注的initParams
属性。initParams
一个@WebInitParam
批注。下面的代码段定义了一个Filter, 指定了一个初始化参数:
import javax.servlet.Filter;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
@WebFilter(filterName = "TimeOfDayFilter",
urlPatterns = {"/*"},
initParams = {
@WebInitParam(name = "mood", value = "awake")})
public class TimeOfDayFilter implements Filter {
...
Filter
接口中最重要的方法是doFilter
, 它传递请求、响应和筛选链对象。此方法可以执行以下操作。
-
检查请求标头。
-
如果Filter希望修改请求标头或数据, 则自定义请求对象。
-
如果Filter希望修改响应标头或数据, 则自定义响应对象。
-
调用Filter链中的下一个实体。如果当前Filter是以目标 web 组件或静态资源结尾的链中的最后一个Filter, 则下一个实体是链末尾的资源; 如果当前Filter是以目标 web 组件或静态资源结尾的链中的最后一个Filter, 则下一个实体是链的末尾的资源。否则, 它是在 WAR 中配置的下一个Filter。Filter通过调用链对象上的
doFilter
方法来调用下一个实体, 传递使用它调用的请求和响应或它可能创建的包装版本。或者, Filter可以选择通过不调用调用下一个实体来阻止请求。在后一种情况下, Filter负责填写响应。 -
调用链中的下一个Filter后, 检查响应标头。
-
引发异常以指示处理中的错误。
除了doFilter
之外, 还必须实现init
和destroy
方法。在实例化Filter时, 容器将调用init
方法。如果要将初始化参数传递给Filter, 则会从传递给init
FilterConfig
对象检索这些参数.
编程自定义的请求和响应
Filter有多种方法可以修改请求或响应。例如, Filter可以向请求中添加属性, 也可以在响应中插入数据。
修改响应的Filter通常必须在将响应返回到客户端之前捕获该响应。为此, 您需要将备用流传递给生成响应的 servlet。备用流阻止 servlet 在完成时关闭原始响应流, 并允许Filter修改 servlet 的响应。
若要将此备用流传递给 servlet, Filter将创建一个响应包装器, 该包装器将覆盖getWriter
或getOutputStream
方法, 以返回此备用流。包装被传递给Filter链的doFilter
方法。包装方法默认调用到包装的请求或响应对象。
若要重写请求方法, 请将请求包装在扩展ServletRequestWrapper
或HttpServletRequestWrapper
的对象中。若要重写响应方法, 请将响应包装在扩展ServletResponseWrapper
HttpServletResponseWrapper
.
指定Filter映射
web 容器使用Filter映射来决定如何将Filter应用于 web 资源。Filter映射按名称将Filter与 web 组件匹配, 或按 URL 模式将Filter与 web 资源匹配。Filter是按Filter映射在 WAR 的Filter映射列表中出现的顺序调用的。通过使用 NetBeans IDE 或使用 XML 对列表进行编码, 可以在 war 的部署描述符中为其指定Filter映射列表。
如果要将每个请求记录到 web 应用程序, 请将命中计数器Filter映射到 URL 模式/*
.
可以将Filter映射到一个或多个 web 资源, 也可以将多个Filter映射到 web 资源。如图18-1 所示, 其中Filter f1 映射到 Servlets s1、s2 和 s3;过滤器 F2 映射到 servlet S2;和过滤器 F3 映射到 servlets S1 和 S2。
Filter链是传递给Filter的doFilter
方法的对象之一。此链是通过Filter映射间接形成的。链中Filter的顺序与Filter映射在 web 应用程序部署描述符中出现的顺序相同。
当Filter映射到 servlet S1 时, web 容器将调用 F1 的doFilter
方法。S1 筛选链中每个Filter的doFilter
方法是由链中的前面的Filter通过chain.doFilter
方法调用的。由于 S1 的筛选链包含Filter F1 和 F3, 因此 F1 对chain.doFilter
的调用调用Filter F3 的doFilter
方法。当 F3 的doFilter
方法完成时, 控件返回到 F1 的doFilter
方法。