SpringBoot实现过滤器Filter的三种方式

news2024/11/23 20:57:08

    • # 实现Filter接口
        • 方式① 使用Filter接口
        • 方式② 使用@Component注解
        • 方式③ Java Config 配置类

# 实现Filter接口

过滤器 Filter 由 Servlet 提供,基于函数回调实现链式对网络请求与响应的拦截与修改。由于基于 Servlet ,其可以对web服务器管理的几乎所有资源进行拦截(JSP、图片文件、HTML 文件、CSS文件等)。

Filter 的生命周期

  • init(): 初始化Filter 实例,Filter 的生命周期与 Servlet 是相同的,也就是当 Web 容器(tomcat)启动时,调用 init() 方法初始化实例,Filter只会初始化一次。需要设置初始化参数的时候,可以写到init()方法中。
  • doFilter(): 业务处理,拦截要执行的请求,对请求和响应进行处理,一般需要处理的业务操作都在这个方法中实现
  • destroy() : 销毁实例,关闭容器时调用 destroy() 销毁 Filter 的实例。

方式① 使用Filter接口

1、在启动类添加注解@ServletComponentScan ,让 Spring 可以扫描到。
2、通过 @WebFilter 注解,将类声明为 Bean 过滤器类。此时可以指定要拦截的url , 但是不能指定过滤器执行顺序。

@Slf4j
@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {

    @Resource
    private RedisTemplate redisTemplate;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        //获取访问 ip 地址
        String ipAddr = getIpAddr(request);
        // 存入缓存10s不允许访问
        String key = new StringBuilder().append("bizKey").append(ipAddr).toString();
        
        if (redisTemplate.hasKey(key)) {
            // 访问次数自增1
            redisTemplate.opsForValue().increment(key, 1);
            log.warn("访问过快,存在强刷行为!key={}", key);
        } else {
            // 第一次访问
            redisTemplate.opsForValue().set(key, 1, 10,
                    TimeUnit.SECONDS);
        }
        try {
            filterChain.doFilter(servletRequest, servletResponse);
        } catch (Exception e) {
            log.warn("认证失败,e:{},url:{},parameters:{}", e,request.getRequestURL(),request.getParameterMap());
            servletResponse.setContentType("application/json");
            servletResponse.setCharacterEncoding("UTF-8");
            servletResponse.getWriter().write(JSONUtil.toJsonStr(Result.fail("业务执行报错~")));
        }
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }

    public static String getIpAddr(HttpServletRequest request){
        String ipAddress = null;
        try {
            ipAddress = request.getHeader("X-Forwarded-For");
            if (ipAddress != null && ipAddress.length() != 0 && !"unknown".equalsIgnoreCase(ipAddress)) {
                // 多次反向代理后会有多个ip值,第一个ip才是真实ip
                if (ipAddress.indexOf(",") != -1) {
                    ipAddress = ipAddress.split(",")[0];
                }
            }
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("Proxy-Client-IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("WL-Proxy-Client-IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getHeader("HTTP_CLIENT_IP");
            }
            if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) {
                ipAddress = request.getRemoteAddr();
            }
        }catch (Exception e) {

        }
        return ipAddress;
    }
}

方式② 使用@Component注解

使用@Component注解后,可以使用@Order注解保证过滤器执行顺序,@Order 注解用于指定组件的执行顺序,其中值越小的组件优先执行。

@Component
@Order(1)
public class MyFilter1 implements Filter {
    // ...
}
@Component
@Order(2)
public class MyFilter2 implements Filter {
    // ...
}

注意: 1、不使用@Order注解,则按照filter类名的字母顺序来执行
2、方式②可以保证执行顺序, 但是过滤器不能指定拦截的url , 只能默认拦截全部
在这里插入图片描述

方式③ Java Config 配置类

使用 @Configuration + @Bean 配置类,注解声明Bean,交由 Spring 容器管理。此方式既能拦截Url,也能指定执行顺序
Java Config 的方式可以通过 @Bean 配置顺序或 FilterRegistrationBean.setOrder() 决定 Filter 执行顺序。(在启动类配置拦截器,此时自定义过滤器不加注解,为普通类即可) 可以指定过滤器要拦截的url 和 过滤器执行顺序, 但需要代码方式实现.

public class MyFilter1 implements Filter {
    // ...
}

public class MyFilter2 implements Filter {
    // ...
}

通过在springboot的configuration中配置不同的FilterRegistrationBean实例,来注册自定义过滤器
这里创建一个configuration类

@Configuration
public class DemoConfiguration {
    @Bean
    public FilterRegistrationBean RegistTest1(){
        //通过FilterRegistrationBean实例设置优先级可以生效
        //通过@WebFilter无效
        FilterRegistrationBean bean = new FilterRegistrationBean();
        bean.setFilter(new Test1Filter());//注册自定义过滤器
        bean.setName("flilter1");//过滤器名称
        bean.addUrlPatterns("/*");//过滤所有路径
        bean.setOrder(1);//优先级,最顶级
        return bean;
    }
    @Bean
    public FilterRegistrationBean RegistTest2(){
        //通过FilterRegistrationBean实例设置优先级可以生效
        //通过@WebFilter无效
        FilterRegistrationBean bean = new FilterRegistrationBean();
        bean.setFilter(new Test2Filter());//注册自定义过滤器
        bean.setName("flilter2");//过滤器名称
        bean.addUrlPatterns("/test/*");//过滤所有路径
        bean.setOrder(6);//优先级,越低越优先
        return bean;
    }
}

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

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

相关文章

重复消费和堆积

接受消息会重复这一现状,然后通过一些方法来消除重复消息对业务的影响 利用幂等性解决重复消息问题 幂等(其任意多次执行所产生的影响均与一次执行的影响相同。) 一个幂等的方法,使用同样的参数,对它进行多次调用和一…

flutter七牛云上传sdk插件qiniu_flutter_sdk使用

flutter七牛云上传sdk插件qiniu_flutter_sdk使用 最近在拆分代码,将上传组件设置成插件,下面记录下实现过程。 一、创建flutter_plugin上传插件 这里Android Studio使用创建plugin 填写一下信息 Project nameProject locationDescriptionProject typ…

单片机入门所需的基础数电和模电知识

要学习单片机并入门相关领域,推荐掌握以下数电和模电的基础知识: 数电知识: 布尔代数和逻辑门:了解布尔代数的基本概念和逻辑门的工作原理,包括与门、或门、非门、与非门、或非门、异或门等。 时序逻辑和时钟信号&a…

AIOps介绍

AIOps介绍 AIOps是指人工智能运维(Artificial Intelligence for IT Operations)的缩写。它是将人工智能(AI)和机器学习(ML)技术应用于IT运维领域的一种方法。 传统的IT运维通常需要人工监测和管理大量的系…

脑机接口科普0022——黑门02:伦理道德问题

本文禁止转载!!!! 脑机接口这个技术,是属于黑科技技术中的一种。 现在已经有很多专家,以及机构,提出脑机接口的存在的一些问题。法律是一块的问题,伦理道德是另一块的问题。 虽然…

苹果iPhone14卡死怎么办?解决办法分享!

正常使用的iPhone14虽然很少会出现卡死的情况,但iPhone就是一台微型电脑,像电脑一样“死机”也不是没可能。 有用户称在使用iPhone14时出现突然出现弹出的提示框无法点击取消,锁屏也解决不了死机的问题。同时又因为屏幕其他区域不能操作&…

MySQL免安装配置教程(win10)

一、下载安装包 1.1、下载zip包 打开官网地址下载zip安装包,这里下载的版本是5.7,可自行选择。 对应下载网址:https://downloads.mysql.com/archives/community/ 根据自己电脑进行选择对应安装包 若需要下载msi安装包(图形化界…

Mysql漏洞处理之升级版本到5.7.42过程指导手册

一、背景 某次安全漏扫,发现MySQL大量漏洞,基于Mysql之用于内网,且版本确实有点旧,考虑升级,综合漏洞分析,只能升级到最新版5.7.42和8.0.33,现场环境:Mysql 5.7.28、5.7.20和mysql&…

高等职业学院校园IP网络广播应用-河北资源环境职业技术学院校园IP广播

职业院校大学校园IP网络广播在河北资源环境职业技术学院产教融合基地的应用 北京海特伟业科技任洪卓发布于2023年6月20日 一、高等职业院校校园IP网络广播系统-广播中心 河北资源环境职业技术学院产教融合基地-高等职业院校校园IP网络广播系统是基于TCP/IP协议校园局域网构建…

通过GPIO子系统编写LED驱动,应用程序控制LED灯亮灭

1、在内核设备树中添加设备信息: LED1的设备树编写需要参考内核的帮助文档: linux-5.10.61/Documentation/devicetree/bindings/gpio 在根节点内部添加led灯设备树节点 :~/linux-5.10.61/arch/arm/boot/dts $ vi stm32mp157a-fsmp1a.dts myled.c #in…

渗透测试思路总结

一、说明 《Metasploit 渗透测试魔鬼训练营》等书已经对渗透测试的步骤流程划分得比较合理透彻了,但感觉在多次通读该类书藉之后仍总感觉不得要领----要对一台给定的主机进行渗透还是不懂到底该如何着手。想来主要是存在以下两个问题。 第一个是在渗透操作系统时&…

Yolov8优化:引入Soft-NMS,提升密集遮挡场景检测精度

1.Soft-NMS介绍 论文地址:https://arxiv.org/pdf/1704.04503.pdf NMS需要优化的参数: IoU 的阈值是一个可优化的参数,一般范围为0~0.5,可以使用交叉验证来选择最优的参数。 R-CNN会从一张图片中找出n个可能是物体的矩形框,然后为每个矩形框为做类别分类概率: 就…

maven测试依赖的排除

1、概念 当 A 依赖 B,B 依赖 C 而且 C 可以传递到 A 的时候,A 不想要 C,需要在 A 里面把 C 排除掉。而往往这种情况都是为了避免 jar 包之间的冲突。 所以配置依赖的排除其实就是阻止某些 jar 包的传递。因为这样的 jar 包传递过来会和其他 …

parallelStream与CompletableFuture

1 了解parallelStream parallelStream怎么实现的并行处理呢? 其底层是Fork/Join并行计算框架的默认线程池,默认线程池的数量就是处理器的数量,可以使用系统属性:-Djava.util.concurrent.ForkJoinPool.common.parallelism{N} 调整…

【数据库】MySQL 高级(进阶) SQL 语句

文章目录 前提条件一、常用查询1. SELECT(显示查询)2. DISTINCT(不重复查询)3. WHERE(有条件查询)4. AND/OR(且/或)5. IN (显示已知值的字段)6. BETWEEN&…

自驾出游擅自使用对讲机属于违法行为?

周末或节假日大多数人通常都会选择自驾出游,或是叫上自己的好友一起出游,这个时候就可以组成一个车队。为了沟通起来更方便,大家一般都喜欢配个对讲机。 不过据调查显示,大多数人并不认为擅自使用对讲机算违法行为。在多个电商平…

【计算机视觉】OFA:通过一个简单的seq2seq的学习框架来统一架构、任务和模态

文章目录 一、导读二、摘要三、介绍四、OFA4.1 I/O & Architecture4.1.1 I/O4.1.2 Architecture 4.2 Tasks & Modalities4.3 预训练数据集4.4 训练与推理4.5 缩放模型 五、实验结果5.1 跨模态任务的结果5.2 单模态任务的结果5.3 zero-shot学习和任务迁移 六、测试结果七…

测试不为人知的小秘密,你占了几个?

1、线上出现小bug,小本本记下,后面偷偷给开发提个bug。 2、操作服务器时,把数据库玩坏了,系统玩崩了,加班熬夜默默的抢救修复。 3、和开发吵了一架,然后重点照顾了他负责的模块,找了一堆bug&a…

智慧无线灌溉在园林中的应用

智慧无线灌溉技术是解决人们生活用水与园林灌溉之间用水矛盾的有效措施之一,对提升园林灌溉效率和节约水资源有着重要的意义。 智慧无线灌溉系统可以自动感知园林植物周围的环境温度、水分等要素,并对感知到的要素进行详细分析和判断,以确定…

小白到运维工程师自学之路 第四十一集 (shell脚本的基本使用)

一、概述 Shell是一种命令行解释器,它是一种编程语言,用于在操作系统上执行命令和脚本。Shell语言是一种脚本语言,它可以用于自动化任务、批处理、系统管理和编写简单的程序。Shell语言通常用于Unix和Linux操作系统中,但也可以在其…