Tomcat 学习之 Filter 过滤器

目录

1 Filter 介绍

2 Filter 的生命周期

3 Filter 和 FilterChain

4 Filter 拦截过程

5 FilterConfig

6 Filter 使用


1 Filter 介绍

        在 Tomcat 中,Filter 是一种用于拦截请求过滤响应的组件,可以在请求到达 Servlet 之前或响应离开 Servlet 之后对其进行处理。

Filter 的主要应用场景包括:

  1. 权限控制:可以使用 Filter 来检查请求的用户是否具有访问特定资源的权限
  2. 日志记录:可以使用 Filter 来记录请求和响应的信息,以便进行监控和故障排除
  3. 性能监控:可以使用 Filter 来测量请求的处理时间和响应时间,以便进行性能优化
  4. 数据加密和解密:可以使用 Filter 来对请求和响应进行加密和解密,以保护敏感信息的安全

2 Filter 的生命周期

Filter 的生命周期由 Tomcat 容器管理,包含以下几个方法:

  1. 构造器方法,在 web 工程启动的时候执行
  2. init 初始化方法,在 web 工程启动的时候执行
  3. doFilter 过滤方法,每次拦截到请求,就会执行
  4. destroy 销毁,停止 web 工程的时候,就会销毁 Filter 过滤器

3 Filter 和 FilterChain

Filter 接口

public interface Filter {// 容器创建的时候调用, 即启动 Tomcat 的时候调用public void init(FilterConfig filterConfig) throws ServletException;// 由 FilterChain 调用, 并且传入 FilterChain 本身, 最后回调 FilterChain 的 doFilter() 方法public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException;// 容器销毁的时候调用, 即关闭 Tomcat 的时候调用public void destroy();}

FilterChain 接口

public interface FilterChain {// 由 Filter.doFilter() 中的 chain.doFilter 调用public void doFilter(ServletRequest request, ServletResponse response)throws IOException, ServletException;
}

        当 Tomcat 接收到 URL 请求时,它会根据在 web.xml 文件中配置的过滤器和映射路径来创建 FilterChain。如果某个请求匹配了一些过滤器的映射路径,那么这些过滤器将被添加到 FilterChain。创建了 FilterChain 之后,就开始执行 doFilter,进行请求的链式处理。

过滤器执行顺序:

  • 通过 web.xml 配置的 Filter 过滤器,执行顺序由 <filter-mapping> 标签的配置顺序决定。<filter-mapping> 靠前,则 Filter 先执行,靠后则后执行。通过修改 <filter-mapping> 的顺序便可以修改 Filter 的执行顺序
  • 通过 @WebFilter 注解配置的 Filter 过滤器,无法进行排序,若需要对 Filter 过滤器进行排序,建议使用 web.xml 进行配置

4 Filter 拦截过程

        如图是 Filter 拦截过程示意图。所有 Filter 和 Web 资源都默认执行在同一个线程中(因为Filter 和 Web 资源通常是在 HttpServlet 容器中运行的,而 HttpServlet 容器是基于单线程模型的)。对于 FilterChain 中的 Filter,它们都使用同一 Request 对象。

以下是 Filter 拦截过程的一般步骤:

  1. 客户端发送请求到给 Web 服务器
  2. Web 服务器接收到请求后,将请求传递给 HttpServlet 容器
  3. HttpServlet 容器根据请求的 URL 路径和配置的映射信息,确定应该调用哪些 Filter
  4. Filter 的 doFilter() 方法被调用,该方法将接收请求和响应对象作为参数
  5. 在 doFilter() 方法中,Filter 可以执行各种操作,例如检查请求头、修改请求参数、处理权限验证等
  6. 如果 Filter 决定继续处理请求,它可以通过调用 filterChain.doFilter() 方法将请求传递给下一个 Filter(如果有下一个 Filter)或 Web 资源(没有下一个 Filter)
  7. 下一个 Filter 的 doFilter() 方法被调用,直到请求到达最终的目标资源
  8. 目标资源处理请求并生成响应,响应通过 Filter 链反向传递,每个 Filter 都可以在响应离开之前对其进行修改或处理
  9. 最终,响应被发送回客户端,客户端接收到处理后的结果

FilterConfig

        FilterConfig 是 Filter 过滤器的配置文件类。Tomcat 每次创建 Filter 的时候,也会同时创建一个 FilterConfig 类,它包含了 Filter 配置文件的配置信息。
FilterConfig 类的作用是获取 filter 过滤器的配置内容
  • 获取 Filter 的名称 filter-name 的内容
  • 获取在 Filter 中配置的 init-param 初始化参数
  • 获取 ServletContext 对象
@Override
public void init(FilterConfig filterConfig) throws ServletException {// 1、获取 Filter 的名称 filter-name 的内容System.out.println("filter-name 的值是:" + filterConfig.getFilterName());// 2、获取在 web.xml 中配置的 init-param 初始化参数System.out.println("初始化参数 username 的值是:" + filterConfig.getInitParameter("username"));System.out.println("初始化参数 url 的值是:" + filterConfig.getInitParameter("url"));// 3、获取 ServletContext 对象System.out.println(filterConfig.getServletContext());
}

6 Filter 使用

工程目录

web.xml 配置

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"><!-- <display-name> 元素常用于配置 servlet、过滤器或其他 Web 组件的显示名称。这个显示名称主要用于在管理界面或日志中标识该组件,以方便识别和管理。 --><!-- 标识项目名 --><display-name>ServletTest</display-name><!-- 定义首页文件,也就是用户直接输入域名时跳转的页面(如http://localhost:8080/)--><welcome-file-list><welcome-file>login.jsp</welcome-file></welcome-file-list><!--filter 标签用于配置一个 Filter 过滤器--><filter><!--给 filter 起一个别名--><filter-name>AdminFilter1</filter-name><!--配置 filter 的全类名--><filter-class>com.test.AdminFilter1</filter-class><!-- 设置 Servlet 初始化参数可以通过 FilterConfig.getInitParamenter(String name) 方法访问初始化参数 --><init-param><param-name>username</param-name><param-value>root</param-value></init-param><init-param><param-name>url</param-name><param-value>jdbc:mysql://localhost3306/test</param-value></init-param></filter><!-- 设置 filter 映射 --><filter-mapping><!-- 和 filter 标签中的 filter-name 对应 --><filter-name>AdminFilter1</filter-name><!-- 设置匹配的路径,这里设置为 /img/* 表示访问 img 目录下的图片都会调用该 filter(AdminFilter) --><url-pattern>/img/*</url-pattern></filter-mapping><filter><filter-name>AdminFilter2</filter-name><filter-class>com.test.AdminFilter2</filter-class></filter><filter-mapping><filter-name>AdminFilter2</filter-name><url-pattern>/img/*</url-pattern></filter-mapping>
</web-app>

login.jsp 

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html><head><title>登录</title></head><body><form action="http://localhost:8080/servlettest/loginServlet" method="get">用户名: <input type="text" name="username"/> <br>密 码: <input type="password" name="password"/> <br><input type="submit" /></form></body>
</html>

LoginServlet 类

package com.test;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {resp.setContentType("text/html; charset=UTF-8");String username = req.getParameter("username");String password = req.getParameter("password");if ("root".equals(username) && "123456".equals(password)) {System.out.println("设置 Seesion: {user : " + username + " }");req.getSession().setAttribute("user",username);System.out.println("登录成功!");resp.getWriter().write("登录 成功!!!");} else {System.out.println("登录失败!");req.getRequestDispatcher("/login.jsp").forward(req,resp);}}
}

AdminFilter1 类

package com.test;import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;public class AdminFilter1 implements Filter {// doFilter 方法,专门用于拦截请求。可以做权限检查@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChainfilterChain) throws IOException, ServletException {System.out.println("过滤器 AdminFilter1");HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;HttpSession session = httpServletRequest.getSession();Object user = session.getAttribute("user");// System.out.println("登录用户: " + user);// 如果等于 null,说明还没有登录if (user == null) {System.out.println("未登录,跳转到登录页面");servletRequest.getRequestDispatcher("/login.jsp").forward(servletRequest,servletResponse);return;} else {// 让程序继续往下访问用户的目标资源System.out.println("AdminFilter1 调用 doFilter 方法");filterChain.doFilter(servletRequest,servletResponse);System.out.println("AdminFilter1 结束了 doFilter 方法的调用");}}@Overridepublic void init(FilterConfig filterConfig) throws ServletException {// 1、获取 Filter 的名称 filter-name 的内容System.out.println("filter-name 的值是:" + filterConfig.getFilterName());// 2、获取在 web.xml 中配置的 init-param 初始化参数System.out.println("初始化参数 username 的值是:" + filterConfig.getInitParameter("username"));System.out.println("初始化参数 url 的值是:" + filterConfig.getInitParameter("url"));// 3、获取 ServletContext 对象System.out.println(filterConfig.getServletContext());}
}

AdminFilter2 类

package com.test;import javax.servlet.*;
import java.io.IOException;public class AdminFilter2 implements Filter {// doFilter 方法,专门用于拦截请求。可以做权限检查@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChainfilterChain) throws IOException, ServletException {System.out.println("过滤器 AdminFilter2");System.out.println("AdminFilter2 调用 doFilter 方法");filterChain.doFilter(servletRequest,servletResponse);System.out.println("AdminFilter2 结束了 doFilter 方法的调用");}
}

运行演示图

运行流程:

  1. 启动服务器 Tomcat,创建 AdminFilter1 和 AdminFilter2 对象,获取 FilterConfig 配置并初始化,创建 LoginServlet 对象,获取 ServletConfig 配置并初始化,进入首页文件 login.jsp
  2. 客户端尝试请求访问 http://localhost:8080/servlettest/img/2.jpg,由过滤器 AdminFilter1 处理,输出“过滤器 AdminFilter1”和“未登录,跳转到登录页面”,之后跳转到 login.jsp 进行登录
  3. 输入账号:root,密码:123456,由 LoginServlet 的 doGet() 方法处理,设置 Seesion: {user : root },输出“登录成功!”
  4. 客户端再次请求访问 http://localhost:8080/servlettest/img/2.jpg,由过滤器 AdminFilter1 和 AdminFilter2 依次处理(调用 filterChain.doFilter 方法后可以对响应结果进行处理),之后返回响应结果给客户端
  5. 客户端得到响应结果,显示图片

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2803090.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

视频的语音转成文字字幕?这3个方法让你实现

随着网络的普及&#xff0c;越来越多的学生选择在网上观看辅导视频&#xff0c;以便随时随地学习。然而&#xff0c;整理这些视频中的教学笔记却成为了一个让人头疼的问题。传统的边看边记录的方式不仅费时费力&#xff0c;还容易遗漏重要信息。那么&#xff0c;有没有一种方法…

Spring Boot application.properties和application.yml文件的配置

在Spring Boot中&#xff0c;application.properties 和 application.yml 文件用于配置应用程序的各个方面&#xff0c;如服务器端口、数据库连接、日志级别等。这两个文件是Spring Boot的配置文件&#xff0c;位于 src/main/resources 目录下。 application.properties 示例 …

Jmeter基础(1) Mac下载安装启动

目录 Jmeter下载安装启动下载启动 Jmeter下载安装启动 注意⚠️&#xff1a;使用jmeter需要有java环境 下载 官网下载地址&#xff1a;https://jmeter.apache.org/ 会看到这里有两个版本&#xff0c;那么有什么区别么&#xff1f; Binaries是可执行版&#xff0c;直接下载解…

PostgreSQL 的实体化视图介绍

PostgreSQL 实体化视图提供一个强大的机制&#xff0c;通过预先计算并将查询结果集存储为物理表来提高查询性能。本教程将使用 DVD Rental Database 数据库作为演示例子&#xff0c;指导你在 PostgreSQL中创建实体化视图。 了解实体化视图 实体化视图是查询结果集的快照&…

网站访问免费升级成 HTTPS

步骤一&#xff1a;获取SSL证书 要将网站访问改为HTTPS&#xff0c;首先需要获取一个免费SSL证书。SSL证书是由受信任的证书颁发机构&#xff08;CA&#xff09;签发的数字证书&#xff0c;用于验证网站的身份并加密与用户的通信。可以通过购买或免费获取SSL证书。一些常见的免…

腾讯云宝塔Linux安装Mysql5.7

一、下载官方mysql包 wget http://dev.mysql.com/get/mysql-community-release-el7-5.noarch.rpm二、安装mysql包 rpm -ivh mysql-community-release-el7-5.noarch.rpm三、安装mysql yum install mysql-community-server -y四、启动数据库 systemctl start mysqld.service…

JNDI注入+RMI流程复现代码调试

前置知识 javax.naming&#xff1a;主要用于命名操作&#xff0c;它包含了命名服务的类和接口&#xff0c;该包定义了Context接口和InitialContext类&#xff1b;javax.naming.directory&#xff1a;主要用于目录操作&#xff0c;它定义了DirContext接口和InitialDir- Context…

使用jconsole监控SpringbootJVM(JDK11)

SpringBoot启动时增加参数&#xff1a; java -Djava.rmi.server.hostname服务器IP -Dcom.sun.management.jmxremotetrue \ -Dcom.sun.management.jmxremote.port1099 \ -Dcom.sun.management.jmxremote.rmi.port1099 \ -Dcom.sun.management.jmxremote.authenticatefalse \ -D…

C 嵌入式系统设计模式 10:中介者模式

本书的原著为&#xff1a;《Design Patterns for Embedded Systems in C ——An Embedded Software Engineering Toolkit 》&#xff0c;讲解的是嵌入式系统设计模式&#xff0c;是一本不可多得的好书。 本系列描述我对书中内容的理解。本文章描述访问硬件的设计模式之三&…

hash,以及数据结构——map容器

1.hash是什么&#xff1f; 定义&#xff1a;hash,一般翻译做散列、杂凑&#xff0c;或音译为哈希&#xff0c;是把任意长度的输入&#xff08;又叫做预映射pre-image&#xff09;通过散列算法变换成固定长度的输出&#xff0c; 该输出就是散列值。这种转换是一种压缩映射&…

谷歌浏览器文件下载不了的问题

问题: 谷歌浏览器测试环境a标签下载附件没问题,但是另一个环境下载闪了一下但是没有下载. 原因:测试环境http,附件下载链接是http,但是另一个环境网页地址是https,附件下载链接是http. Chrome将开始阻止“安全页面”&#xff08;HTTPS&#xff09;上所有“非安全子资源”&#…

BeikeShop跨境电商PHP商城源码

BeikeShop 一款开源好用的跨境电商系统&#xff0c;BeikeShop 是基于 Laravel 开发的一款开源商城系统主要面向外贸/跨境电商行业提供商品管理、订单管理、会员管理、支付、物流、系统管理等功能。 插件市场支持个人免签 BeikeShop系统亮点 1、系统代码100%开源 2、代码分层…

RabbitMQ开启MQTT协议支持

1&#xff09;RabbitMQ启用MQTT插件 rootmq:/# rabbitmq-plugins enable rabbitmq_mqtt Enabling plugins on node rabbitmq: rabbitmq_mqtt The following plugins have been configured:rabbitmq_managementrabbitmq_management_agentrabbitmq_mqttrabbitmq_web_dispatch Ap…

Linux理解

VMware安装Linux安装 目录 VMware安装Linux安装 1.1 什么是Linux 1.2 为什么要学Linux 1.3 学完Linux能干什么 2.1 主流操作系统 2.2 Linux系统版本 VMware安装Linux安装 1.1 什么是Linux Linux是一套免费使用和自由传播的操作系统。 1.2 为什么要学Linux 1). 企业用人…

unity Aaimation Rigging使用多个约束导致部分约束失去作用

在应用多个约束时&#xff0c;在Hierarchy的顺序可能会影响最终的效果。例如先应用了Aim Constraint&#xff0c;然后再应用Two Bone Constraint&#xff0c;可能会导致Two Bone Constraint受到Aim Constraint的影响而失效。因此&#xff0c;在使用多个约束时&#xff0c;应该仔…

【Java程序设计】【C00293】基于Springboot的藏区特产销售平台(有论文)

基于Springboot的藏区特产销售平台&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的藏区特产销售平台 本系统分为系统功能模块以及管理员功能模块。 系统功能模块&#xff1a;进入藏区特产销售平台页面中可以查看…

【Git】:远程仓库操作

远程仓库操作 一.理解版本控制系统二.远程仓库1.克隆2.Push操作3.fetch操作4. .gitnore文件 一.理解版本控制系统 我们⽬前所说的所有内容&#xff08;⼯作区&#xff0c;暂存区&#xff0c;版本库等等&#xff09;&#xff0c;都是在本地&#xff01;也就是在你的笔记本或者计…

前端输入框校验限制不能输入中文

一般我们在做表单的时候都会有表单校验,通常都是用element提供的表单验证的功能&#xff0c;只需要通过 rules 属性传入约定的验证规则&#xff0c;如下面这样 rules: {userName: [{validator: checkUsername,trigger: "blur",},{ validator: this.checkData, trigge…

navicat导出数据库表结构信息

需求阐述 要求导出某一数据库表中的所有表的结构&#xff0c;汇总成一个word 准备工作 拿到所有表名&#xff0c;在navicat中执行sql语句&#xff1a;show tables;然后点击导出结果&#xff0c;选择excel格式进行导出。 拿到该数据库所有表名后&#xff0c;在navicat中执行如…

动态SLAM:基于ORB-SLAM2与YOLOv8剔除动态特征点(三种方法)

基于ORB-SLAM2与YOLOv8剔除动态特征点(三种方法) 写上篇文章时测试过程比较乱&#xff0c;写的时候有些地方有点失误&#xff0c;所以重新写了这篇 本文内容均在RGB-D环境下进行程序测试 本文涉及到的动态特征点剔除速度均是以https://cvg.cit.tum.de/data/datasets/rgbd-dat…