Filter和Listener

1. Filter 过滤器

1 过滤器简介

  • Filter过滤器是JavaWeb的三大组件(Servlet程序、Listener监听器、Filter过滤器)之一

  • Filter作用:拦截请求、过滤响应

  • 是javaee的规范也是接口

  • 拦截请求常见的应用有

    • 权限检查
    • 日记操作
    • 事务管理

2 Filter 生命周期

Filter的生命周期包含几个方法

  1. 构造器方法
  2. init初始化方法
  3. doFilter过滤方法,每次拦截到请求,就会执行
  4. destory销毁

构造器方法和初始化方法都在web工程启动时执行,停止web工程的时候,只执行销毁方法,销毁Filter过滤器

从Java Servlet 3.0 规范开始,为了简化开发,Filter接口引入了默认方法(default methods),其中包括了默认的initdestroy方法的实现。这意味着,你可以只实现doFilter方法来编写自定义的过滤逻辑,而不需要显式地实现initdestroy方法。

3 拦截路径

在web.xml中配置

<filter>
	<filter-name>connectionFilter</filter-name>
    <filter-class>filter.ConnectionFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>connectionFilter</filter-name>
    <url-pattern>/user/*</url-pattern>
</filter-mapping>
  • 精确匹配
<url-pattern>/target.jsp</url-pattern>
以上配置的路径,表示请求地址必须为 http://ip:port/工程路径/target.jsp
  • 目录匹配
<url-pattern>/admin/*</url-pattern>
以上配置的路径, 表示请求地址必须为: http://ip:port/工程路径/admin/*
  • 后缀匹配
<url-pattern>*.html</url-pattern>
以上配置的路径, 表示请求地址必须以.html 结尾才会拦截到
<url-pattern>*.do</url-pattern>
以上配置的路径, 表示请求地址必须以.do 结尾才会拦截到
<url-pattern>*.action</url-pattern>
以上配置的路径, 表示请求地址必须以.action 结尾才会拦截到

Filter过滤器只会关心请求的地址是否匹配,不关心资源是否存在

4 FilterConfig类

是Filter的配置文件类

Tomcat 每次创建 Filter 的时候, 也会同时创建一个 FilterConfig 类, 这里包含了 Filter 配置文件的配置信息。FilterConfig 类的作用是获取 filter 过滤器的配置内容

  • 获取 Filter 的名称 filter-name 的内容

  • 获取在 Filter 中配置的 init-param 初始化参数

  • 获取 ServletContext 对象

web.xml

<!--filter 标签用于配置一个 Filter 过滤器-->
<filter>
	<!--给 filter 起一个别名-->
	<filter-name>AdminFilter</filter-name>
	<!--配置 filter 的全类名-->										<filterclass>com.lxs.filter.AdminFilter</filter-class>
	<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>

java

@Override
public void init(FilterConfig filterConfig) throws ServletException {
	System.out.println("2.Filter 的 init(FilterConfig filterConfig)初始化");
    // 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());
}

5 Filter Chain过滤器链

工作流程图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

过滤器链

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 多个过滤器执行的特点

    • 所有filter和目标资源默认都执行在同一个线程中
    • 多个filter共同执行时,都使用同一个request对象
  • FilterChain.doFilter()方法的作用:

    • 执行下一个Filter(有Filter)
    • 执行目标资源(没有Filter)

    在多个Filter过滤器执行的时候,执行的优先顺序是由在web.xml中从上到下的顺序决定的

Filter1

public class Filter1 implements Filter {
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
    	Filter.super.init(filterConfig);
		System.out.println("filter1 初始化方法");
	}
	@Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException,ServletException {
        System.out.println("filter1 前置 过滤方法 ");
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("filter1 后置 过滤方法 ");
	}
    @Override
    public void destroy() {
    	Filter.super.destroy();
    	System.out.println("销毁方法1");
	}
}

Filter2

public class Filter1 implements Filter {
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
    	Filter.super.init(filterConfig);
		System.out.println("filter2 初始化方法");
	}
	@Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException,ServletException {
        System.out.println("filter2 前置 过滤方法 ");
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("filter2 后置 过滤方法 ");
	}
    @Override
    public void destroy() {
    	Filter.super.destroy();
    	System.out.println("销毁方法2");
	}
}

web.xml

<filter>
    <filter-name>filter1</filter-name>
    <filter-class>com.lxs.demo.filter.Filter1</filter-class>
</filter>
<filter-mapping>
	<filter-name>filter1</filter-name>
	<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
    <filter-name>filter2</filter-name>
    <filter-class>com.lxs.demo.filter.Filter2</filter-class>
</filter>
<filter-mapping>
    <filter-name>filter2</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

6 Filter登录校验

要求:让在web工程下的所有资源在登录后才能被访问

注:WEB-INF目录下的文件不能被直接访问,只能通过转发访问

Filter过滤器使用步骤

  • 编写一个类去实现啊Filter接口
  • 实现过滤方法doFilter()
  • 到web.xml中去配置filter的拦截路径

Filter

public class AdminFilter implements Filter {
    /**
    * doFilter 方法, 专门用于拦截请求。 可以做权限检查
    */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest)servletRequest;
        HttpSession session = httpServletRequest.getSession();
        Object user = session.getAttribute("user");
        // 如果等于 null, 说明还没有登录
        if (user == null) {
            servletRequest.getRequestDispatcher("/login.jsp").forward(servletRequest,servletResponse);
            return;
        } else {
            // 让程序继续往下访问用户的目标资源
            filterChain.doFilter(servletRequest,servletResponse);
        }
    }
}

web.xml

<!--filter 标签用于配置一个 Filter 过滤器-->
<filter>
    <!--给 filter 起一个别名-->
    <filter-name>AdminFilter</filter-name>
    <!--配置 filter 的全类名-->
    <filter-class>com.lxs.filter.AdminFilter</filter-class>
</filter><!--filter-mapping 配置 Filter 过滤器的拦截路径-->
<filter-mapping>
    <!--filter-name 表示当前的拦截路径给哪个 filter 使用-->
    <filter-name>AdminFilter</filter-name>
    <!--url-pattern 配置拦截路径
    / 表示请求地址为: http://ip:port/工程路径/ 映射到 IDEA 的 web 目录
    /admin/* 表示请求地址为: http://ip:port/工程路径/admin/*
    -->
    <url-pattern>/admin/*</url-pattern>
</filter-mapping>

login.jsp 登录表单

这是登录页面。 login.jsp 页面 <br>
<form action="http://localhost:8080/15_filter/loginServlet" method="get">
    用户名: <input type="text" name="username"/> <br>
    密 码: <input type="password" name="password"/> <br>
    <input type="submit" />
</form>

LoginServlet

public class LoginServlet extends HttpServlet {
    @Override
    protected 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 ("wzg168".equals(username) && "123456".equals(password)) {
        	req.getSession().setAttribute("user", username);
            resp.getWriter().write("登录 成功! ! ! ");
        } else {
        	req.getRequestDispatcher("/login.jsp").forward(req, resp);
        }
    }
}

7 HttpServletRequestWrapper

HttpServletRequestWrapper是Servlet中的一个包装器类,用于对原始的HttpServletRequest对象进行包装和增强。它继承自ServletRequestWrapper类,并实现了HttpServletRequest接口。

通过使用HttpServletRequestWrapper,可以在HttpServletRequest对象的基础上添加自定义的功能或修改请求的参数、头部信息等内容,同时也能保持对原始HttpServletRequest方法的支持。

HttpServletRequestWrapper的使用通常包括以下几个步骤:

  1. 创建一个自定义的HttpServletRequestWrapper类,该类需要继承HttpServletRequestWrapper,并实现HttpServletRequest接口的所有抽象方法。

  2. 在自定义HttpServletRequestWrapper类中重写需要增强或修改的方法。例如,可以重写getParameter()方法来修改请求参数的值,或重写getHeader()方法来添加额外的头部信息。

  3. 在自定义HttpServletRequestWrapper类的构造函数中调用父类的构造函数,将原始的HttpServletRequest对象传递进去。

  4. 在Servlet中使用自定义的HttpServletRequestWrapper类来处理请求。可以通过在Servlet中获取到的HttpServletRequest对象创建自定义的HttpServletRequestWrapper对象,然后将其传递给其他的方法进行处理。

通过HttpServletRequestWrapper,我们可以在不修改原始ServletRequest对象的情况下,对请求进行定制化的处理,实现自定义需求。例如,可以用于实现请求参数的过滤、修改请求头、添加额外的请求验证等操作。

实现敏感词过滤

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

public class SensitiveWordFilterWrapper extends HttpServletRequestWrapper {

    public SensitiveWordFilterWrapper(HttpServletRequest request) {
        super(request);
    }

    @Override
    public String getParameter(String name) {
        String value = super.getParameter(name);
        if (value != null) {
            // 进行敏感词过滤处理
            value = sensitiveWordFilter(value);
        }
        return value;
    }

    private String sensitiveWordFilter(String value) {
        // 在这里编写敏感词过滤的逻辑,可以使用正则表达式或其他算法进行匹配和替换操作
        // 示例代码只是简单替换了一些敏感词为*
        value = value.replaceAll("敏感词1", "*");
        value = value.replaceAll("敏感词2", "*");
        /* // 对获取到的参数进行处理或修改
            if (name.equals("key")) {
                if ("敏感词".equals(value)) {
                    return "XXX(和谐)";
                }
            }*/
        // ...
        return value;
    }
}

在上面的示例中,我们创建了一个名为SensitiveWordFilterWrapper的类,继承自HttpServletRequestWrapper,并重写了其中的getParameter()方法。在重写的方法中,首先调用父类的getParameter()方法获取原始的请求参数值,然后对该值进行敏感词过滤处理,最后返回处理后的值。

敏感词过滤的具体实现逻辑可以根据需求来定制,可以使用正则表达式、Trie树等算法来匹配和替换敏感词。上述示例代码只是一个简单的示例,将敏感词替换为了*,实际情况中可能需要更复杂的处理逻辑。

在使用该包装器类时,需要在Servlet中将原始的HttpServletRequest对象替换为自定义的SensitiveWordFilterWrapper对象,示例如下:

public class MyServlet extends HttpServlet {

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpServletRequest wrappedRequest = new SensitiveWordFilterWrapper(req);
        // 使用包装后的请求对象进行处理
        // ...
    }
}

2. Listener 监听器

1 什么是监听器

监听器就是监听某个域对象的的状态变化的组件

监听器的相关概念:

  • 事件源:被监听的对象(三个域对象 request、session、servletContext)

  • 监听器:监听事件源对象事件源对象的状态的变化都会触发监听器

  • 注册监听器:将监听器与事件源进行绑定

  • 响应行为:监听器监听到事件源的状态变化时所涉及的功能代码(程序员编写代码)

2 监听器分类

第一维度是按被监听的对象划分:ServletRequest域,HttpSession域,ServletContext域

第二维度按照监听的内容分:监听域对象的创建与销毁的,监听域对象的属性变化的

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

public class MyListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent){
    	System.out.println("contextInitialized");
    }
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
    	System.out.println("contextDestroyed");
    }
}

web.xml

<listener>
	<listener-class>com.filter.MyListener</listener-class>
</listener>

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

刷题之多数元素(leetcode)

多数元素 哈希表解法&#xff1a; class Solution { public:/*int majorityElement(vector<int>& nums) {//map记录元素出现的次数&#xff0c;遍历map&#xff0c;求出出现次数最多的元素unordered_map<int,int>map;for(int i0;i<nums.size();i){map[nu…

详解Java垃圾回收(GC)机制

一、为什么需要垃圾回收 如果不进行垃圾回收&#xff0c;内存迟早都会被消耗空&#xff0c;因为我们在不断的分配内存空间而不进行回收。除非内存无限大&#xff0c;我们可以任性的分配而不回收&#xff0c;但是事实并非如此。所以&#xff0c;垃圾回收是必须的。 二、哪些内…

flutter环境安装(Mac+vscode)

以前据说flutter跨平台开发app很牛逼&#xff0c;最近突然想到这个东西&#xff0c;于是想体验一下flutter的开发流程&#xff0c;看看能否适合做独立开发。 我用的是mac&#xff0c;手机也是ios&#xff0c;就开始着手部署mac下的开发环境了。 开发后台的时候&#xff0c;一…

Vine: 一种全新定义 Vue 函数式组件的解决方案

7月6日的 vue confg 大会上 ShenQingchuan 大佬介绍了他的 Vue Vine 项目&#xff0c; 一种全新定义 Vue 函数式组件的解决方案。 和 React 的函数式组件有异曲同工之妙&#xff0c;写起来直接起飞了。 让我们来快速体验一下 vine&#xff0c; 看看到底给我们带来了哪些惊喜吧…

AI周报(6.30-7.6)

AI应用-AI控制F16战机与人类飞行员狗斗 2024年美国国防部领导下的国防部高级研究计划局&#xff08;DARPA&#xff09;宣布&#xff0c;世界上首次人工智能&#xff08;AI&#xff09;驾驶的战斗机与人类驾驶的战斗机之间的空战&#xff0c;于去年秋季在加利福尼亚州爱德华兹空…

基于CentOS Stream 9平台搭建RabbitMQ3.13.4以及开机自启

1. erlang与RabbitMQ对应版本参考&#xff1a;https://www.rabbitmq.com/which-erlang.html 2. 安装erlang 官网&#xff1a;https://www.erlang.org/downloads GitHub: https://github.com/rabbitmq/erlang-rpm/releases 2.1 安装依赖&#xff1a; yum -y install gcc glib…

【LeetCode】螺旋矩阵

目录 一、题目二、解法完整代码 一、题目 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[1,2,3,6,9,8,7,4,5] 示例 2&…

zdppy + vue3 + antd 实现一个表格编辑行,批量删除功能

编辑单元格和多选的功能 首先是编辑单元格的功能&#xff0c;点击编辑按钮&#xff0c;可以直接在表格中队内容进行编辑&#xff0c;点击保存以后能够同步到数据库。 其次是多选的功能&#xff0c;点击每行前面的多选框按钮&#xff0c;我们可以选中多行。 完整后端代码&am…

axios和Mybatis

除了get和post方法还有其他的方法&#xff1a; 发送 PUT 请求 发送 PUT 请求通常用于更新服务器上的资源。 const updateData {title: foo updated,body: bar updated,userId: 1 };axios.put(https://jsonplaceholder.typicode.com/posts/1, updateData).then(function (res…

Camera Raw:编辑 - 配置文件

Camera Raw “编辑”模块中的配置文件 Profile面板为照片编辑提供了一个坚实的基础&#xff0c;能够显著改善照片的初始外观&#xff0c;使编辑过程更加高效和灵活。 使用配置文件&#xff0c;可以控制如何呈现照片中的颜色和色调。配置文件旨在作为照片编辑的起点和基础。 ◆ …

数列结构(3.9)——队列应用

树的层次遍历 树的层次遍历&#xff0c;也称为树的广度优先遍历&#xff0c;是一种按照树的层次顺序&#xff0c;从上到下、从左到右遍历树中所有节点的算法。在二叉树中&#xff0c;这种遍历方式通常使用队列来实现。下面是层次遍历的基本步骤&#xff1a; 创建一个空队列&a…

qemu模拟orangepi

前言 由于qemu目前只支持orange pipc单板&#xff0c;也就是H3型号&#xff0c;故我们就拿这个型号做测试 环境搭建 linux主机环境 我这里采用win10 WSL&#xff0c;且环境用的是openeuler的&#xff0c;在选择服务器类型可以按照自己喜好选择&#xff0c;也就是包安装方式…

【ARMv8/v9 GIC 系列 1.7 -- GIC PPI | SPI | SGI | LPI 中断使能配置介绍】

请阅读【ARM GICv3/v4 实战学习 】 文章目录 GIC 各种中断使能配置PPIs(每个处理器私有中断)SPIs(共享外设中断)SGIs(软件生成的中断)LPIs(局部中断)GIC 各种中断使能配置 在ARM GICv3和GICv4架构中,不同类型的中断(如PPIs、SPIs、SGIs和LPIs)可以通过不同的方式进…

SUSAN

1995年英国牛津大学的S.M.Smith提出了一种新的图像边缘检测算法SUSAN算法,不同于以前经典边缘检测算法,SUSAN算法基于灰度相似性比较,采用圆形模板,对图像进行灰度差统计,无需计算方向导数,而且具备积分特性,它简单而且有效,适用于图像中边缘和角点的检测,可以去除图像…

【Unity】简单举例UI合批,优化draw call

1. UGUI-Editor 首先引入UGUI-Editor插件 链接: https://pan.baidu.com/s/1PpxStvgRCDi9xjUr6j6nCQ?pwdm5ju 提取码: m5ju 或者直接去Github搜索UGUI-Editor 2. 没有UI时 3. 放几个UI看看效果 4. 选中Canvas&#xff0c;右键优化Batch 发现减少了3个&#xff0c;这是因为&…

玉石风能否接棒黏土风?一探AI绘画新风尚

在数字艺术的浪潮中,AI绘画平台以其独特的创造力和便捷性,正在逐步改变我们对艺术的传统认知。从黏土风的温暖质感到琉璃玉石的细腻光泽,每一次风格的转变都引领着新的潮流。今天,我们将聚焦玉石风,探讨它是否能成为下一个流行的艺术滤镜,并提供一种在线体验的方式,让你…

昇思25天学习打卡营第13天 | ShuffleNet图像分类

ShuffleNet网络介绍 ShuffleNetV1是旷视科技提出的一种计算高效的CNN模型&#xff0c;和MobileNet, SqueezeNet等一样主要应用在移动端&#xff0c;所以模型的设计目标就是利用有限的计算资源来达到最好的模型精度。ShuffleNetV1的设计核心是引入了两种操作&#xff1a;Pointw…

Spring AOP实现操作日志记录示例

1. 准备工作 项目环境&#xff1a;jdk8springboot2.6.13mysql8 1.1 MySQL表 /*Navicat Premium Data TransferSource Server : localhostSource Server Type : MySQLSource Server Version : 50730Source Host : 127.0.0.1:3306Source Schema …

通过IDEA生成webapp及web.xml配置文件

1、选择File->Project Structure 2、选择Modules-> + -> Web 有的springboot工程选择是war工程,这个web可能已经存在了。 如果不存在,就手动创建,创建后,需要修改pom.xml中的配置 <packaging>war</packaging> 3、创建webapp根目录 这步重点就是创建…

ARM架构以及程序运行解析

文章目录 1. ARM架构 2. ARM处理器程序运行的过程 3. 示例 3. 基于ARM架构的STM32单片机 1. 运行模式 2. 寄存器组 3. STM32的基本结构 4. STM32的运行模式 4. 寄存器组详解 1. 未备份寄存器 2. 备份寄存器 3. 程序计数器 4. 程序状态寄存器 5. CPSR和SPSR寄存器…