Servlet Filter 又称 Servlet 过滤器,它是在 Servlet 2.3 规范中定义的,能够对 Servlet 容器传给 Web 资源的 request 对象和 response 对象进行检查和修改。

Filter 不是 Servlet,不能直接访问,它本身也不能生成 request 对象和 response 对象,它只能为 Web 资源提供以下过滤功能:

  • 在 Web 资源被访问前,检查 request 对象,修改请求头和请求正文,或对请求进行预处理操作。
  • 将请求传递到下一个过滤器或目标资源。
  • 在 Web 资源被访问后,检查 response 对象,修改响应头和响应正文。

注意:过滤器并不是必须要将请求传递到下一个过滤器或目标资源,它可以自行对请求进行处理,并发送响应给客户端,也可以将请求转发或重定向到其他的 Web 资源。

Filter 是 Servlet 规范中最实用的技术,通过它可以对服务器管理的所有 Web 资源(例如 JSP、Servlet、静态 HTML 文件、静态图片等)进行拦截,从而实现一些特殊的功能,例如用户的权限控制、过滤敏感词、设置统一编码格式等。

Filter 接口

与开发 Servlet 需要实现 javax.servlet.Servlet 接口类似,开发过滤器要实现 javax.servlet.Filter 接口,并提供一个公开的不带参的构造方法。在 Filter 接口中,定义了 3 个方法,如下表所示。

返回值类型 方法 功能描述
void init (FilterConfig filterConfig) 该方法用于初始化过滤器。
void doFilter(ServletRequest request,SeivletResponse response, FilterChain chain) 该方法完成实际的过滤操作,当客户端请求的 URL 与过滤器映射的 URL 匹配时,容器会先调用该方法对请求进行拦截。
参数 request 和 response 表示请求和响应对象。
参数 chain 代表当前 Filter 链对象,在该方法内部,调用 chain.doFilter() 方法,才能把请求交付给 Filter 链中的下一个 Filter 或者 Web 资源。
void destroy() 该方法在销毁 Filter 对象之前被调用,用于释放被 Filter 对象占用的资源。 

Filter 的工作流程

Filter的工作流程如下:

  1. 客户端请求访问容器内的 Web 资源。
  2. Servlet 容器接收请求,并针对本次请求分别创建一个 request 对象和 response 对象。
  3. 请求到达 Web 资源之前,先调用 Filter 的 doFilter() 方法,检查 request 对象,修改请求头和请求正文,或对请求进行预处理操作。
  4. 在 Filter 的 doFilter() 方法内,调用 FilterChain.doFilter() 方法,将请求传递给下一个过滤器或目标资源。
  5. 目标资源生成响应信息返回客户端之前,处理控制权会再次回到 Filter 的 doFilter() 方法,执行 FilterChain.doFilter() 后的语句,检查 response 对象,修改响应头和响应正文。
  6. 响应信息返回客户端。

Filter 的生命周期

Filter 的生命周期分为 3 个阶段:

  1. 初始化阶段
  2. 拦截和过滤阶段
  3. 销毁阶段

1. 初始化阶段

Servlet 容器负责加载和实例化 Filter。容器启动时,读取 web.xml 或 @WebFilter 的配置信息对所有的过滤器进行加载和实例化。

加载和实例化完成后,Servlet 容器调用 init() 方法初始化 Filter 实例。在 Filter 的生命周期内, init() 方法只执行一次。

2. 拦截和过滤阶段

该阶段是 Filter 生命周期中最重要的阶段。当客户端请求访问 Web 资源时,Servlet 容器会根据 web.xml 或 @WebFilter 的过滤规则进行检查。当客户端请求的 URL 与过滤器映射匹配时,容器将该请求的 request 对象、response 对象以及 FilterChain 对象以参数的形式传递给 Filter 的 doFilter() 方法,并调用该方法对请求/响应进行拦截和过滤。

3. 销毁阶段

Filter 对象创建后会驻留在内存中,直到容器关闭或应用被移除时销毁。销毁 Filter 对象之前,容器会先调用 destory() 方法,释放过滤器占用的资源。在 Filter 的生命周期内,destory() 只执行一次。

注册与映射 Filter

注册和映射 Filter 有 2 种方式:

  1. 通过 web.xml 配置
  2. 通过 @WebFilter 注解配置

1. 通过web.xml配置

在 web.xml 中,通过 <filter> 及其子元素注册 Filter,代码如下。

<filter>
<filter-name>myFilter</filter-name>
<filter-class>net.biancheng.www.MyFilter</filter-class>
<init-param>
<param-name>name</param-name>
<param-value>编程帮</param-value>
</init-param>
<init-param>
<param-name>URL</param-name>
<param-value>www.biancheng.net</param-value>
</init-param>
</filter>

以上元素说明如下:

  • <filter>  用于注册过滤器
  • <filter-name> 是<filter> 元素的子元素, 用于指定过滤器的注册名,该元素的内容不能为空。
  • <filter-class> 是<filter> 元素的子元素,用于指定过滤器的完整限定名(包名+类名)。
  • <init-param> 是<filter> 元素的子元素,用于为过滤器指定初始化参数,它的子元素 <param-name> 指定参数的名称,<param-value> 指定参数的值。

在 web.xml 中,通过使用 <filter-mapping> 及其子元素映射 Filter,代码如下。

<filter-mapping>
<filter-name>myFilter</filter-name>
<url-pattern>/login</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
<filter-mapping>
<filter-name>myFilter</filter-name>
<servlet-name>ServletDemo</servlet-name>
</filter-mapping>

以上元素说明如下:

  • <filter-mapping> 元素用于设置 Filter 负责拦截的资源。
  • <filter-name> 是<filter-mapping> 元素的子元素,用于设置 Filter 的注册名,该值必须在 <filter>元素的子元素 <filter-name>  中声明过。
  • <url-pattern> 是<filter-mapping> 元素的子元素,用于设置 Filter 拦截的请求路径。
  • <servlet-name> 是<filter-mapping> 元素的子元素,用于设置 Filter 拦截的 Servlet 名称。
  • <dispatcher> 是<filter-mapping> 元素的子元素,用于指定 Filter 拦截的资源被 Servlet 容器调用的方式,可以是 REQUEST、INCLUDE、FORWARD 和 ERROR 之一,默认 REQUEST。用户可以设置多个 <dispatcher> 子元素指定 Filter 对资源的多种调用方式进行拦截。

<dispatcher> 元素的取值及其意义:

  • REQUEST:当用户直接访问页面时,容器将会调用过滤器。如果目标资源是通过 RequestDispatcher 的 include() 或 forward() 方法访问,则该过滤器就不会被调用。
  • INCLUDE:如果目标资源通过 RequestDispatcher 的 include() 方法访问,则该过滤器将被调用。除此之外,该过滤器不会被调用。
  • FORWARD:如果目标资源通过 RequestDispatcher 的 forward() 方法访问,则该过滤器将被调用,除此之外,该过滤器不会被调用。
  • ERROR:如果目标资源通过声明式异常处理机制访问,则该过滤器将被调用。除此之外,过滤器不会被调用。

2. 使用 @WebFilter 注解进行配置

@WebFilter 注解也可以对过滤器进行配置,容器在部署应用时,会根据其具体属性配置将相应的类部署为过滤器。

@WebFilter 注解具有下表给出的一些常用属性。以下所有属性均为可选属性,但 value、urlPatterns、servletNames 三者必需至少包含一个,且 value 和 urlPatterns 不能共存,如果同时指定,通常忽略 value 的取值。

属性名 类型 描述
filterName String 指定过滤器的 name 属性,等价于 <filter-name>。
urlPatterns String[] 指定过滤器的 URL 匹配模式。等价于 <url-pattern> 标签。
value String[] 该属性等价于 urlPatterns 属性,但是两者不能同时使用。
servletNames String[] 指定过滤器将应用于哪些 Servlet。取值是 @WebServlet 中 filterName 属性的取值,或者 web.xml 中 <servlet-name> 的取值。
dispatcherTypes DispatcherType 指定过滤器拦截的资源被 Servlet 容器调用的方式。具体取值包括: ASYNC、ERROR、FORWARD、INCLUDE、REQUEST。
initParams WebInitParam[] 指定一组过滤器初始化参数,等价于 <init-param> 标签。
asyncSupported boolean 声明过滤器是否支持异步操作模式,等价于 <async-supported> 标签。
description String 指定过滤器的描述信息,等价于 <description> 标签。
displayName String 指定过滤器的显示名,等价于 <display-name> 标签。

使用 @WebFilter 注解配置过滤器,代码如下。

package net.biancheng.www.filter;
import java.io.IOException;
import java.util.logging.LogRecord;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
@WebFilter(
dispatcherTypes = {
DispatcherType.REQUEST,
DispatcherType.FORWARD,
DispatcherType.INCLUDE,
DispatcherType.ERROR
},
asyncSupported = true,
description = "过滤器4",
urlPatterns = {"/login"},
initParams = {
@WebInitParam(name = "name", value = "编程帮", description = "name的描述")
},
servletNames = {"SuccessServlet"})
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
}
}

Servlet Filter(过滤器)的更多相关文章

  1. Servlet Filter 过滤器

    Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源: 例如Jsp, Servlet, 静态图片文件或静态 ht ...

  2. Servlet Filter 过滤器 对指定页面不拦截

    package niit.dxs.controller; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; i ...

  3. JavaWeb -- Servlet Filter 过滤器

    1. Servlet API中提供了一个Filter接口,开发web应用时,如果编写的Java类实现了这个接口,则把这个java类称之为过滤器Filter.通过Filter技术,开发人员可以实现用户在 ...

  4. servlet之filter过滤器

    1.Servlet 过滤器有以下目的 在客户端的请求访问后端资源之前,拦截这些请求. 在服务器的响应发送回客户端之前,处理这些响应. 2.Filter接口 1.每一个过滤器都需直接或间接继承Filte ...

  5. Servlet的过滤器Filter

    Servlet 编写过滤器 Servlet 过滤器可以动态地拦截请求和响应,以变换或使用包含在请求或响应中的信息. 可以将一个或多个 Servlet 过滤器附加到一个 Servlet 或一组 Serv ...

  6. 理解Servlet过滤器 (javax.servlet.Filter)

    过滤器(Filter)的概念 过滤器位于客户端和web应用程序之间,用于检查和修改两者之间流过的请求和响应. 在请求到达Servlet/JSP之前,过滤器截获请求. 在响应送给客户端之前,过滤器截获响 ...

  7. 【Servlet】Filter过滤器的编写和配置

    Servlet的Filter介绍 在Servlet作为过滤器使用时,它可以对客户的请求进行过滤处理,当它处理完成后,它会交给下一个过滤器处理,就这样,客户的请求在过滤链里一个个处理,直到请求发送到目标 ...

  8. Servlet的学习之Filter过滤器技术(1)

    本篇将讲诉Servlet中一项非常重要的技术,Filter过滤器技术.通过过滤器,可以对来自客户端的请求进行拦截,进行预处理或者对最终响应给客户端的数据进行处理后再输出. 要想使用Filter过滤器, ...

  9. 【转载】Servlet Filter(过滤器)、Filter是如何实现拦截的、Filter开发入门

    Servlet Filter(过滤器).Filter是如何实现拦截的.Filter开发入门 Filter简介 Filter也称之为过滤器,它是Servlet技术中最激动人心的技术,WEB开发人员通过F ...

  10. Servlet之过滤器(Filter)和监听器(Listener)

    过滤器 过滤器是一个java组件,可以拦截发送至某个servelet,jsp页面或静态页面的请求,可以在响应发送到客户之前进行拦截 工作原理: 过滤器类必须实现 Filter 接口,包含的方法如下: ...

随机推荐

  1. ajax 有终止请求 abort 那 axios 有没有,怎么实现

    见代码 class View extends Component { constructor(props){ super(props); this.state = { cancel:null, can ...

  2. react中使用Input表单双向绑定方法

    input react 表单 input 密码框在谷歌浏览器下 会有黄色填充 官网的不太用,这个比较好用 type="password" autoComplete="ne ...

  3. SpringBoot简单整合分布式任务调度平台(XXL-JOB)

    官方文档:https://www.xuxueli.com/xxl-job/#%E3%80%8A%E5%88%86%E5%B8%83%E5%BC%8F%E4%BB%BB%E5%8A%A1%E8%B0%8 ...

  4. 再谈多线程模型之生产者消费者(总结)(c++11实现)

    0.关于 为缩短篇幅,本系列记录如下: 再谈多线程模型之生产者消费者(基础概念)(c++11实现) 再谈多线程模型之生产者消费者(单一生产者和单一消费者)(c++11实现) 再谈多线程模型之生产者消费 ...

  5. 【九度OJ】题目1174:查找第K小数 解题报告

    [九度OJ]题目1174:查找第K小数 解题报告 标签(空格分隔): 九度OJ 原题地址:http://ac.jobdu.com/problem.php?pid=1174 题目描述: 查找一个数组的第 ...

  6. Beautiful Walls

    [1553] Beautiful Walls 时间限制: 1000 ms 内存限制: 65535 K 问题描述 To simplify the building process, XadillaX b ...

  7. 【死磕Java并发】-----Java内存模型之重排序

    在执行程序时,为了提供性能,处理器和编译器常常会对指令进行重排序,但是不能随意重排序,不是你想怎么排序就怎么排序,它需要满足以下两个条件: 在单线程环境下不能改变程序运行的结果: 存在数据依赖关系的不 ...

  8. 【操作系统】Linux bash常用函数路径配置

    临时方法:export PATH=/usr/bin:/usr/sbin:/bin:/sbin长期方法:1.    vi /etc/profile2.    在最后插入并保存:    export PA ...

  9. C++判断月份天数(判断闰年)

    题目描述 输入年份和月份,输出这一年的这一月有多少天.需要考虑闰年. 输入格式 无 输出格式 无 输入输出样例 输入 #1 输出 #1 1926 8 31 输入 #2 输出 #2 2000 2 29 ...

  10. Second Order Optimization for Adversarial Robustness and Interpretability

    目录 概 主要内容 (4)式的求解 超参数 Tsiligkaridis T., Roberts J. Second Order Optimization for Adversarial Robustn ...