首页 > 其他分享 >SpringBoot系列---【过滤器Filter和拦截器HandlerInterceptor的区别和用法】

SpringBoot系列---【过滤器Filter和拦截器HandlerInterceptor的区别和用法】

时间:2023-12-22 15:13:07浏览次数:33  
标签:拦截器 SpringBoot Filter 过滤器 import servlet public 请求

1.作用时机

1.1 过滤器

过滤器(Filter)主要作用在请求到达Servlet或JSP之前,对请求进行预处理,可以对HTTP请求进行过滤、修改。过滤器是基于回调函数实现的,开发人员通过重写doFilter()方法实现过滤逻辑,其主要功能有:

  • 权限验证:检查用户是否已经登录或者是否具有相应的权限。
  • 数据压缩:从web服务器向客户端传送数据前,把数据压缩成gzip格式,减少网络传输量。
  • 字符编码转换:将输入输出流的字符集统一。
  • 日志记录:记录客户端访问时间、IP地址等信息,方便后期统计分析。
    过滤器来自Servlet。

1.2 拦截器

拦截器(Interceptor)主要作用在请求到达Controller之前或之后,对请求进行拦截,防止非法请求到达Controller,或者在请求到达Controller之后,对返回结果进行加工处理。
在Java Web应用中,可以通过定义拦截器(Interceptor)来实现对请求和响应的拦截和处理。拦截器可以在请求被处理前、后或异常时执行相应的操作。
拦截器来自Spring框架。

  • 登录认证:在一些简单应用中,可能会通过拦截器来验证用户的登录状态,如果没有登录或者登录失效,就会给用户一个友好的提示或者返回登录页面。
  • 记录系统日志:在Web应用中,通常需要记录用户的请求信息,比如请求的IP、方法执行时 常等,通过这些记录可以监控系统的状况,以便于对系统进行信息监控、信息统计、计算PV (PageView)和性能调优等。
  • 通用处理:在应用程序中可能存在所有方法都要返回的信息,这时可以使用拦截器来实现 省去每个方法冗余重复的代码实现。
  • 日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算 PV(Page View)等;
  • 权限检查:如登录检测,进入处理器检测是否登录;
  • 性能监控:通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间。(反向代理,如 Apache也可以自动记录)
  • 通用行为:读取 Cookie 得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取 Locale、Theme 信息等,只要是多个处理器都需要的即可使用拦截器实现。

1.3 二者区别

1、拦截器是基于java的反射机制的,而过滤器是基于函数回调(职责链)。
2、过滤器依赖与servlet容器,而拦截器不依赖与servlet容器。
3、拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
4、拦截器可以访问action上下文、值栈里的对象,而过滤器不能。
5、在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
6、拦截器可以获取IOC容器中的各个bean,而过滤器不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。

简单理解:
(1)过滤器(Filter):当你有一堆东西的时候,你只希望选择符合你要求的某一些东西。定义这些要求的工具,就是过滤器。(理解:就是一堆字母中取一个B)
(2)拦截器(Interceptor):在一个流程正在进行的时候,你希望干预它的进展,甚至终止它进行,这是拦截器做的事情。(理解:就是一堆字母中,干预它,通过验证的少点,顺便干点别的东西触发时机与执行顺序。

2.实战案例

2.1 过滤器

编写过滤器

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

public class MyFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("myfilter执行了");
        filterChain.doFilter(servletRequest,servletResponse);//这个如果不放行,就进不去拦截器,直接就执行两次返回
    }
}

编写过滤器配置类

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FilterConfig {
    @Bean
    public FilterRegistrationBean<MyFilter> RegistTest1(){
        //通过FilterRegistrationBean实例设置优先级可以生效
        //通过@WebFilter(value="/*")和@SerletCompomnetScan作用于启动类也可以
        FilterRegistrationBean<MyFilter> bean = new FilterRegistrationBean<MyFilter>();
        bean.setFilter(new MyFilter());//注册自定义过滤器
        bean.setName("myFilter");//过滤器名称
        bean.addUrlPatterns("/*");//过滤所有路径
        bean.setOrder(1);//优先级,最顶级
        return bean;
    }
}

2.2 拦截器

编写拦截器

import cn.hutool.core.thread.threadlocal.NamedThreadLocal;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Slf4j
public class AaMyInterceptor implements HandlerInterceptor {

    //NamedThreadLocal:Spring提供的一个命名的ThreadLocal实现。线程安全的,每进来一个请求都会创建一个单独的对象,其他用户不会收到影响
    //ThreadLocal,它是线程绑定的变量,提供线程局部变量(一个线程一个 ThreadLocal,A线程的ThreadLocal 只能看到A线程的 ThreadLocal,不能看到B线程的 ThreadLocal)
    //一个请求创建一个对象不会影响到其他请求,所以时间不会混乱
    private NamedThreadLocal<Long> startTimeThreadLocal = new NamedThreadLocal<>("StopWatch-StartTime");

    //控制器方法执行之前执行
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        long beginTime = System.currentTimeMillis();//1、开始时间
        startTimeThreadLocal.set(beginTime);//线程绑定变量(该数据只有当前请求的线程可见)
        return true;//继续流程
    }

    //控制器方法执行以后执行
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        //HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
    }

    //处理完视图和模型数据,渲染视图完毕之后执行afterCompletion()
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        long endTime = System.currentTimeMillis();//2、结束时间
        long beginTime = startTimeThreadLocal.get();//得到线程绑定的局部变量(开始时间)
        long consumeTime = endTime - beginTime;//3、消耗的时间

        System.out.println("开始时间:"+beginTime);
        System.out.println("结束时间:"+endTime);
        System.out.println("消耗时间:"+consumeTime);
        if(consumeTime > 500) {//此处认为处理时间超过500毫秒的请求为慢请求
            //TODO 记录到日志文件 设置日志
            log.info(String.format("%s consume %d millis", request.getRequestURI(), consumeTime));
        } else {
            // 测试的时候由于请求时间未超过500,所以启用该代码
            //request.getRequestURI():请求路径:/test/filter
            //consumeTime:销毁时间
            // 日志打印:/test/filter consume 13 millis
            log.info(String.format("%s consume %d millis", request.getRequestURI(), consumeTime));
        }
    }
}

编写拦截器配置类

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 AaInterceptorConfig implements WebMvcConfigurer {
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
//        registry.addInterceptor(拦截器类).addPathPatterns("路径路径");
        registry.addInterceptor(new AaMyInterceptor()).addPathPatterns("/jemeter/*");
    }
}

标签:拦截器,SpringBoot,Filter,过滤器,import,servlet,public,请求
From: https://www.cnblogs.com/hujunwei/p/17921623.html

相关文章

  • Spring MVC 源码分析 - HandlerMapping 组件(二)之 HandlerInterceptor 拦截器
    HandlerMapping组件HandlerMapping组件,请求的处理器匹配器,负责为请求找到合适的 HandlerExecutionChain 处理器执行链,包含处理器(handler)和拦截器们(interceptors)handler 处理器是Object类型,可以将其理解成HandlerMethod对象(例如我们使用最多的 @RequestMapping 注解所标......
  • 【Java】Spring、SpringBoot、SpringCloud理解和入门
    关于Spring、SpringBoot、SpringCloud我总结了几点。Spring是轻量级的容器框架,目前大多数项目不直接使用Spring的。SpringBoot是Spring的升级版,主要应用单个微服务,关联性小的项目、规模小、硬件要求不高的项目。SpringCloud基于SpringBoot来实现微服务开发组件。主要应用于规......
  • 【SpringBootWeb入门-17】Mybatis-基础操作-动态SQL
    1、章节回顾上一篇文章我们讲解完了Mybatis基础操作,本篇继续学习Mybatis中非常重要的功能:动态SQL。什么是动态SQL:随着用户的输入或外部条件的变化而变化的SQL语句,我们称为动态SQL。简单说SQL语句不是固定的,是动态变化的。就拿我们上一篇所提到的根据条件来查询员工的SQL语句来......
  • Spring Boot学习随笔- 拦截器实现和配置(HandlerInterceptor、addInterceptors)、jar包
    学习视频:【编程不良人】2021年SpringBoot最新最全教程第十三章、拦截器拦截器:Interceptor拦截中断类似于javaweb中的Filter,不过没有Filter那么强大作用SpringMVC的拦截器是一种用于在请求处理过程中进行预处理和后处理的机制。拦截器可以在请求到达控制器之前和......
  • 如何新建SpringBoot2.7.X项目
    新版的idea在创建SpringBoot项目时最低的JDK都需要选择jdk17,可是我的本地只有jdk8,通过创建maven工程,然后在pom中手动填写相关依赖等信息来创建项目,pom文件内容(官网copy的)<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-......
  • SpringBoot原理
    配置SpringBoot中支持三种格式的配置文件.properties.yml.yaml虽然Springboot支持多种文件配置,但是通常在项目开发中,我们一般推荐使用yml文件配置优先级在SpringBoot项目中,常见的属性配置有5种,3种配置文件加上两种外部的配置,生效优先级SrpingBoot配置优先级(低->高):1......
  • SpringBoot集成Memcached实现高效缓存
    一、前言Memcached是一款高性能的分布式内存对象缓存系统,可以用来缓存SQL查询结果、API调试结果等。使用Memcached可以减少对数据库的查询次数,提高系统性能。它主要用于减轻数据库负载,提供应用系统,减少数据库压力。SpringBoot可以快速集成Memcached实现对缓存到读写操作。二、安装......
  • SpringBoot整合Dubbo常用注解类说明
    SpringBoot与Dubbo的整合pom依赖:<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.spr......
  • 【SpringBootWeb入门-16】Mybatis-基础操作-多条件查询操作&XML文件配置SQL
    1、章节回顾上一篇文章我们讲解了Mybatis的增改查操作,本篇继续学习Mybatis的复杂查询操作(多条件查询)。2、增删改查操作-多条件查询操作根据条件姓名、性别、入职时间来查询员工表emp数据,其中员工姓名支持模糊匹配,性别进行精确匹配,入职时间进行范围查询,查询结果按照最后修改时间......
  • backdrop-filter:为元素后面区域添加图形效果
    backdrop-filter:为元素后面区域添加图形效果该属性可以让你为一个元素后面区域(即背景区域)添加图形效果(如模糊或颜色偏移)。它适用于元素背后的所有元素,为了看到效果,必须使元素或其背景至少部分透明。作用于元素背后的区域所覆盖的所有元素与filter的区别:filter作用于元素本身,ba......