过滤器 与 拦截器

news2024/9/21 16:28:43

文章目录

  • 过滤器 与 拦截器
  • 一、过滤器(Filter)
    • 1、特点
    • 2、生命周期
    • 3、实现
    • 4、过滤器链
      • 1)配置 order
      • 2)执行顺序
  • 二、拦截器 Inteceptor
    • 1、特点
    • 2、生命周期
    • 3、实现
    • 4、拦截器链
      • 1)配置 order
      • 2)执行顺序(没有异常)
      • 3)某拦截器 preHandle 返回false
      • 4)执行顺序(有异常)
      • 5)小结
  • 三、执行顺序
    • 1、自定义 Servlet
    • 2、自定义 Filter
    • 3、自定义 Inteceptor
    • 4、对比:Servlet 与 Filter
    • 5、对比:Filter 与 Inteceptor
    • 6、小结

过滤器 与 拦截器

一、过滤器(Filter)

1、特点

过滤器是基于Java Servlet规范的一部分,用于在请求 到达Servlet之前 或 响应离开Servlet之后 对请求和响应进行处理。

  • 过滤器可以对所有请求进行处理,不仅限于特定的Servlet或Spring MVC控制器。
  • 过滤器在Servlet容器层面工作,而不是Spring层面。
  • 适合用于日志记录、身份验证、权限检查等通用功能。

2、生命周期

public interface Filter {
    // 初始化方法
    default void init(FilterConfig filterConfig) throws ServletException {
    }

    // 执行拦截方法
    void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;

    // 销毁方法
    default void destroy() {
    }
}
# 创建【init方法】
1. 特点:
		服务器启动,项目加载,创建filter对象,执行【init方法】(只执行一次)
2. 对比Servlet:
		先于Servlet的init方法执行

# 拦截【doFilter方法】
1. 特点:
		用户访问被拦截的目标资源时,执行【doFilter方法】(浏览器每访问一次,就会执行一次)
2. 对比Servlet:
		先于Servlet的service方法执行

# 销毁【destroy方法】
1. 特点:
		服务器关闭,项目关闭,销毁filter对象,执行【destroy方法】(只执行一次)
2. 对比Servlet:
		后于Servlet的destroy方法执行

3、实现

定义拦截器只要实现Filter接口,重写doFilter方法即可

public class MyFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // 前置处理...
        System.out.println("Filter doFilter before");

        // 处理请求
        chain.doFilter(request, response);

        // 后置处理...
        System.out.println("Filter doFilter after");
    }
}

注册拦截器(SpringBoot示例)

@Configuration
public class FilterConfig {
    @Bean
    public FilterRegistrationBean<MyFilter> myFilter() {
        FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new MyFilter());
        // 过滤路径(/*表示所有)
        registrationBean.addUrlPatterns("/*");
        // 过滤顺序(多个Filter按Order从小到大顺序执行)
        registrationBean.setOrder(1);
        return registrationBean;
    }
}

4、过滤器链

1)配置 order

多个 Filter 按 Order的大小 从小到大 执行(如果没有配置Order,按 Bean声明的顺序 从上到下 执行)

@Configuration
public class FilterConfig {
    @Bean
    public FilterRegistrationBean<MyFilter> myFilter1() {
        FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new MyFilter1());
        registrationBean.addUrlPatterns("/*");
        registrationBean.setOrder(1);
        return registrationBean;
    }

    @Bean
    public FilterRegistrationBean<MyFilter> myFilter2() {
        FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new MyFilter2());
        registrationBean.addUrlPatterns("/*");
        registrationBean.setOrder(2);
        return registrationBean;
    }

    @Bean
    public FilterRegistrationBean<MyFilter> myFilter3() {
        FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new MyFilter3());
        registrationBean.addUrlPatterns("/*");
        registrationBean.setOrder(3);
        return registrationBean;
    }
}

2)执行顺序

Filter1 doFilter before
Filter2 doFilter before
Filter3 doFilter before

Servlet service

// 如果发生异常,就不会执行 doFilter after 了
Filter3 doFilter after
Filter2 doFilter after
Filter1 doFilter after

二、拦截器 Inteceptor

1、特点

拦截器是Spring MVC提供的功能,用于在请求到达控制器之前和响应离开控制器之后进行处理。

  • 拦截器主要用于Spring MVC层面,处理的是控制器层的请求和响应。
  • 适合用于权限检查、日志记录、请求计时等与业务逻辑密切相关的操作。

2、生命周期

在这里插入图片描述

public interface HandlerInterceptor {
    // Controller执行之前调用
	default boolean preHandle(HttpServletRequest request,  HttpServletResponse response, Object handler) throws Exception {
		return true;
	}

    // Controller执行之后调用(发生异常 或 preHandle=false 不会调用)
	default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
	}

    // Controller执行之后调用(发生异常也会调用,preHandle=false不会调用)
	default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
	}
}

3、实现

自定义拦截器只要实现HandlerInterceptor接口,按需重写指定即可。

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("Pre Handle method is Called");
        return true; // 继续处理请求
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("Post Handle method is Called");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("Request and Response is completed");
    }
}

注册拦截器

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 添加自定义拦截器
        registry.addInterceptor(new MyInterceptor())
            	// 配置拦截路径
                .addPathPatterns("/**")
            	// 配置放过路径
                .excludePathPatterns();
    }
}

4、拦截器链

1)配置 order

多个 Interceptor 按 Order的大小 从小到大 执行(如果没有配置Order,按 添加的顺序 从上到下 执行)

@Configuration
public class MyAdapter implements WebMvcConfigurer {
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/**").order(1);
        registry.addInterceptor(new MyInterceptor2()).addPathPatterns("/**").order(2);
        registry.addInterceptor(new MyInterceptor3()).addPathPatterns("/**").order(3);
	}
}

2)执行顺序(没有异常)

Interceptor1 preHandle	// true
Interceptor2 preHandle	// true
Interceptor3 preHandle	// true
    
Servlet service

Interceptor3 postHandle
Interceptor2 postHandle
Interceptor1 postHandle  

Interceptor3 afterCompletion
Interceptor2 afterCompletion
Interceptor1 afterCompletion

3)某拦截器 preHandle 返回false

这里我们假设中间的 Interceptor2 的 preHandle 返回 false

Interceptor1 preHandle	// true
Interceptor2 preHandle	// false

Interceptor1 afterCompletion
之前的拦截器(即 Interceptor1): 执行了 preHandle 和 afterCompletion
阻隔的拦截器(即 Interceptor2): 执行了 preHandle
之后的拦截器(即 Interceptor3): 全部不执行

4)执行顺序(有异常)

Interceptor1 preHandle	// true
Interceptor2 preHandle	// true
Interceptor3 preHandle	// true

// 发生异常之前
Servlet service

// 这个竟然是在 异常的堆栈信息 之前执行的
Interceptor3 afterCompletion
Interceptor2 afterCompletion
Interceptor1 afterCompletion

异常的堆栈信息

// 发生异常之后,又整体执行了一遍....
Interceptor1 preHandle
Interceptor2 preHandle
Interceptor3 preHandle

Interceptor3 postHandle
Interceptor2 postHandle
Interceptor1 postHandle

Interceptor3 afterCompletion
Interceptor2 afterCompletion
Interceptor1 afterCompletion

5)小结

整体顺序:所有 preHandle -> Controller -> 所有 postHandle -> 所有 afterCompletion

# preHandle
1. 调用前提
		无
2. 调用时机
		Controller方法处理之前
3. 调用链顺序
		顺序执行:preHandle1 ==> preHandle2 ==> preHandle3

# postHandle
1. 调用前提
		preHandle返回true 且 Controller没有发生异常
2. 调用时机
		Controller方法处理完之后,afterCompletion调用之前
3. 调用链顺序
		倒序执行:postHandle3 ==> postHandle2 ==> postHandle1

# afterCompletion
1. 调用前提
		preHandle返回true(Controller发生异常也会调用)
2. 调用时机
		Controller方法处理完之后
3. 调用链顺序
		倒序执行:afterCompletion3 ==> afterCompletion2 ==> afterCompletion1

三、执行顺序

1、自定义 Servlet

public class MyServlet extends HttpServlet {
    @Override
    public void destroy() {
        System.out.println("Servlet destroy");
        super.destroy();
    }

    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("Servlet init");
        super.init(config);
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("Servlet service");
        resp.getWriter().write("Hello from MyServlet");
    }
}
@Configuration
public class ServletConfig {
    @Bean
    public ServletRegistrationBean<MyServlet> myServlet() {
        return new ServletRegistrationBean<>(new MyServlet(), "/myServlet");
    }
}

2、自定义 Filter

public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("Filter init");
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        // 前置处理...
        System.out.println("Filter doFilter before");

        // 处理请求
        chain.doFilter(request, response);

        // 后置处理...
        System.out.println("Filter doFilter after");
    }

    @Override
    public void destroy() {
        System.out.println("Filter destroy");
        Filter.super.destroy();
    }
}
@Configuration
public class FilterConfig {
    @Bean
    public FilterRegistrationBean<MyFilter> myFilter() {
        FilterRegistrationBean<MyFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new MyFilter());
        registrationBean.addUrlPatterns("/*");
        registrationBean.setOrder(1);
        return registrationBean;
    }
}

3、自定义 Inteceptor

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("Interceptor preHandle");
        return true; // 继续处理请求
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("Interceptor postHandle");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("Interceptor afterCompletion");
    }
}
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns();
    }
}

4、对比:Servlet 与 Filter

// 项目启动
Filter init
    
// 访问 http://localhost:8080/myServlet
Servlet init
Filter doFilter before
Servlet service
Filter doFilter after

// 项目关闭
Servlet destroy
Filter destroy

5、对比:Filter 与 Inteceptor

@RestController
public class TestController {
    @GetMapping("/interceptor")
    public ResponseEntity<String> interceptor() {
        System.out.println("Servlet service");
        return ResponseEntity.ok("SUCCESS");
    }
}
// 项目启动
Filter init

// 访问 http://localhost:8080/interceptor
Filter doFilter before
Interceptor preHandle
Servlet service
Interceptor postHandle
Interceptor afterCompletion
Filter doFilter after

// 项目关闭
Filter destroy

6、小结

在这里插入图片描述

// 项目启动
Filter init

// 访问接口
Servlet init
Filter doFilter before
Interceptor preHandle
Servlet service
Interceptor postHandle
Interceptor afterCompletion
Filter doFilter after

// 项目关闭
Servlet destroy
Filter destroy

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

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

相关文章

【Linux】保姆级 Linux 常见命令使用

&#x1f970;&#x1f970;&#x1f970;来都来了&#xff0c;不妨点个关注叭&#xff01; &#x1f449;博客主页&#xff1a;欢迎各位大佬!&#x1f448; 文章目录 1. Linux 是什么1.1 Linux 是什么1.2 关于 Linux 我们需要学什么 2. 需提前准备的东西2.1 环境 —— 如何获取…

关于PowerDesigner的使用

1.PowerDesigner概述&#xff1a; 1.PowerDesigner是一款开发人员常用的数据库建模工具&#xff0c;用户利用该软件可以方便地制作 数据流程图、概念数据模型 、 物理数据模型 &#xff0c;它几乎包括了数据库模型设计的全过程&#xff0c;是Sybase公司为企业建模和设计提供的…

蓝色炫酷碎粒子HTML5导航源码

源码介绍 蓝色炫酷碎粒子HTML5导航源码&#xff0c;源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面&#xff0c;重定向这个界面 效果预览 源码获取 蓝色炫酷碎粒…

火焰传感器详解(STM32)

目录 一、介绍 二、传感器原理 1.原理图 2.引脚描述 三、程序设计 main.c文件 IR.h文件 IR.c文件 四、实验效果 五、资料获取 项目分享 一、介绍 火焰传感器是一种常用于检测火焰或特定波长&#xff08;760nm-1100nm&#xff09;红外光的传感器。探测角度60左右&am…

MQTT学习:MQTT vs AMQP,mosquitto安装,调试工具mqttfx mqttx

前言 物联网vs互联网? 数据量/数据源:物联网的数据多是设备的自动采集,其数量远远超过互联网,互联网的数据更多是人工生成的 MQTT 协议(Message Queuing Telemetry Transport)vs AMQP 协议(Advanced Message Queuing Protocol)是两种在物联网中广泛使用的协议。 物联网…

推荐一款灵活,可靠和快速的开源分布式任务调度平台

今天给大家推荐一款灵活&#xff0c;可靠和快速的开源分布式任务调度平台——SnailJob。 前言 什么是任务调度&#xff1f; 任务调度&#xff0c;是指在多任务的环境下&#xff0c;合理地分配系统资源&#xff0c;调度各个任务在什么时候&#xff0c;由哪一个处理器处理&…

【简单】 猿人学web第一届 第15题 备周则意怠,常见则不疑

数据接口分析 数据接口 https://match.yuanrenxue.cn/api/match/15 请求时需要携带 page 页码&#xff0c;m为加密参数 cookie中没有加密信息&#xff0c;携带 SessionId请求即可 加密参数还原 查看数据接口对应的 requests 栈 m参数 是通过 window.m() 方法执行后得到的 打上…

分布式系统中的Dapper与Twitter Zipkin:链路追踪技术的实现与应用

目录 一、什么是链路追踪&#xff1f; 二、核心思想Dapper &#xff08;一&#xff09;Dapper链路追踪基本概念概要 &#xff08;二&#xff09;Trace、Span、Annotations Trace Span Annotation 案例说明 &#xff08;三&#xff09;带内数据与带外数据 带外数据 带…

『 C++ 』多线程相关

文章目录 极短临界区互斥锁的短板原子操作类 atomicatomic 原子操作原理 CASCAS 操作解决多线程创建链表的节点丢失问题多线程下的 shared_ptr 智能指针最简单的单例模式 极短临界区互斥锁的短板 如果两个线程同时对一个共享资源变量x进行自增操作将会出现线程安全问题,这个线程…

官方宣布Navicat免费使用!

官方宣布Navicat免费使用&#xff01; 对于开发者和数据库管理员来说&#xff0c;Navicat一直是不可或缺的工具之一。官方宣布Navicat可以免费使用&#xff0c;这无疑是个令人振奋的消息&#xff01;虽然是精简版&#xff0c;但足够日常使用。文末有下载链接。 无论你是管理M…

Linux 文件接口和文件管理

目录 一、回顾c语言文件操作 二、系统调用的文件操作 系统调用文件接口 open&#xff1a; close&#xff1a; write&#xff1a; 代码测试&#xff1a; ​编辑 ​编辑 read&#xff1a; 语言和系统函数间的关系&#xff1a; flags的实现思路 三、OS内文件的管理 语…

时序预测 | 基于MAMbaS+transformer时间序列预测模型(pytorch)

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 MAMBAS,transformer python代码&#xff0c;pytorch架构 可以发刊&#xff0c;先发先的&#xff0c;高精度代码。 需知&#xff1a;好的创新性模型可以事半功倍。。 适合功率预测&#xff0c;风电光伏预测&#xff0…

ubuntu通过smba访问华为设备

文章目录 ubuntu通过smba访问华为设备华为设备设置ubuntu设置访问测试 ubuntu通过smba访问华为设备 华为设备设置 华为设备在华为分享一栏下有共享至电脑的选项&#xff0c;打开即可&#xff0c;这里会创建用户名和密码进入设置 -> 关于手机/平板电脑 -> 状态信息&…

Android 10.0 mtk平板camera2横屏预览旋转90度功能实现

1.前言 在10.0的系统rom定制化开发中,在进行一些平板等默认横屏的设备开发的过程中,需要在进入camera2的 时候,默认预览图像也是需要横屏显示的,所以就需要看下mtk的camera2的相关预览功能,然后看下进入 launcher camera的时候看下如何实现预览横屏显示 如图所示: 2.mtk平…

【Linux】文件魔法师:时间与日历的解密(8/15完成)

欢迎来到 CILMY23 的博客 &#x1f3c6;本篇主题为&#xff1a;文件魔法师&#xff1a;时间与日历的解密 &#x1f3c6;个人主页&#xff1a;CILMY23-CSDN博客 &#x1f3c6;系列专栏&#xff1a;Python | C | C语言 | 数据结构与算法 | 贪心算法 | Linux | 算法专题 | 代码…

Golang | Leetcode Golang题解之第390题消除游戏

题目&#xff1a; 题解&#xff1a; func lastRemaining(n int) int {a1 : 1k, cnt, step : 0, n, 1for cnt > 1 {if k%2 0 { // 正向a1 step} else { // 反向if cnt%2 1 {a1 step}}kcnt >> 1step << 1}return a1 }

数学建模强化宝典(6)0-1规划

前言 0-1规划是决策变量仅取值0或1的一类特殊的整数规划。这种规划的决策变量称为0-1变量或二进制变量&#xff0c;因为一个非负整数都可以用二进制记数法用若干个0-1变量表示。在处理经济管理和运筹学中的某些规划问题时&#xff0c;若决策变量采用0-1变量&#xff0c;可把本来…

upload-labs-master靶场通关攻略

第一关 上传并进行抓包&#xff0c;修改后缀为php 第二关 抓包修改后缀 第三关 改后缀为php3 第4关 使用Apache的配置文件.htaccess来上传文件 然后再上传php文件 第5关 使用.user.ini来上传文件 然后再上传jpg文件 访问upload目录下的readme.php文件 第6关 大小写绕过 第…

公钥密码学

1. 非对称密码学 非对称密码学&#xff08;Asymmetric Cryptography) 中的 “非对称” 指的是用于加密数据的密钥和用于解密数据的密钥是不一样的&#xff08;如果一样&#xff0c;那就是对称密码学&#xff09;。对称密码学也称为共享密钥密码学。类似地&#xff0c;非对称密码…

大模型笔记01--基于ollama和open-webui快速部署chatgpt

大模型笔记01--基于ollama和open-webui快速部署chatgpt 介绍部署&测试安装ollama运行open-webui测试 注意事项说明 介绍 近年来AI大模型得到快速发展&#xff0c;各种大模型如雨后春笋一样涌出&#xff0c;逐步融入各行各业。与之相关的各类开源大模型系统工具也得到了快速…