Filter Listener

news2025/2/24 10:06:28

文章目录

    • 一 过滤器(Filter)
      • 1 什么是过滤器
      • 2 为什么使用过滤器
      • 3 过滤器执行流程
      • 4 过滤器的生命周期
      • 5 过滤器的注册
        • 5.1 XML方式
        • 5.2 @WebFilter 注解方式
      • 6 FilterConfig
      • 7 过滤器链
      • 8 过滤器应用
    • 二 什么是监听器
      • 1 监听器分类
      • 2 监听器使用
        • 2.1 监听对象的创建
        • 2.2 注册监听器
        • 2.3 监听对象中属性的变化
      • 3 注册监听器
        • 3.1 XMl方式
        • 3.2 @WebListener注解方式
        • 3 应用

一 过滤器(Filter)

在这里插入图片描述

1 什么是过滤器

通过Filter可以对web服务器管理的所有web资源,如JSP, Servlet, 静态图片文件或静态html 文件等进行拦截,从而实现一些特殊的功能。

Filter不能通过url直接访问
过滤器本身并不产生请求和响应对象,它只能提供过滤作用。
过滤器能够在web资源被调用之前检查request对象,修改request Header和request内容;在Servlet被调用之后检查response对象,修改response Header和response内容。

2 为什么使用过滤器

访问资源时,针对不同的资源可能会执行很多相同的逻辑操作,如编码的设置,登录权限的判断等,借助Filter中的代码复用,可以提高开发效率

3 过滤器执行流程

在这里插入图片描述

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

4 过滤器的生命周期

1)创建和初始化阶段

​ Tomcat服务器启动时,如果应用中存在filter,会创建filter对象,并调用其初始化方法。filter对象只会创建一次,init方法也只会执行一次。通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象

2)拦截和过滤阶段

​ 通过chain.doFilter()进行实际的过滤操作,可以访问后续的资源,访问资源后,会回到doFilter方法中

3)销毁阶段

​ 当应用重新加载,或者关闭tomcat服务器时,会销毁filter对象

创建Filter对象

public class FirstFilter implements Filter {

    /**
     * Default constructor. 
     */
    public FirstFilter() {
        // TODO Auto-generated constructor stub
    	System.out.println("first filter constructor");
    }

	/**
	 * @see Filter#destroy()
	 */
	public void destroy() {
		// TODO Auto-generated method stub
		System.out.println("first filter destroy");
	}

	/**
	 * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
	 */
	// 核心方法,针对filter逻辑,写到该方法中
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		// TODO Auto-generated method stub
		// place your code here
		System.out.println("first filter before");
		// 放行请求,如果有其他的filter,继续访问filter,如果没有,访问目标资源
		// 多个filter的访问顺序,由filter在web.xml中的注册顺序决定
		chain.doFilter(request, response);
		System.out.println("first filter after");
	}

	/**
	 * @see Filter#init(FilterConfig)
	 */
	// 一个filter对应一个FilterConfig对象
	public void init(FilterConfig fConfig) throws ServletException {
		// TODO Auto-generated method stub
		System.out.println("first filter init");
		
		// 获取filter的初始化参数
		String value = fConfig.getInitParameter("aaa");
		System.out.println(value);
		
	}

}

注册Filter

<filter>
    <display-name>FirstFilter</display-name>
    <filter-name>FirstFilter</filter-name>
    <filter-class>com.qianfeng.filter.FirstFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>utf8</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>FirstFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

5 过滤器的注册

5.1 XML方式

在web.xml中对Filter进行注册,设置拦截的资源,一般设置为”/*”,对任意资源都进行过滤

<filter>
    <display-name>FirstFilter</display-name>
    <filter-name>FirstFilter</filter-name>
    <filter-class>com.qianfeng.filter.FirstFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>FirstFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

用于注册过滤器
用于指定过滤器的注册名,该元素的内容不能为空。
用于指定过滤器的完整限定名(包名+类名)。
元素用于设置 Filter 负责拦截的资源。
用于设置 Filter 的注册名,该值必须在 元素的子元素 中声明过。
用于设置 Filter 拦截的请求路径。

5.2 @WebFilter 注解方式
属性名描述
filterName指定过滤器的 name 属性,等价于 。
urlPatterns指定过滤器的 URL 匹配模式。等价于 标签。
value该属性等价于 urlPatterns 属性,但是两者不能同时使用。
servletNames指定过滤器将应用于哪些 Servlet。取值是 @WebServlet 中 filterName 属性的取值,或者 web.xml 中 的取值。
dispatcherTypes指定过滤器拦截的资源被 Servlet 容器调用的方式。具体取值包括: ASYNC、ERROR、FORWARD、INCLUDE、REQUEST。
initParams指定一组过滤器初始化参数,等价于 标签。
@WebFilter(filterName = "LoginFilter", value = "/*")
public class LoginFilter implements Filter {
}

6 FilterConfig

方法功能描述
String getInitParameter(String name)根据初始化参数名 name,返回对应的初始化参数值。
Enumeration getInitParameterNames()返回 Servlet 所有的初始化参数名的枚举集合,如果该 Servlet 没有初始化参数,则返回一个空的集合。
ServletContext getServletContext()返回一个代表当前 Web 应用的 ServletContext 对象。
String getFilterName()返回 Filter 的名字

7 过滤器链

在一个web应用中,可以开发编写多个Filter,这些Filter组合起来称之为一个Filter链

在doFilter方法中,开发人员如果调用了chain.doFilter方法,web服务器会检查FilterChain对象中是否还有其他的filter,如果有,则调用依次调用其余的filter,如果没有,则调用访问的目标资源。

在这里插入图片描述

注意:
访问filter的先后顺序,由filter在web.xml中的注册顺序决定
通过 @WebFilter 注解配置的 Filter 过滤器,没有提供排序的属性,但是,多个过滤器默认按照过滤器类名升序的顺序执行。若需要对 Filter 过滤器进行排序,建议使用 web.xml 进行配置

8 过滤器应用

1) 统一编码

public class EncodingFilter implements Filter {

    /**
     * Default constructor. 
     */
    public EncodingFilter() {
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see Filter#destroy()
	 */
	public void destroy() {
		// TODO Auto-generated method stub
	}

	/**
	 * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
	 */
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		// TODO Auto-generated method stub
		// place your code here
		// 针对post方式的中文乱码
		request.setCharacterEncoding("utf-8");
		// 响应
		response.setContentType("text/html;charset=utf-8");
		
		// pass the request along the filter chain
		chain.doFilter(request, response);
	}

	/**
	 * @see Filter#init(FilterConfig)
	 */
	public void init(FilterConfig fConfig) throws ServletException {
		// TODO Auto-generated method stub
	}

}

2) 访问权限控制

有些资源需要登录后访问

public class LoginFilter implements Filter {

	private String[] passArr = null;
    /**
     * Default constructor. 
     */
    public LoginFilter() {
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see Filter#destroy()
	 */
	public void destroy() {
		// TODO Auto-generated method stub
	}

	/**
	 * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
	 */
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		// TODO Auto-generated method stub
		// place your code here

		// 因为类型原因,某些方法不能正常调用,需要强制转换
		HttpServletRequest req = (HttpServletRequest)request;
		HttpServletResponse res = (HttpServletResponse)response;
		
		// 获取请求的资源的路径
		String uri = req.getRequestURI();
		// 如果是和登录相关的资源,直接放行
		
		// 是否放行的状态
		boolean flag = false;
		if(passArr != null){
			for(String info : passArr){
				if(uri.contains(info)){
					flag =  true;
					break;
				}
			}
		}
		
		if(flag){
			chain.doFilter(request, response);
		}else{
			HttpSession session = req.getSession();
			String name = (String)session.getAttribute("loginName");
			// 已经登陆过
			if(name != null){
				chain.doFilter(request, response);
			}else{
				// 跳转到登录页面
				res.sendRedirect(req.getContextPath() + "/login.jsp");
			}
			
		}
		
		// 获取session对象,判断是否有登录状态,如果有,继续访问,如果没有,跳转到登录页面
		
		
	}

	/**
	 * @see Filter#init(FilterConfig)
	 */
	public void init(FilterConfig fConfig) throws ServletException {
		// TODO Auto-generated method stub
		String initParameter = fConfig.getInitParameter("passInfo");
		if(initParameter != null){
			passArr = initParameter.split(",");
		}
		
	}

}

二 什么是监听器

在这里插入图片描述

监听器就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法将立即被执行。

在Servlet规范中定义了多种类型的监听器,它们用于监听的事件源分别为ServletContext, HttpSession 和ServletRequest 这三个域对象,主要用来监听对象的创建、销毁、属性的变化

监听器的相关概念:
事件:方法调用、属性改变、状态改变等。
事件源:被监听的对象( 例如:request、session、servletContext)。
监听器:用于监听事件源对象 ,事件源对象状态的变化都会触发监听器。
注册监听器:将监听器与事件源进行绑定。

1 监听器分类

Servlet 规范中定义了 8 个监听器接口,可以用于监听 ServletContext、HttpSession 和 ServletRequest 对象的生命周期和属性变化事件。开发 Servlet 监听器需要实现相应的监听器接口并重写接口中的方法。

(1)监听对象创建/销毁的监听器接口

ServlectContxtListener
ServletRequestListener
HttpSessionListener

(2)监听对象属性变化的接口

监听属性的增删改

ServletContextAttributeListener
ServletRequestAttributeListener
HttpSessionAttributeListener

(3)其他session相关监听器接口

HttpSessionBindingListener 监听对象绑定到session的事件

HttpSessionActivationListener 监听HttpSession中对象的活化和钝化过程

2 监听器使用

2.1 监听对象的创建
// 加载web应用时,创建对象
public class ContextListener implements ServletContextListener {

    /**
     * Default constructor. 
     */
    public ContextListener() {
        // TODO Auto-generated constructor stub
    	System.out.println("constructor");
    }

	/**
     * @see ServletContextListener#contextDestroyed(ServletContextEvent)
     */
    // 销毁ServletContext对象,调用该方法
    public void contextDestroyed(ServletContextEvent arg0)  { 
         // TODO Auto-generated method stub
    	System.out.println("servletcontext destroy");
    }

	/**
     * @see ServletContextListener#contextInitialized(ServletContextEvent)
     */
    // 创建ServletContext对象,调用该方法
    public void contextInitialized(ServletContextEvent arg0)  { 
         // TODO Auto-generated method stub
    	System.out.println("servletcontext init");
    }
	
}
2.2 注册监听器
<listener>
  <listener-class>com.qfedu.listener.ContextListener</listener-class>
</listener>
2.3 监听对象中属性的变化
public class SessionAttrListener implements HttpSessionAttributeListener {

    /**
     * Default constructor. 
     */
    public SessionAttrListener() {
        // TODO Auto-generated constructor stub
    }

	/**
     * @see HttpSessionAttributeListener#attributeAdded(HttpSessionBindingEvent)
     */
    public void attributeAdded(HttpSessionBindingEvent event)  { 
         // TODO Auto-generated method stub
    	
    	// 监测到添加的数据的信息
    	// 获取添加的属性的key值
    	System.out.println(event.getName());
    	// 获取添加的属性的value值
    	System.out.println(event.getValue());
    	
    }

	/**
     * @see HttpSessionAttributeListener#attributeRemoved(HttpSessionBindingEvent)
     */
    public void attributeRemoved(HttpSessionBindingEvent event)  { 
         // TODO Auto-generated method stub
    	
    	System.out.println("delete:" +event.getName());
    	System.out.println("delete:" +event.getValue());
    }

	/**
     * @see HttpSessionAttributeListener#attributeReplaced(HttpSessionBindingEvent)
     */
    // 修改数据时
    public void attributeReplaced(HttpSessionBindingEvent event)  { 
         // TODO Auto-generated method stub
    	// 修改前的数据
    	System.out.println("update:" + event.getName());
    	System.out.println("update:" + event.getValue());
    	
    	HttpSession session = event.getSession();
    	System.out.println("after update:" + session.getAttribute(event.getName()));
    	
    }
	
}

3 注册监听器

3.1 XMl方式
<listener>
  <listener-class>com.rr.listener.MyServletContextListener</listener-class>
</listener>
3.2 @WebListener注解方式
@WebListener
public class MyListener implements ServletContextListener {
}
3 应用

通过listener,实现获取所有登录用户信息的功能

package com.qfedu.listener;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import java.util.ArrayList;
import java.util.List;

@WebListener
public class MyListener implements ServletContextListener, HttpSessionAttributeListener {

    public MyListener() {
    }

    // 监听到ServletContext创建后,新建一个用户列表,将列表放入ServletContext对象
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        /* This method is called when the servlet context is initialized(when the Web application is deployed). */
        // 用来存储登录的用户名
        List<String> userList = new ArrayList<>();
        // 将列表存入ServletContext对象中
        sce.getServletContext().setAttribute("userList", userList);
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        /* This method is called when the servlet Context is undeployed or Application Server shuts down. */
    }

    // 当用户登录,将用户信息添加到用户列表中
    @Override
    public void attributeAdded(HttpSessionBindingEvent sbe) {
        /* This method is called when an attribute is added to a session. */
        String name = sbe.getName();
        // 说明是登录时添加的数据
        if (name.equals("loginInfo")) {
            ServletContext servletContext = sbe.getSession().getServletContext();
            List<String> userList = (List<String>) servletContext.getAttribute("userList");
            userList.add(sbe.getValue().toString());
        }
    }

    @Override
    public void attributeRemoved(HttpSessionBindingEvent sbe) {
        /* This method is called when an attribute is removed from a session. */
    }

    @Override
    public void attributeReplaced(HttpSessionBindingEvent sbe) {
        /* This method is called when an attribute is replaced in a session. */
    }
}

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

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

相关文章

Mac忘记本机MySql怎么办?

Mac忘记本机MySql怎么办&#xff1f; 1.打开系统偏好设置 2.打开Mysql 3.停止服务 4.直接初始化服务上图有一个初始化数据库 5.输入8位密码确认 6.重启服务

Blender教程(基础)-初始用户界面-01

开始第一天的Blender学习、也是业余学习。希望记录下这一份学习的过程、并且分享给大家。今天带大家认识Blender这一款软件&#xff0c;先说说我为什么选择了Blender&#xff0c;我在软件市场找了好久&#xff0c;市场上其他雷同软件都是要么收费要么不好用&#xff0c;最终决定…

【面试深度解析】滴滴后端二面:12306场景设计、Redis缓存设计、MyBatis两级缓存(下)

欢迎关注公众号&#xff08;通过文章导读关注&#xff1a;【11来了】&#xff09;&#xff0c;及时收到 AI 前沿项目工具及新技术的推送&#xff01; 在我后台回复 「资料」 可领取编程高频电子书&#xff01; 在我后台回复「面试」可领取硬核面试笔记&#xff01; 文章导读地址…

Mac安装nvm,安装多个不同版本node,指定node版本

一.安装nvm brew install nvm二。配置文件 touch ~/.zshrc echo export NVM_DIR~/.nvm >> ~/.zshrc echo source $(brew --prefix nvm)/nvm.sh >> ~/.zshrc三.查看安装版本 nvm -vnvm常用命令如下&#xff1a;nvm ls &#xff1a;列出所有已安装的 node 版本nvm…

一张图文深入了解信息量概念

通信原理第10页最后一段&#xff1a; 概率论告诉我们&#xff0c;事件的不确定程度可以用其出现的概率来描述。因此&#xff0c;消息中包含的信息量与消息发生的概率密切相关。消息出现的概率越小&#xff0c;则消息中包含的信息量就越大。 这句话怎么理解呢&#xff1f; 比如…

小红构造数组-牛客周赛 Round 29(DFS方法)

题目很直白&#xff0c;方法就是暴力即可。 虽然说数据范围显得很大&#xff0c;但是在长整型范围内&#xff0c;一个数字的素因子数量最多不超64&#xff0c;而如果是不相同的素因子&#xff0c;虽然没有计算过&#xff0c;但是如果是12个不同的素因子应该会超过数据范围了。…

消息中间件之八股面试回答篇:三、RabbitMQ如何解决消息堆积问题(100万条消息堆积)+RabbitMQ高可用性和强一致性机制+回答模板

RabbitMQ中的消息堆积问题 当生产者发送消息的速度超过了消费者处理消息的速度&#xff0c;就会导致队列中的消息堆积&#xff0c;直到队列存储消息达到上限。之后发送的消息就会成为死信&#xff0c;可能会被丢弃&#xff0c;这就是消息堆积问题。 解决消息堆积有三种种思路…

c++阶梯之引用与内联函数

1. 引用 1.1 引用概念 引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&#xff0c;编译器不会为引用变量开辟内存空间&#xff0c;它和它引用的变量共用同一块内存空间。 语法 类型& 引用变量名(对象名) 引用实体; 示例 很显然&#xff0c;在下面这…

21.Arrays类

Arrays类 1. 概述2. 常见方法3. sort 方法的自定义排序4. 代码示例5. 输出结果6. 注意事项 具体信息请查看 API 帮助文档 1. 概述 Arrays类是Java中的一个工具类&#xff0c;位于java.util包中。 它提供了一组静态方法&#xff0c;用于操作数组。通过Arrays类&#xff0c;我们…

springboot136人口老龄化社区服务与管理平台

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章 第四章 获取资料方式 **项…

web前端---------盒子模型2

一------内边距 padding 属性用来设置元素的内边距长度&#xff0c;元素在默认情况下没有内边距&#xff0c;其值为none。 &#xff08;1&#xff09;当 padding 属性中仅含一个值时&#xff0c;该长度应用在上、下、左、右四个区域。 &#xff08;2&#xff09;当 padding …

Java二分查找-图文

一、二分查找概念 二分查找也叫折半查找&#xff0c;是在一组有序(升序/降序)的数据中查找一个元素&#xff0c;它是一种效率较高的查找方。 二、二分查找原理 1.二分查找的数组必须是有序数值型数组。 2.将想要查找的目标元素与查找范围内的中间元素进行比较&#xff0c;如果…

文件包含漏洞长度截断

长度截断 文件漏洞的利用方式什么是长度截断通过实操理解00截断对版本要求更高一点&#xff0c;而长度截断则是利用了windows的系统漏洞&#xff0c;就是windows文件名&#xff08;就是文件名后缀之后&#xff09;之后如果有空格&#xff0c;或者是点都会被忽略掉&#xff0c;也…

研发日记,Matlab/Simulink避坑指南(八)——else if分支结构Bug

文章目录 前言 背景介绍 问题描述 分析排查 解决方案 总结归纳 前言 见《研发日记&#xff0c;Matlab/Simulink避坑指南(三)——向上取整Bug》 见《研发日记&#xff0c;Matlab/Simulink避坑指南(四)——transpose()转置函数Bug》 见《研发日记&#xff0c;Matlab/Simuli…

Spring Cloud + Vue前后端分离-第13章 网站开发

源代码在GitHub - 629y/course: Spring Cloud Vue前后端分离-在线课程 Spring Cloud Vue前后端分离-第13章 网站开发 13-1 网站模块的搭建 新建web模板 1.网站开发&#xff0c;增加web模块&#xff0c;使用命令&#xff1a;vue create web vue版本4.2.3 大家拿到一个v…

【Web】小白也能做的RWCTF体验赛baby题部分wp

遇到不会的题&#xff0c;怎么办&#xff01;有的师傅告诉你完了&#xff0c;废了&#xff0c;寄了&#xff01;只有Z3告诉你&#xff0c;稳辣&#xff01;稳辣&#xff01;都稳辣&#xff01; 这种CVE复现的题型&#xff0c;不可能要求选手从0到1进行0day挖掘&#xff0c;其实…

如何快速上手一个vue框架

安装nvm 下载nvm-setup.zip&#xff1a; https://github.com/coreybutler/nvm-windows/releases 解压安装nvm&#xff1a; 创建两个文件夹&#xff0c;一个是nvm的安装位置&#xff0c;另一个是node.js的下载位置。不需要配置环境变量和修改setting文件了 检查nvm是否安装成功…

Redis客户端之Redisson(三)Redisson分布式锁

一、背景&#xff1a; 高效的分布式锁设计应该包含以下几个要点&#xff1a; 1、互斥&#xff1a; 在分布式高并发的条件下&#xff0c;我们最需要保证&#xff0c;同一时刻只能有一个线程获得锁&#xff0c;这是最基本的一点 2、防止死锁&#xff1a; 在分布式高并发的条…

【vue3源码】vue源码探索之旅:项目介绍

简言 记录下我眼中的vue源码项目。 gitHubvue3项目仓库 项目要求: vue版本 3.4.15nodeV18.12.0以上使用pnpm包管理器vitest测试框架Vue3 vue3是渐进式JavaScript框架,易学易用,性能出色,适用场景丰富的 Web 前端框架。 Vue 是一个框架,也是一个生态。其功能覆盖了大部分…

VBA技术资料MF111:将表对象转换为正常范围

我给VBA的定义&#xff1a;VBA是个人小型自动化处理的有效工具。利用好了&#xff0c;可以大大提高自己的工作效率&#xff0c;而且可以提高数据的准确度。我的教程一共九套&#xff0c;分为初级、中级、高级三大部分。是对VBA的系统讲解&#xff0c;从简单的入门&#xff0c;到…