学习Java第70天,过滤器Filter简介
过滤器概述
Filter,即过滤器,是JAVAEE技术规范之一,作用目标资源的请求进行过滤的一套技术规范,是Java Web项目中
最为实用的技术之一
-
Filter接口定义了过滤器的开发规范,所有的过滤器都要实现该接口
-
Filter的工作位置是项目中所有目标资源之前,容器在创建HttpServletRequest和HttpServletResponse对象后,会先调用Filter的doFilter方法
-
Filter的doFilter方法可以控制请求是否继续,如果放行,则请求继续,如果拒绝,则请求到此为止,由过滤器本身做出响应
-
Filter不仅可以对请求做出过滤,也可以在目标资源做出响应前,对响应再次进行处理
-
Filter是GOF中责任链模式的典型案例
-
Filter的常用应用包括但不限于: 登录权限检查,解决网站乱码,过滤敏感字符,日志记录,性能分析... ...
生活举例: 公司前台,停车场安保,地铁验票闸机
-
公司前台对来访人员进行审核,如果是游客则拒绝进入公司,如果是客户则放行 . 客户离开时提醒客户不要遗忘物品
-
停车场保安对来访车辆进行控制,如果没有车位拒绝进入,如果有车位,发放停车卡并放行,车辆离开时收取请车费
-
地铁验票闸机在人员进入之前检查票,没票拒绝进入,有票验票后放行,人员离开时同样验票
过滤器开发中应用的场景
-
日志的记录
-
性能的分析
-
乱码的处理
-
事务的控制
-
登录的控制
-
跨域的处理
-
... ...
过滤器工作位置图解

Filter接口API
import java.io.IOException;public interface Filter {default public void init(FilterConfig filterConfig) throws ServletException {}public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException;default public void destroy() {}
}
-
API目标
| API | 目标 |
|---|---|
| default public void init(FilterConfig filterConfig) | 初始化方法,由容器调用并传入初始配置信息filterConfig对象 |
| public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) | 过滤方法,核心方法,过滤请求,决定是否放行,响应之前的其他处理等都在该方法中 |
| default public void destroy() | 销毁方法,容器在回收过滤器对象之前调用的方法 |
过滤器使用
目标:开发一个日志记录过滤器
-
用户请求到达目标资源之前,记录用户的请求资源路径
-
响应之前记录本次请求目标资源运算的耗时
-
可以选择将日志记录进入文件,为了方便测试,这里将日志直接在控制台打印
定义一个过滤器类,编写功能代码
package com.atguigu.filters;import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class LoggingFilter implements Filter {private SimpleDateFormat dateFormat =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {// 参数父转子HttpServletRequest request =(HttpServletRequest) servletRequest;HttpServletResponse response =(HttpServletResponse) servletResponse;// 拼接日志文本String requestURI = request.getRequestURI();String time = dateFormat.format(new Date());String beforeLogging =requestURI+"在"+time+"被请求了";// 打印日志System.out.println(beforeLogging);// 获取系统时间long t1 = System.currentTimeMillis();// 放行请求filterChain.doFilter(request,response);// 获取系统时间long t2 = System.currentTimeMillis();// 拼接日志文本String afterLogging =requestURI+"在"+time+"的请求耗时:"+(t2-t1)+"毫秒";// 打印日志System.out.println(afterLogging);}
}
-
说明
-
doFilter方法中的请求和响应对象是以父接口的形式声明的,实际传入的实参就是HttpServletRequest和HttpServletResponse子接口级别的,可以安全强转
-
filterChain.doFilter(request,response); 这行代码的功能是放行请求,如果没有这一行代码,则请求到此为止
-
filterChain.doFilter(request,response);在放行时需要传入request和response,意味着请求和响应对象要继续传递给后续的资源,这里没有产生新的request和response对象
-
定义两个Servlet作为目标资源
@WebServlet(urlPatterns = "/servletA",name = "servletAName")
public class ServletA extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 处理器请求System.out.println("servletA处理请求的方法,耗时10毫秒");// 模拟处理请求耗时try {Thread.sleep(10);} catch (InterruptedException e) {throw new RuntimeException(e);}}
}
@WebServlet(urlPatterns = "/servletB", name = "servletBName")
public class ServletB extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 处理器请求System.out.println("servletB处理请求的方法,耗时15毫秒");// 模拟处理请求耗时try {Thread.sleep(15);} catch (InterruptedException e) {throw new RuntimeException(e);}}
}
配置过滤器以及过滤器的过滤范围
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"version="5.0"><!--配置filter,并为filter起别名--><filter><filter-name>loggingFilter</filter-name><filter-class>com.atguigu.filters.LoggingFilter</filter-class></filter><!--为别名对应的filter配置要过滤的目标资源--><filter-mapping><filter-name>loggingFilter</filter-name><!--通过映射路径确定过滤资源--><url-pattern>/servletA</url-pattern><!--通过后缀名确定过滤资源--><url-pattern>*.html</url-pattern><!--通过servlet别名确定过滤资源--><servlet-name>servletBName</servlet-name></filter-mapping>
</web-app>
说明
-
filter-mapping标签中定义了过滤器对那些资源进行过滤
-
子标签url-pattern通过映射路径确定过滤范围
-
/servletA 精确匹配,表示对servletA资源的请求进行过滤
-
*.html 表示对以.action结尾的路径进行过滤
-
/* 表示对所有资源进行过滤
-
一个filter-mapping下可以配置多个url-pattern
-
-
子标签servlet-name通过servlet别名确定对那些servlet进行过滤
-
使用该标签确定目标资源的前提是servlet已经起了别名
-
一个filter-mapping下可以定义多个servlet-name
-
一个filter-mapping下,servlet-name和url-pattern子标签可以同时存在
-

过滤器生命周期
过滤器作为web项目的组件之一,和Servlet的生命周期类似,略有不同,没有servlet的load-on-startup的配置,默认就是系统启动立刻构造
| 阶段 | 对应方法 | 执行时机 | 执行次数 |
|---|---|---|---|
| 创建对象 | 构造器 | web应用启动时 | 1 |
| 初始化方法 | void init(FilterConfig filterConfig) | 构造完毕 | 1 |
| 过滤请求 | void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) | 每次请求 | 多次 |
| 销毁 | default void destroy() | web应用关闭时 | 1次 |
过滤器链的使用
一个web项目中,可以同时定义多个过滤器,多个过滤器对同一个资源进行过滤时,工作位置有先后,整体形成一个工作链,称之为过滤器链
-
过滤器链中的过滤器的顺序由filter-mapping顺序决定
-
每个过滤器过滤的范围不同,针对同一个资源来说,过滤器链中的过滤器个数可能是不同的
-
如果某个Filter是使用ServletName进行匹配规则的配置,那么这个Filter执行的优先级要更低
图解过滤器链
注解方式配置过滤器
@WebFilter注解的使用
-
源码
package jakarta.servlet.annotation;import jakarta.servlet.DispatcherType;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@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;
}
一个比较完整的Filter的XML配置
<!--配置filter,并为filter起别名-->
<filter><filter-name>loggingFilter</filter-name><filter-class>com.atguigu.filters.LoggingFilter</filter-class><!--配置filter的初始参数--><init-param><param-name>dateTimePattern</param-name><param-value>yyyy-MM-dd HH:mm:ss</param-value></init-param>
</filter>
<!--为别名对应的filter配置要过滤的目标资源-->
<filter-mapping><filter-name>loggingFilter</filter-name><!--通过映射路径确定过滤资源--><url-pattern>/servletA</url-pattern><!--通过后缀名确定过滤资源--><url-pattern>*.html</url-pattern><!--通过servlet别名确定过滤资源--><servlet-name>servletBName</servlet-name>
</filter-mapping>
将xml配置转换成注解方式实现
package com.atguigu.filters;import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.annotation.WebInitParam;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;@WebFilter(filterName = "loggingFilter",initParams = {@WebInitParam(name="dateTimePattern",value="yyyy-MM-dd HH:mm:ss")},urlPatterns = {"/servletA","*.html"},servletNames = {"servletBName"}
)
public class LoggingFilter implements Filter {private SimpleDateFormat dateFormat ;/*init初始化方法,通过filterConfig获取初始化参数* init方法中,可以用于定义一些其他初始化功能代码* */@Overridepublic void init(FilterConfig filterConfig) throws ServletException {// 获取初始参数String dateTimePattern = filterConfig.getInitParameter("dateTimePattern");// 初始化成员变量dateFormat=new SimpleDateFormat(dateTimePattern);}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {// 参数父转子HttpServletRequest request =(HttpServletRequest) servletRequest;HttpServletResponse response =(HttpServletResponse) servletResponse;// 拼接日志文本String requestURI = request.getRequestURI();String time = dateFormat.format(new Date());String beforeLogging =requestURI+"在"+time+"被请求了";// 打印日志System.out.println(beforeLogging);// 获取系统时间long t1 = System.currentTimeMillis();// 放行请求filterChain.doFilter(request,response);// 获取系统时间long t2 = System.currentTimeMillis();String afterLogging =requestURI+"在"+time+"的请求耗时:"+(t2-t1)+"毫秒";// 打印日志System.out.println(afterLogging);}
}
ps:来源尚硅谷
相关文章:
学习Java第70天,过滤器Filter简介
过滤器概述 Filter,即过滤器,是JAVAEE技术规范之一,作用目标资源的请求进行过滤的一套技术规范,是Java Web项目中最为实用的技术之一 Filter接口定义了过滤器的开发规范,所有的过滤器都要实现该接口 Filter的工作位置是项目中所有目标资源之前,容器在创建HttpServletRequest和…...
Ubuntu Desktop 22.04 设置 ssh 超时时间
Ubuntu Desktop 22.04 使用 ssh 连接服务器时,发现一段时间不操作就会自动断开连接,解决方法如下: 打开 /etc/ssh/ssh_config 文件: sudo vim /etc/ssh/ssh_config在文件最后添加: # ssh 客户端会每隔 30 秒发送一个…...
【微服务】Spring Aop原理深入解析
目录 一、前言 二、aop概述 2.1 什么是AOP 2.2 AOP中的一些概念 2.2.1 aop通知类型 2.3 AOP实现原理 2.3.1 aop中的代理实现 2.4 静态代理与动态代理 2.4.1 静态代理实现 三、 jdk动态代理与cglib代理 3.1 jdk动态代理 3.1.1 jdk代理示例 3.1.2 jdk动态代理模拟实现…...
Spring Boot JSON中文文档
本文为官方文档直译版本。原文链接 Spring Boot JSON中文文档 引言Jackson自定义序列化器和反序列化器混入 GsonJSON-B 引言 Spring Boot 提供与三个 JSON 映射库的集成: GsonJacksonJSON-B Jackson 是首选的默认库。 Jackson Spring-boot-starter-json 提供了…...
Flink系列之:State Time-To-Live (TTL)
Flink系列之:State Time-To-Live TTL 一、TTL二、TTL实现代码三、过期状态的清理 一、TTL Flink的TTL(Time-To-Live)是一种数据过期策略,用于指定数据在流处理中的存活时间。TTL可以应用于Flink中的状态或事件时间窗口࿰…...
数据结构(Chapter Two -01)—线性表及顺序表
2.1 线性表 线性表是具有相同数据类型的n个数据元素的有限序列。第一个元素为表头元素,最后一个元素为表尾元素。除第一个元素,每个元素有且仅有一个直接前驱。除最后一个元素,每个元素都仅有一个直接后继。 其中线性表包括以下(…...
【刷题笔记1】
笔记1 string s;while(cin>>s);cout<<s.length()<<endl;输入为hello nowcoder时,输出为8 (nowcoder的长度) 2.字符串的输入(有空格) string a;getline(cin, a);cout<<a<<endl;输入为ABCabc a 输出为ABCabc a …...
视频数据卡设计方案:120-基于PCIe的视频数据卡
一、产品概述 基于PCIe的一款视频数据收发卡,并通过PCIe传输到存储计算服务器,实现信号的采集、分析、模拟输出,存储。 产品固化FPGA逻辑,实现PCIe的连续采集,单次采集容量2GB,开源的PCIe QT客…...
Windows使用VNC Viewer远程桌面Ubuntu【内网穿透】
文章目录 前言1. ubuntu安装VNC2. 设置vnc开机启动3. windows 安装VNC viewer连接工具4. 内网穿透4.1 安装cpolar【支持使用一键脚本命令安装】4.2 创建隧道映射4.3 测试公网远程访问 5. 配置固定TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址5.3 测试…...
javascript 数组处理的两个利器: `forEach` 和 `map`(上)
🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…...
【C语言】SCU安全项目1-FindKeys
目录 前言 命令行参数 16进制转字符串 extract_message1 process_keys12 extract_message2 main process_keys34 前言 因为这个学期基本都在搞CTF的web方向,C语言不免荒废。所幸还会一点指针相关的知识,故第一个安全项目做的挺顺利的,…...
IDA pro软件 如何修改.exe小程序打开对话框显示的文字?
环境: Win10 专业版 IDA pro Version 7.5.201028 .exe小程序 问题描述: IDA pro软件 如何修改.exe小程序打开对话框显示的文字? 解决方案: 一、在IDA Python脚本中编写代码来修改.rdata段中的静态字符串可以使用以下示例代码作为起点(未成功) import idc# 定义要修…...
Ubuntu22.04切换用户
一、只有一个用户时没有切换用户菜单项 1、用户信息 cat /etc/passwd 2、系统菜单 二、添加用户 添加新用户ym,全名yang mi 三、有两个及以上的用户时出现切换用户菜单项 1、用户信息 cat /etc/passwd 2、系统菜单 四、切换用户 1、点击上图中Switch User …...
torch.gather(...)
1. Abstract 对于 pytorch 中的函数 torch.gather(input, # (Tensor) the source tensordim, # (int) the axis along which to indexindex, # (LongTensor) the indices of elements to gather*,sparse_gradFalse,outNone ) → Tensor有点绕,很多博客画各…...
vscode如何开发微信小程序?JS与TS的主要区别?
要在 VS Code 中编写微信小程序代码并同步到 Git,需要安装以下插件: 1. 微信小程序插件(WeChat Mini Program):此插件提供了微信小程序的语法高亮、代码提示、调试、上传等功能。 2. Git 插件(GitLens、…...
产品入门第五讲:Axure交互和情境
目录 一.Axure交互和情境的介绍 1.交互介绍 概念 常见的Axure交互设计技巧 2.情境介绍 概念 常见的Axure情境设计技巧: 二.实例展示 1.ERP登录页到主页的跳转 2.ERP的菜单跳转到各个页面 📚📚 🏅我是默,一个…...
Python 自动化之收发邮件(一)
imapclient / smtplib 收发邮件 文章目录 imapclient / smtplib 收发邮件前言一、基本内容二、发送邮件1.整体代码 三、获取邮件1.整体代码 总结 前言 简单给大家写个如何用Python进行发邮件和查看邮件教程,希望对各位有所帮助。 一、基本内容 本文主要分为两部分…...
Flutter开发笔记 —— sqflite插件数据库应用
前言 今天在观阅掘金大佬文章的时候,了解到了该 sqflite 插件,结合官网教程和自己实践,由此总结出该文,希望对大家的学习有帮助! 插件详情 Flutter的 SQLite 插件。支持 iOS、Android 和 MacOS。 支持事务和batch模式…...
OxLint 发布了,Eslint 何去何从?
由于最近的rust在前端领域的崛起,基于rust的前端生态链遭到rust底层重构,最近又爆出OxLint,是一款基于Rust的linter工具Oxlint在国外前端圈引起热烈讨论,很多大佬给出了高度评价;你或许不知道OxLint,相比ES…...
第一次使用ThreadPoolExecutor处理业务
通过对业务逻辑的分析,进行编码,先把第一条sql查出来的数据进行分组,然后分别使用不同的线程去查询数据返回,并添加到原来的数据中。 总感觉哪里写的不对,但是同事们都没用过这个,请大家指教一下ÿ…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...
涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战
“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...
深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问(基础概念问题) 1. 请解释Spring框架的核心容器是什么?它在Spring中起到什么作用? Spring框架的核心容器是IoC容器&#…...
Kafka入门-生产者
生产者 生产者发送流程: 延迟时间为0ms时,也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于:异步发送不需要等待结果,同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...
