拦截器和过滤器的区别是什么

news2024/9/25 21:27:05

过滤器

过滤器Filter是基于Servlet实现。Servlet的工作原理是拦截配置好的客户端请求,然后对RequestResponse进行处理。Filter过滤器随着web应用的启动而启动,只初始化一次。

过滤器的配置比较简单,直接实现Filter 接口就可以了,也可以通过@WebFilter注解实现对特定URL拦截,Filter 接口中定义了三个方法:init()、doFilter()以及destroy()。

  • init() :该方法在容器启动初始化过滤器时被调用,它在 Filter 的整个生命周期只会被调用一次。注意:这个方法必须执行成功,否则过滤器会不起作用。

  • doFilter() :容器中的每一次请求都会调用该方法, FilterChain 用来调用下一个过滤器 Filter。

  • destroy(): 当容器销毁 过滤器实例时调用该方法,一般在方法中销毁或关闭资源,在过滤器 Filter 的整个生命周期也只会被调用一次。

下面是的代码的实现方式:

package com.redis.test.filter;

import org.springframework.stereotype.Component;

import javax.servlet.*;
import java.io.IOException;

/**
 * @Author: laz
 * @CreateTime: 2023-03-01  17:21
 * @Version: 1.0
 */
@Component
public class TestFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
            System.err.println("过滤器前置");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.err.println("过滤器处理中");
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {
        System.err.println("过滤器销毁");
    }
}

写一个测试类:

package com.redis.test.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @Author: laz
 * @CreateTime: 2023-03-01  09:39
 * @Version: 1.0
 */
@RestController
@RequestMapping("test")
public class TestController {


    @RequestMapping("filter")
    public void test(){
        System.err.println("controller逻辑代码");
    }
}

启动项目,执行此接口,然后查看控制台:

在这里插入图片描述
通过控制台输出日志可以看到:init()方法在容器启动初始化过滤器时被调用,doFilter()方法在请求接口的时候被调用,destroy()方法在容器销毁的时候才会被调用,一般看不到。

拦截器

拦截器是SpringMVC中实现的一种基于Java反射(动态代理)机制的方法增强工具,拦截器的实现方式是是实现HandlerInterceptor 接口,HandlerInterceptor接口里面也有三个方法:preHandle()postHandle()afterCompletion()

  • preHandle() :这个方法将在请求处理之前进行调用。注意:如果该方法的返回值为false ,将视为当前请求结束,不仅自身的拦截器会失效,还会导致其他的拦截器也不再执行。

  • postHandle():只有在 preHandle() 方法返回值为true 时才会执行。会在Controller中的方法调用之后,DispatcherServlet 返回渲染视图之前被调用。 有意思的是:postHandle() 方法被调用的顺序跟 preHandle() 是相反的,先声明的拦截器 preHandle() 方法先执行,而postHandle()方法反而会后执行。

  • afterCompletion():只有在 preHandle() 方法返回值为true 时才会执行。在整个请求结束之后, DispatcherServlet 渲染了对应的视图之后执行。

下面是的代码的实现方式:
先实现HandlerInterceptor接口并重写里面的三个方法:

package com.redis.test.interceptor;

import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @Author: laz
 * @CreateTime: 2023-03-01  17:14
 * @Version: 1.0
 */
@Component
public class TestInterceptor implements HandlerInterceptor {


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        System.err.println("拦截器前置");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
        System.err.println("拦截器处理中");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        System.err.println("拦截器后置");
    }

}

然后写一个配置类,将我们定义好的拦截器进行注册:

package com.redis.test.config;

import com.redis.test.interceptor.TestInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @Author: laz
 * @CreateTime: 2023-03-01  17:17
 * @Version: 1.0
 */
@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private TestInterceptor testInterceptor;


    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        /**
         * addInterceptor(testInterceptor)将我们定义的拦截器进行注册
         * addPathPatterns("/**")表示对所有请求进行拦截
         * excludePathPatterns("/login")表示对某些请求放行,不需要拦截
         */
        registry.addInterceptor(testInterceptor).addPathPatterns("/**").excludePathPatterns("/login");
    }
}

启动项目,再次调用我们上面的接口:

在这里插入图片描述

通过日志可以看到:preHandle()方法在请求处理前被调用,postHandle()方法在controller请求结束后被调用,而afterCompletion()方法是在整个请求结束后才被调用。

过滤器和拦截器的区别

从上面输出日志可以看到,过滤器是在拦截器之前被调用,下面提供两张过滤器与拦截器执行顺序图:

在这里插入图片描述

由图可知:过滤器Filter是在请求进入容器后,但在进入servlet之前进行预处理,请求结束是在servlet处理完以后,过滤器属于Servlet级别。

拦截器Interceptor 是在请求进入servlet后,在进入Controller之前进行预处理的,Controller 中渲染了对应的视图之后请求结束,拦截器属于Spring级别。

在这里插入图片描述

拦截器与过滤器执行顺序即:

过滤器前置->过滤器处理中->拦截器前置->拦截器处理中->拦截器后置->过滤器后置

在日常实际开发中拦截器的应用场景会比过滤器要更多,一般情况下他们的使用场景如下:

  • 拦截器:权限控制,日志打印,参数校验

  • 过滤器:跨域问题解决,编码转换

总结

拦截器和过滤器的区别主要有一下几点:

  1. 实现原理不同:过滤器拦截器 底层实现方式大不相同,过滤器 是基于函数回调的,拦截器 则是基于Java的反射机制(动态代理)实现的。
  2. 使用范围不同: 过滤器 实现的是 javax.servlet.Filter 接口,而这个接口是在Servlet规范中定义的,也就是说过滤器Filter 的使用要依赖于Tomcat等容器,导致它只能在web程序中使用。而拦截器它是一个Spring组件,并由Spring容器管理,并不依赖Tomcat等容器,是可以单独使用的。不仅能应用在web程序中,也可以用于Application等程序中。
  3. 触发时机不同: 由上图可知,过滤器优先于拦截器执行。
  4. 拦截的请求范围不同: 过滤器几乎可以对所有进入容器的请求起作用,而拦截器只会对Controller中请求或访问static目录下的资源请求起作用。

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

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

相关文章

Python 虚拟环境的使用

PyCharm 创建的虚拟环境与使用 workon 命令创建的虚拟环境在本质上没有区别,它们都是 Python 的虚拟环境。 使用 PyCharm 创建工程时,使用可以使用曾经工程的虚拟环境,或者新建一个虚拟环境来安装 Python 的库,又或者使用 workon…

org.postgresql.util.PSQLException

1.使用springboot整合postgresql时报错&#xff1a;org.postgresql.util.PSQLException 1.1依赖 使用spring boot和postgresql搭建简单demo <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</arti…

Git概述

查看git版本&#xff1a; git --version1、Git概述 Git 是一个免费的、开源的分布式版本控制系统&#xff0c;可以快速高效地处理从小型到大型的各种项目。 Git 易于学习&#xff0c;占地面积小&#xff0c;性能极快。它具有廉价的本地库&#xff0c;方便的暂存区域和多个工作…

【C++基础入门】运算符、程序流程结构(if语句,for循环,switch语句等)

一&#xff1a;运算符 作用&#xff1a;用于执行代码的运算 运算符类型作用算术运算符用于处理四则运算赋值运算符用于将表达式的值赋给变量比较运算符用于表达式的比较&#xff0c;并返回一个真值或假值逻辑运算符用于根据表达式的值返回真值或假值 1.1 算术运算符 作用 &a…

PDF编辑/PDF浏览/PDF打印:PDFPrinting.NET Crack

PDFPrinting.NET高级 PDF 编辑库&#xff0c;可完全控制您的 PDF 创建工作流程 我们为 PDF 创建和编辑提供高级和低级 API。从简单的文档拆分到单个元素的精确删除。 从头开始创建 PDF 文档。 编辑现有文件。 支持创建、插入或删除 PDF 元素。 允许更改 PDF 的加密和压缩。 自…

计算机组成原理4小时速成7:存储器和cpu的连接,位扩展,字扩展,存储器的校验,汉明码编码纠错检错

计算机组成原理4小时速成7&#xff1a;存储器和cpu的连接&#xff0c;位扩展&#xff0c;字扩展&#xff0c;存储器的校验&#xff0c;汉明码编码纠错检错 2022找工作是学历、能力和运气的超强结合体&#xff0c;遇到寒冬&#xff0c;大厂不招人&#xff0c;可能很多算法学生都…

C/C++每日一练(20230302)

目录 1. 个位数是6&#xff0c;且能被3整除的五位数共有多少个&#xff1f; ☆ 2. 不同方式求n的阶乘 ★ 3. 报数游戏 ★☆ 1. 个位数是6&#xff0c;且能被3整除的五位数共有多少个&#xff1f; 答案&#xff1a; 3000 &#xff0c;代码略 2. 不同方式求n的阶乘 求n的…

sdwan方案有哪些 SD-WAN怎么搭建

随着sdwan网络架构的形成到目前的广泛应用到各行业之中&#xff0c;足见sdwan方案已经逐步的走向成熟。sdwan软件定义网络可在包括公共Internet&#xff0c;MPLS和宽带在内的标准网络传输服务上运行&#xff0c;解决了很多跨区域之间网络传输数据的难题。那么&#xff0c;sdwan…

软件测试4

一 form表单标签 1.form表单标签里面就是所有用户填写的表单数据&#xff1b; action“xxx.py”把表单数据提交给哪一个后台程序去处理 method“post” 传递数据时候的方式方法&#xff0c;post代表隐式提交数据、get明文传送数据 2.input标签的type类型 type“text” 普通的输…

优思学院|解密六西格玛:探索DMAIC和DMADV之间的区别

六西格玛方法中最为广泛使用的两种方法是DMAIC和DMADV。这两种方法都是为了让企业流程更加高效和有效而设计的。虽然这两种方法有一些重要的共同特点&#xff0c;但它们并不可以互相替代&#xff0c;并且被开发用于不同的企业流程。在更详细地比较这两种方法之前&#xff0c;我…

扬帆优配|突发利空,千亿巨头重挫!凭“一己之力”

马斯克效应持续凸显&#xff0c;稀土永磁板块早盘大跌&#xff0c;千亿市值的北方稀土跌超4%。 近来&#xff0c;马斯克凭“一己之力”带火A股卫星互联网、毫米波雷达两大概念板块&#xff0c;多只相关个股闻风大涨。 今日&#xff0c;马斯克效应在A股再度应验。在当地时间3月…

功能测试前还需要做哪些准备?

概述 在项目管理流程中&#xff0c;有几个关键阶段&#xff1a; 需求阶段 开发阶段 测试阶段 上线阶段 其中的需求阶段和开发阶段是最为重要的&#xff0c;一个是设计&#xff0c;定义这个功能如何运作&#xff0c;一个是执行与实现&#xff0c;这两个阶段把控好了&#…

从安卓系统USB升级包里提取system.img、boot.img和recovery.img在内的镜像文件

1.前言 如果你拿到一个USB升级包&#xff0c;你会发现升级包的结构基本相似。 但是里面并不是直接就有包括system.img、boot.img和recovery.img在内的镜像文件。 如果我们需要在Android手机上获取Magisk。提取内核&#xff08;boot.img&#xff09;就至关重要。当然其他镜像根…

不能去演唱会现场就多听听耳机里的他们,教你用python来实现一个音乐播放器

前言 最近可以说大麦网很知名了&#xff0c;哈哈还有好多想要用Python来搞抢票脚本的 怎么说呢也不是不行&#xff0c;但是咱今天可不是来搞这个的&#xff0c;我可不抢票&#xff0c;抢了都去不了&#xff0c;上班搞钱啊铁铁们 咱就是说去不了现场&#xff0c;就多听听手机…

实例分割 mask loss异常值,训练过程报错 debug记录

实例分割包含了目标检测,和检测框里的语义分割。 在搭建好一个模型后,训练过程中遇到了mask loss异常值,目标框消失不见,validation过程报错的情况,这里记录一下对这些问题的分析过程和debug记录。 首先分析一下mask loss异常值的问题。 mask loss用的是BCE loss。 mask…

dva( 轻量级的应用框架 )

dva核心知识与实战运用 dva 首先是一个基于 redux 和 redux-saga 的数据流方案&#xff0c;然后为了简化开发体验&#xff0c;dva 还额外内置了 react-router 和 fetch&#xff0c;所以也可以理解为一个轻量级的应用框架! 介绍 | DvaJS 易学易用&#xff0c;仅有 6 个 api&…

易基因-MeRIP-seq揭示衰老和神经变性过程中m6A RNA甲基化修饰的保守下调机制

大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。2023年02月22日&#xff0c;《美国国家科学院院刊》(Proc Natl Acad Sci USA)期刊发表了题为“Conserved reduction of m6A RNA modifications during aging and neurodegeneration is lin…

机器学习:学习KMeans算法,了解模型创建、使用模型及模型评价

机器学习&#xff1a;学习KMeans算法&#xff0c;了解模型创建、使用模型及模型评价 作者&#xff1a;AOAIYI 作者简介&#xff1a;Python领域新星作者、多项比赛获奖者&#xff1a;AOAIYI首页 &#x1f60a;&#x1f60a;&#x1f60a;如果觉得文章不错或能帮助到你学习&#…

android 动态加载jar包

什么时候需要用到动态加载jar包呢&#xff1f; 减少apk本身大小&#xff0c;某些界面才需要用jar里的功能jar中的功能可以独立开发&#xff0c;不要依赖其它的东西&#xff0c;能适用各个项目和第三方公司合作&#xff0c;人家不提供项目源码给你&#xff0c;但又要开发他们使…

MySQL workbench的基本操作

1. 创建新的连接 hostname主机名输入“local host”和“127.0.0.1”效果是一样的&#xff0c;指的是本地的服务器。 需要注意的是&#xff0c;此处的密码在安装软件的时候已经设定。 点击【Test Connection】&#xff0c;测试连接是否成功。 创建完的连接可以通过&#xff0c…