从 01 开始 从 01 开始
首页
  • 📚 计算机基础

    • 计算机简史
    • 数字电路
    • 计算机组成原理
    • 操作系统
    • Linux
    • 计算机网络
    • 数据库
    • 编程工具
    • 装机
  • 🎨 前端

    • Node
  • JavaSE
  • Java 高级
  • JavaEE

    • 构建、依赖管理
    • Ant
    • Maven
    • 日志框架
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • 环境管理和配置管理-科普篇
    • Servlet
  • Spring

    • Spring基础
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC

    • SpringMVC 基础
  • SpringBoot

    • SpringBoot 基础
  • Windows 使用技巧
  • 手机相关技巧
  • 最全面的输入法教程
  • 最全面的浏览器教程
  • Office
  • 图片类工具
  • 效率类工具
  • 最全面的 RSS 教程
  • 码字工具
  • 各大平台
  • 校招
  • 五险一金
  • 职场规划
  • 关于离职
  • 杂谈
  • 自媒体
  • 📖 读书

    • 读书工具
    • 走进科学
  • 🌍 英语

    • 从零开始学英语
    • 英语兔的相关视频
    • Larry 想做技术大佬的相关视频
  • 🏛️ 政治

    • 反腐
    • GFW
    • 404 内容
    • 审查与自我审查
    • 互联网
    • 战争
    • 读书笔记
  • 💰 经济

    • 关于税
    • 理财
  • 💪 健身

    • 睡眠
    • 皮肤
    • 口腔健康
    • 学会呼吸
    • 健身日志
  • 🏠 其他

    • 驾驶技能
    • 租房与买房
    • 厨艺
  • 电影

    • 电影推荐
  • 电视剧
  • 漫画

    • 漫画软件
    • 漫画推荐
  • 游戏

    • Steam
    • 三国杀
    • 求生之路
  • 小说
  • 关于本站
  • 关于博主
  • 打赏
  • 网站动态
  • 友人帐
  • 从零开始搭建博客
  • 搭建邮件服务器
  • 本站分享
  • 🌈 生活

    • 2022
    • 2023
    • 2024
    • 2025
  • 📇 文章索引

    • 文章分类
    • 文章归档

晓林

程序猿,自由职业者,博主,英语爱好者,健身达人
首页
  • 📚 计算机基础

    • 计算机简史
    • 数字电路
    • 计算机组成原理
    • 操作系统
    • Linux
    • 计算机网络
    • 数据库
    • 编程工具
    • 装机
  • 🎨 前端

    • Node
  • JavaSE
  • Java 高级
  • JavaEE

    • 构建、依赖管理
    • Ant
    • Maven
    • 日志框架
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • 环境管理和配置管理-科普篇
    • Servlet
  • Spring

    • Spring基础
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC

    • SpringMVC 基础
  • SpringBoot

    • SpringBoot 基础
  • Windows 使用技巧
  • 手机相关技巧
  • 最全面的输入法教程
  • 最全面的浏览器教程
  • Office
  • 图片类工具
  • 效率类工具
  • 最全面的 RSS 教程
  • 码字工具
  • 各大平台
  • 校招
  • 五险一金
  • 职场规划
  • 关于离职
  • 杂谈
  • 自媒体
  • 📖 读书

    • 读书工具
    • 走进科学
  • 🌍 英语

    • 从零开始学英语
    • 英语兔的相关视频
    • Larry 想做技术大佬的相关视频
  • 🏛️ 政治

    • 反腐
    • GFW
    • 404 内容
    • 审查与自我审查
    • 互联网
    • 战争
    • 读书笔记
  • 💰 经济

    • 关于税
    • 理财
  • 💪 健身

    • 睡眠
    • 皮肤
    • 口腔健康
    • 学会呼吸
    • 健身日志
  • 🏠 其他

    • 驾驶技能
    • 租房与买房
    • 厨艺
  • 电影

    • 电影推荐
  • 电视剧
  • 漫画

    • 漫画软件
    • 漫画推荐
  • 游戏

    • Steam
    • 三国杀
    • 求生之路
  • 小说
  • 关于本站
  • 关于博主
  • 打赏
  • 网站动态
  • 友人帐
  • 从零开始搭建博客
  • 搭建邮件服务器
  • 本站分享
  • 🌈 生活

    • 2022
    • 2023
    • 2024
    • 2025
  • 📇 文章索引

    • 文章分类
    • 文章归档
  • JavaSE

  • JavaSenior

  • JavaEE

  • JavaWeb

    • 服务器软件

    • 环境管理和配置管理-科普篇
    • Servlet 入门

      • 什么是 Servlet
      • Servlet 入门案例
      • Servlet 生命周期
      • Servlet 中的注解
      • Tomcat 集成 IDEA
      • Servlet 体系结构
      • HTTP 协议基础
      • 深入 request 和 response 对象
      • request 对象基本使用
      • request 其他功能
      • Servlet 实现登录功能
      • HTTP 协议基础-响应
      • Response 对象基本使用
      • response 对象之重定向
      • response 输出字符到浏览器
      • response 输出字节数据
      • 验证码案例
      • ServletContext
      • 文件下载案例
      • Cookie 笔记
      • Cookie 的更多细节
      • Cookie 实践:记住上次访问时间
      • JSP 入门
      • JSP 的内置对象和案例
      • IDEA 与 JavaWeb 的小技巧
      • Session 笔记
      • 验证码案例
      • JSP 深入学习
      • MVC 开发模式
      • EL 表达式和 JSTL 标签
      • JSTL 标签库
      • 案例:列表的增删改查
      • Filter 学习
        • 什么是 Filter
        • 快速入门
        • WebFilter 源码
        • 过滤器执行流程
        • 过滤器生命周期方法
        • 通过路径和方式配置过滤器
        • 过滤器链(配置多个过滤器)
      • Filter 案例
      • Listener 学习
      • Java 中的 Ajax
      • Java 中的 JSON
  • Spring

  • 主流框架

  • SpringMVC

  • SpringBoot

  • Java
  • JavaWeb
  • Servlet 入门
2023-04-17
目录

Filter 学习

# 135.Filter 学习

Servlet,Filter 和 Listener 被称为 JavaWeb 的三大组件,今天我们就开始学习 Filter(重点掌握)和 Listener(了解)

# 什么是 Filter

Filter,就是过滤器的意思,例如:

  • 生活中的过滤器:净水器, 空气净化器

  • JavaWeb 中的过滤器:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能,例如有些功能是得登录后才能使用,如果我们在每个 Servlet 里都加上判断是否登录的代码,就非常难以维护。

    我们可以加个过滤器,有请求时先判断用户是否登录了,是则放行这个请求,这样就减少了重复代码

  • 过滤器的作用:一般用于完成通用的操作。如:登录验证、统一字符编码处理(比如我们之前的 doPost 方法里要设置编码为 UTF8)、敏感字符过滤(比如游戏中不能骂人)...

# 快速入门

编写过滤器的步骤:

  • 定义一个类,实现接口 Filter
  • 复写 Filter 的方法
  • 配置拦截路径: 例如注解 @WebFilter("/*"),或者通过 web.xml ‍ 我们写个 Servlet 演示下:
package com.peterjxl.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter("/*")  // 拦截路径,这样访问所有资源之前都会执行该过滤器
public class FilterDemo1 implements Filter {


    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("FilterDemo1被执行了。。。。");

        // 放行请求,如果不放行则相当于不返回数据给浏览器
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {

    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

‍ 注意:如果不放行,访问任何资源都是不会有数据返回给浏览器的 ‍ 也可以通过 web.xml 配置:

<filter>
     <filter-name>demo1</filter-name>
     <filter-class>com.peterjxl.filter.FilterDemo1</filter-class>
 </filter>
 <filter-mapping>
     <filter-name>demo1</filter-name>
	<!-- 配置拦截路径 -->
     <url-pattern>/*</url-pattern>
 </filter-mapping>
1
2
3
4
5
6
7
8
9

# WebFilter 源码

我们可以看看注解 WebFilter 的源码:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebFilter {
    String description() default "";

    String displayName() default "";

    WebInitParam[] initParams() default {};

    String filterName() default "";

    String smallIcon() default "";

    String largeIcon() default "";

    String[] servletNames() default {};

    String[] value() default {};

    String[] urlPatterns() default {};

    DispatcherType[] dispatcherTypes() default {DispatcherType.REQUEST};

    boolean asyncSupported() default false;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

‍ ElementType.TYPE 表明可以使用在类上,

RUNTIME 表明保留到运行阶段

Documented 表明生成文档

其他的属性我们可以忽略,主要是看 urlPatterns,和 WebServlet 的注解差不多 ‍

# 过滤器执行流程

  1. 执行过滤器
  2. 执行放行后的资源
  3. 回来执行过滤器放行代码下边的代码

举个生活的例子:你坐公交去会所,公交车是一个过滤器,交钱后给你放行;等你从会所回来,又坐公交车,那么还得交钱,然后放行。相当于原路返回。 ‍

package com.peterjxl.filter;

import javax.servlet.*;
import javax.servlet.annotation.*;
import java.io.IOException;

@WebFilter("/*")
public class FilterDemo2 implements Filter {
    public void init(FilterConfig config) throws ServletException {
    }

    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        //对request对象请求消息增强,例如判断是否登陆
        System.out.println("filterDemo2执行了....");

        //放行
        chain.doFilter(request, response);

        //对response对象的响应消息增强,例如判断登陆成功,在响应消息中设置登录信息
        System.out.println("filterDemo2回来了...");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

‍ 需要注意的是,过滤器中拿到的 request 对象和具体 Servlet 中拿到的 request 对象是同一个,因为我们 doFilter 里传的就是 request 和 response 对象 ‍ 重启 Tomcat,访问 index.jsp,可以看到输出了

filterDemo2执行了....
filterDemo2回来了...
1
2

# 过滤器生命周期方法

Filter 接口有 3 个方法,分别代表 3 个生命周期:

  1. init: 在服务器启动后,会创建 Filter 对象,然后调用 init 方法。该方法只执行一次,常用于加载资源
  2. doFilter: 每一次请求被拦截资源时,会执行。一般会执行多次
  3. destroy: 如果服务器是正常关闭,则会执行 destroy 方法, Filter 对象被销毁。只执行一次,常用于释放资源 ‍ 我们可以写个 Servlet,然后关闭和启动一次 Tomcat,观察方法是否被执行了
package com.peterjxl.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/**
 * 演示生命周期
 */
@WebFilter("/*")
public class FilterDemo3 implements Filter {
    public void init(FilterConfig config) throws ServletException {
        System.out.println("FilterDemo3 Init....");
    }

    public void destroy() {
        System.out.println("FilterDemo3 destroy....");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        chain.doFilter(request, response);
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 通过路径和方式配置过滤器

我们访问资源的时候,除了浏览器访问之外,还可以通过转发的方式访问;而过滤器可以根据请求的方式来配置是否执行过滤器,例如转发的时候就不执行过滤器。 ‍ 拦截路径配置方式:

  1. 具体资源路径: /index.jsp 只有访问 index.jsp 资源时,过滤器才会被执行
  2. 拦截目录: /user/* 访问/user 下的所有资源时,过滤器都会被执行
  3. 后缀名拦截: *.jsp 访问所有后缀名为 jsp 资源时,过滤器都会被执行
  4. 拦截所有资源:/* 访问所有资源时,过滤器都会被执行

拦截方式配置:资源被访问的方式。例如设置浏览器直接请求资源,才能被拦截器拦截,这样服务器内部转发的就不会被拦截,可以通过注解和 web.xml 配置。

通过注解配置拦截方式:设置 dispatcherTypes 属性, 可以设置多个,例如

@WebFilter(value="/index.jsp"  dispatcherTypes = DispatcherType.Request)
1

‍ 有如下访问方式:

  • REQUEST:默认值,也就是浏览器直接请求资源的方式
  • FORWARD:转发访问资源的方式,如果过滤器配置了这个属性,那么只有转发的资源才会被过滤器执行
  • INCLUDE:包含访问资源,了解即可
  • ERROR:错误跳转资源,了解即可
  • ASYNC:异步访问资源,SYNC 就是同步,加个 A 就是反义词,因此 ASYNC 就是异步,了解即可 ‍ 可以配置多个拦截方式:
//浏览器直接请求index.jsp或者转发访问index.jsp,该过滤器会被执行
@WebFilter(value="/index.jsp",dispatcherTypes ={ DispatcherType.FORWARD, DispatcherType.REQUEST})
1
2

web.xml 配置:在 filter-mapping 下 设置 <dispatcher></dispatcher> 标签即可 ‍

# 过滤器链(配置多个过滤器)

执行顺序:如果有两个过滤器,分别是过滤器 1 和过滤器 2,假设先执行了过滤器 1,则过滤器的执行流程为:

  • 过滤器 1
  • 过滤器 2
  • 资源执行
  • 过滤器 2 剩下的代码
  • 过滤器 1 剩下的代码

更多过滤器的情况同理,相当于原路返回

还是以坐公车去会所为例,相当于要转车,去到目的地获取想要的资源;然后回来的时候还是一样,原路返回,转车。 ‍ 那么怎么判断哪个过滤器先执行呢?有如下规则:

  1. 注解配置:按照类名的字符串比较规则比较,值小的先执行。如: AFilter 和 BFilter,AFilter 就先执行了。
  2. web.xml 配置: <filter-mapping> 谁定义在上边,谁先执行 ‍ 我们可以创建两个 Servlet 来演示下:
package com.peterjxl.filter;

import javax.servlet.*;
import javax.servlet.annotation.*;
import java.io.IOException;

@WebFilter("/*")
public class FilterDemo6 implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        System.out.println("filterDemo6执行了...");
        chain.doFilter(request, response);
        System.out.println("filterDemo6回来了...");
    }

    public void init(FilterConfig config) throws ServletException {
    }

    public void destroy() {
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.peterjxl.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter("/*")
public class FilterDemo7 implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        System.out.println("filterDemo7执行了...");
        chain.doFilter(request, response);
        System.out.println("filterDemo7回来了...");
    }

    public void init(FilterConfig config) throws ServletException {
    }

    public void destroy() {
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

‍ 重启 Tomcat,随便访问某个路径,控制台输出:

filterDemo6执行了...
filterDemo7执行了...
filterDemo7回来了...
filterDemo6回来了...
1
2
3
4

‍

上次更新: 2025/6/3 09:31:54
案例:列表的增删改查
Filter 案例

← 案例:列表的增删改查 Filter 案例→

最近更新
01
学点统计学:轻松识破一本正经的胡说八道
06-05
02
2025 年 5 月记
05-31
03
《贫穷的本质》很棒,但可能不适合你
05-27
更多文章>
Theme by Vdoing | Copyright © 2022-2025 | 粤 ICP 备 2022067627 号 -1 | 粤公网安备 44011302003646 号 | 点击查看十年之约
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式