首页 > 其他分享 >拦截器和过滤器(原理&区别)

拦截器和过滤器(原理&区别)

时间:2024-03-14 23:59:12浏览次数:26  
标签:拦截器 请求 request 过滤器 原理 执行 public

目录

一、拦截器

拦截器是什么

拦截器的使用

拦截器的实现

导入依赖

实现HandlerInterceptor接口

注册拦截器

拦截器的生命周期

拦截器的执行顺序

拦截器的生命周期

多个拦截器的执行流程

拦截器的实际使用

拦截器实现日志记录

实现接口幂等性校验

拦截器的性能优化

二、过滤器

过滤器是什么

过滤器的使用

过滤器的实现

创建过滤器

开启URL过滤

过滤器的生命周期

多个Filter的执行顺序

三、过滤器和拦截器的区别

相同

底层原理

使用范围不同

触发时机不同

控制执行的顺序不同


一、拦截器

拦截器是什么

拦截器(Interceptor)是一种特殊的组件,它是基于反射进行实现。它可以在请求处理的过程中对请求和响应进行拦截和处理。拦截的是servlet 和 controller 之间的请求和响应。

拦截器的使用

  • 权限控制:拦截器可以在请求到达处理器之前进行权限验证,从而实现对不同用户的访问控制。

  • 日志记录:拦截器可以在请求处理过程中记录请求和响应的详细信息,便于后期分析和调试。

  • 接口幂等性校验:拦截器可以在请求到达处理器之前进行幂等性校验,防止重复提交。

  • 数据校验:拦截器可以在请求到达处理器之前对请求数据进行校验,确保数据的合法性。

  • 缓存处理:拦截器可以在请求处理之后对响应数据进行缓存,提高系统性能。

拦截器的实现

导入依赖

如果是使用的是springboot项目的话,直接导入这个依赖,spring项目需要导入 web 依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

实现HandlerInterceptor接口

要在SpringBoot中实现拦截器,首先需要创建一个类并实现HandlerInterceptor接口。HandlerInterceptor接口包含以下三个方法:

preHandle:在请求到达处理器之前执行,可以用于权限验证、数据校验等操作。如果返回true,则继续执行后续操作;如果返回false,则中断请求处理。

postHandle:在处理器处理请求之后执行,可以用于日志记录、缓存处理等操作。

afterCompletion:在视图渲染之后执行,可以用于资源清理等操作。

public class MainInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("我是处理之前!");
        return true;   //只有返回true才会继续,否则直接结束
    }
​
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("我是处理之后!");
    }
​
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("我是完成之后!");
    }
}

注册拦截器

要让拦截器生效,需要将其注册到InterceptorRegistry中。这可以通过实现WebMvcConfigurer接口并重写addInterceptors方法来实现。注册成功以后,我们还可以设置拦截的规则,拦截的路径,和不拦截的路径

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Autowired
    private MainInterceptor customInterceptor;
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 添加拦截器,并设置拦截路径
        registry.addInterceptor(customInterceptor)
                .addPathPatterns("/**").excludePathPatterns("/exclude/**");
    }
}

拦截器的生命周期

拦截器的执行顺序

当有多个拦截器时,它们的执行顺序取决于注册顺序。先注册的拦截器先执行,后注册的拦截器后执行。在请求处理过程中,拦截器的preHandle方法按注册顺序执行,而postHandle和afterCompletion方法按注册顺序的逆序执行。

拦截器的生命周期

拦截器的生命周期由Spring容器管理。当Spring容器启动时,拦截器会被实例化并初始化;当Spring容器关闭时,拦截器会被销毁。

多个拦截器的执行流程

当有多个拦截器时,它们的执行流程如下:

  1. 执行所有拦截器的preHandle方法,按注册顺序执行。如果某个拦截器的preHandle方法返回false,则中断请求处理,直接执行已执

  2. 拦截器的afterCompletion方法。

  3. 执行处理器的处理方法。

  4. 执行所有拦截器的postHandle方法,按注册顺序的逆序执行。

  5. 渲染视图。

  6. 执行所有拦截器的afterCompletion方法,按注册顺序的逆序执行。

拦截器的实际使用

拦截器实现日志记录

使用拦截器记录接口访问的记录,记录访问该接口的IP地址

@Component
public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("request.getRemoteHost() = " + request.getRemoteHost());
        System.out.println("request.getParameter(\"id\") = " + request.getParameter("id"));
        return true;   //只有返回true才会继续,否则直接结束
    }
​
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        request.getParameter("id");
        System.out.println("我是处理之后!");
    }
​
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("我是完成之后!");
    }
}
​

实现接口幂等性校验

拦截器可以在请求到达处理器之前进行幂等性校验,防止重复提交。以下是一个简单的幂等性校验示例:

public class IdempotentInterceptor implements HandlerInterceptor {
​
    private static final String IDEMPOTENT_TOKEN = "idempotentToken";
​
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        String token = request.getHeader(IDEMPOTENT_TOKEN);
        if (StringUtils.isEmpty(token)) {
            throw new RuntimeException("Idempotent token is missing");
        }
        if (!checkIdempotentToken(token)) {
            throw new RuntimeException("Duplicate request");
        }
        return true;
    }
​
    private boolean checkIdempotentToken(String token) {
        // Check the token in the cache or database
        // Return true if the token is valid, false otherwise
    }
}
​
//在上述示例中,我们在preHandle方法中检查请求头中的幂等性令牌,如果令牌无效,则抛出异常并中断请求处理。

拦截器的性能优化

拦截器在请求处理过程中可能会影响系统性能,以下是一些性能优化策略:

  • 减少拦截器数量:尽量将相关功能集中到一个拦截器中,避免创建过多的拦截器。

  • 精确配置拦截规则:通过addPathPatterns和excludePathPatterns方法精确配置拦截规则,避免不必要的拦截。

  • 使用异步处理:在拦截器中使用异步处理,避免阻塞请求处理过程。

  • 使用缓存:在拦截器中使用缓存,减少对数据库或其他资源的访问。

二、过滤器

过滤器是什么

过滤器顾名思义就是对事物进行过滤的,在Web中的过滤器,当然就是对请求进行过滤,我们使用过滤器,就可以对请求进行拦截,然后做相应的处理,实现许多特殊功能。过滤器的实现是通过函数回调进行实现。

函数回调:它指的是将一个函数作为参数传递给另一个函数,并在特定事件发生时被调用执行的函数。这种方式使得在异步编程中,当某个操作完成后,系统能够调用预先定义好的回调函数来处理结果,从而避免阻塞程序的执行,提高程序的效率和响应速度。

过滤器的使用

  • 如登录控制

  • 权限管理

  • 过滤敏感词汇等

过滤器的实现

过滤器的配置比较简单,直接实现Filter 接口即可,也可以通过@WebFilter注解实现对特定URL拦截,看到Filter 接口中定义了三个方法。

创建过滤器

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

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

默认就会传入Request和Response,这个参数封装了请求和响应,我们直接使用就行。ServletResquest和ServletResponse可以直接强转成HttpServletRequest和HttpServletResponse,然后使用相应的方法。

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

@Component
@WebFilter("/*") // 定义的过滤规则,只过滤对应的url请求
public class MyFilter implements Filter {
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
​
        System.out.println("Filter 前置");
    }
​
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
​
        System.out.println("Filter 处理中");
        filterChain.doFilter(servletRequest, servletResponse);
    }
​
    @Override
    public void destroy() {
​
        System.out.println("Filter 后置");
    }
}
开启URL过滤

开启专门的Url过滤需要在启动类添加一个注解 @ServletComponentScan

@SpringBootApplication
@ServletComponentScan
public class InterceptorApplication {
    public static void main(String[] args) {
        SpringApplication.run(InterceptorApplication.class, args);
    }
}

过滤器的生命周期

  1. 初始化阶段(Initialization): 在 Servlet 容器启动时,会实例化所有的过滤器并调用其 init 方法进行初始化。在 init 方法中,过滤器可以进行一些初始化操作,例如读取配置文件、建立数据库连接等。该方法只会在过滤器实例化时调用一次。

  2. 请求处理阶段(Request Processing): 在请求到达 Servlet 前,过滤器可以对请求进行预处理。当请求与过滤器匹配时,Servlet 容器会调用过滤器的 doFilter 方法来处理请求。在 doFilter 方法中,过滤器可以执行一些操作,例如修改请求或响应内容、记录日志、验证权限等。如果请求不符合过滤器的条件,过滤器可以选择放行请求,将请求传递给下一个过滤器或目标 Servlet。

  3. 销毁阶段(Destruction): 在 Servlet 容器关闭时,会销毁所有的过滤器并调用其 destroy 方法进行清理。在 destroy 方法中,过滤器可以进行一些清理操作,例如释放资源、关闭连接等。该方法只会在过滤器销毁时调用一次。

多个Filter的执行顺序
  • 如果我们是在web.xml中配置的过滤器,那么过滤器的执行顺序就是<filter-mapping>在web配置的顺序,配置在上面那么就会先执行。

  • 如果我们是使用@WebFilter进行配置的,那么执行顺序就是字符比较顺序来执行,例如有2个过滤器,一个是AFilter,一个是BFilter,那么AFilter就会先执行。

  • 如果注解和xml混用,那么在web.xml中配置的会先执行。

三、过滤器和拦截器的区别

相同

二者都是体现了AOP的思想,都可以实现诸如日志记录、登录鉴权等功能,但二者的不同点也是比较多的,接下来一一说明。

底层原理

拦截器是使用反射进行实现,过滤器是基于函数回调进行实现

使用范围不同

过滤器 实现的是 javax.servlet.Filter 接口,而这个接口是在Servlet规范中定义的,也就是说过滤器Filter 的使用要依赖于Tomcat等容器,导致它只能在web程序中使用。

拦截器(Interceptor) 它是一个Spring组件,并由Spring容器管理,并不依赖Tomcat等容器,是可以单独使用的。不仅能应用在web程序中,也可以用于ApplicationSwing等程序中。

触发时机不同

过滤器拦截器的触发时机也不同,我们看下边这张图

过滤器Filter是在请求进入容器后,但在进入servlet之前进行预处理,请求结束是在servlet处理完以后。

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

控制执行的顺序不同

拦截器:是先声明的拦截器 preHandle() 方法先执行,而postHandle()方法反而会后执行。

为什么?

两个方法中在调用拦截器数组 HandlerInterceptor[] 时,循环的顺序竟然是相反的。导致postHandle()preHandle() 方法执行的顺序相反。

标签:拦截器,请求,request,过滤器,原理,执行,public
From: https://blog.csdn.net/asdfasaa/article/details/136725319

相关文章

  • 【智能算法】白鲨算法(AVOA)原理及实现
    目录1.背景2.算法原理2.1算法思想2.2算法过程3.代码实现4.参考文献1.背景2022年,Braik等人受到白鲨捕食行为启发,提出了非洲秃鹫优化算法(WhiteSharkOptimizer,WSO)。2.算法原理2.1算法思想海洋中白鲨拥有敏锐的感知、听觉和嗅觉,WSO模拟了白鲨探索整个搜索......
  • Spring揭秘:Aware接口应用场景及实现原理!
    内容概要Aware接口赋予了Bean更多自感知的能力,通过实现不同的Aware接口,Bean可以轻松地获取到Spring容器中的其他资源引用,像ApplicationContext、BeanFactory等。这样不仅增强了Bean的功能,还提高了代码的可维护性和扩展性,从而让Spring的IoC容器变得更加强大和灵活。核心......
  • Spring揭秘:BeanDefinition接口应用场景及实现原理!
    BeanDefinition接口灵活性高,能够描述Bean的全方位信息,使得Spring容器可以智能地进行依赖注入和生命周期管理。同时,它支持多种配置方式,简化了Bean的声明和配置过程,提高了开发效率和可维护性。技术应用场景BeanDefinition接口定义了一个Bean的元数据,它包含了用于创建Bean对......
  • 苹果短信,imessage群发,苹果imessage,imessage推信,苹果系统imessage应用实现群发的原
    Apple公司全线在macos与ios两个操作系统上内置了FaceTime与iMessage两个应用。完美替代运营商的短信与电话。并且FaceTime与iMessage的帐号不仅仅与AppleID绑定,同时也与使用这AppleID的手机号码绑定,这样的漏洞自然给无孔不入的群发垃圾信息商们提供了后门。我们的iPhone用户......
  • 交叉编译工具链构建原理
    交叉编译工具链构建原理这是与弗朗西斯科·图尔科(FrancescoTurco)讨论的结果。弗朗西斯科为初学者提供了一个很好的教程(死链,Wayback机器没有存档版本),以及一个示例,从x86_64Debian主机为ARM目标构建工具链的分步过程。谢谢弗朗西斯科发起这个活动!我想要一个交叉编译器!你说的......
  • 面试官:说说反射的底层实现原理?
    反射是Java面试中必问的面试题,但只有很少人能真正的理解“反射”并讲明白反射,更别说能说清楚它的底层实现原理了。所以本文就通过大白话的方式来系统的讲解一下反射,希望大家看完之后能真正的理解并掌握“反射”这项技术。1.什么是反射?反射在程序运行期间动态获取类和操纵类的......
  • Spring Cloud原理详解:构建云原生应用的利器
    SpringCloud原理详解:构建云原生应用的利器引言在当今云原生应用的潮流中,微服务架构已经成为了构建可扩展、高可用性系统的首选范式之一。而SpringCloud作为构建微服务架构的利器,不仅提供了丰富的解决方案,还拥有强大的生态系统,为开发人员提供了便利与效率。本文将深入探......
  • FaceShift人脸表情识别原理分析
    之前负责了一个数字人应用平台的建设,其中一个核心功能是用摄像头实时捕捉用户的脸部图像,然后通过表情识别算法分析出用户的表情信息,驱动数字人做出同样的表情。这个功能已经在动画电影制作和游戏动画人物制作中频繁使用,目前更多的是穿戴专业的动捕服在专业的动捕篷中完成,制作成......
  • 单目测距的基本介绍和实现原理
    单目测距的基本介绍和实现原理单目测距是一种常用的测量技术,它通过单个摄像头来测量物体与摄像头的距离。在现代科技的推动下,单目测距术正在不断发展和应用于各个领域。本文将分点阐述关于单目测距的重要性、原理和方法、应用领域以及潜在的挑战和发展方向结尾附赠非常宝贵的自......
  • 在springboot中使用拦截器+JWT验证token的流程
    我的计算机设计大赛的项目需要用到JWT来进行用户身份验证,项目采用springboot技术,因为我没学过springSrcurity所以只能用原生的拦截器+JWT技术进行验证,我是跟着【SpringBoot整合JWT】这篇文章做的,老师讲的很详细跟着一步一步来也可以实现JWT身份验证,但是对于验证过程的整个流程......