Springboot——自定义Filter使用测试总结

文章目录

  • 前言
  • 自定义过滤器并验证
  • 关于排除某些请求的方式
  • 创建测试接口
  • 请求测试
  • 验证异常过滤器的执行流程
  • 注意事项
  • 资料参考

前言

在Java-web的开发领域,对于过滤器拦截器用处还是很多,但两者的概念却极易混淆。

过滤器拦截器都是采用AOP的核心思想,对具体的实现方法进行增强,都能拦截请求方法。

不同点过滤器拦截器
研发者由Servlet研发由SpringMVC研发
拦截对象拦截WEB请求拦截器不仅可以拦截请求,还能拦截普通方法。
执行顺序过滤器会比拦截器优先执行拦截器在过滤器之后执行,但使用比过滤器简单。
使用场景编码格式转化跨域解决xss攻击权限控制、日志打印、参数验证、回话信息等。

【资料参考】

  • 过滤器和拦截器的异同(小计)
  • springboot配置监听器、过滤器和拦截器

以实际生活中的栗子,作为各个名词的描述:

  • 过滤器 过滤器好比就是筛子,只有满足大小要求的颗粒,才能通过过滤器,不满足的则会筛出来。
  • 拦截器 拦截器就好比是一个门户,只能满足要求,才能进入

这两者本身上其实都差不多,只是在技术层面为了区别各个不同的原理和技术,才定义了不同的名词。

本篇博客不说拦截器,只说过滤器的使用和基本准则。

自定义过滤器并验证

创建Springboot项目,并创建两个自定义的过滤器,如下所示:

  • MyFilter1
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@Slf4j
@Order(1) // 数字越小  优先级越高
@WebFilter(filterName = "myFilter1",urlPatterns = {"/*"})
public class MyFilter1 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("####  MyFilter1 ==== init ####");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        log.info("####  MyFilter1 ==== doFilter ####");
        log.info("####  MyFilter1 ==== doFilter before ####");
        chain.doFilter(request,response);
        log.info("####  MyFilter1 ==== doFilter after ####");
    }

    @Override
    public void destroy() {
        log.info("####  MyFilter1 ==== destroy ####");
    }
}
  • MyFilter2
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@Slf4j
@Order(2) // 数字越小  优先级越高
@WebFilter(filterName = "myFilter2",urlPatterns = {"/*"}) // urlPatterns 设置需要拦截过滤的请求,可以正则表达式,未指定时会拦截所有请求
public class MyFilter2 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("####  MyFilter2 ==== init ####");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        log.info("####  MyFilter2 ==== doFilter ####");
        log.info("####  MyFilter2 ==== doFilter before ####");
        String msg = request.getParameter("msg");
        if("err".equalsIgnoreCase(msg)){
            throw new RuntimeException("传递参数有误,验证过滤器....");
        }
        chain.doFilter(request,response);
        log.info("####  MyFilter2 ==== doFilter after ####");
    }

    @Override
    public void destroy() {
        log.info("####  MyFilter2 ==== destroy ####");
    }
}

可以看到本次使用的是注解方式,除了新增这两个自定义的Filter之外,还需要在启动类上增加一个注解标识,否则自定义的过滤器并不会被加载,如下所示:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;

@SpringBootApplication
@ServletComponentScan // 扫描filter
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class,args);
    }
}

@ServletComponentScan // 扫描filter

在自定义的过滤器中,使用的@WebFilter注解方式,该注解中需要设定某些值,这些参数信息又有什么含义呢?

参数名含义
filterName给过滤器定义别名称,需要唯一区别。
urlPatterns过滤器针对的请求url路径,默认或者不配置时,是过滤所有的请求。此处可以写正则表达式。
initParams自定义过滤器初始化参数的数组,此参数可以通过自定义过滤器 init() 的入参FilterConfig对象的 getInitParameter() 方法获取;(由于过滤器没有直接排除自定义URL不拦截的设定,如果我们需要在自定义拦截的URL中排除部分不需要拦截的URL,可以通过将需要排除的URL放到initParams参数中再在doFilter方法中排除)

关于排除某些请求的方式

参考:SpringBoot自定义过滤器Filter使用详解

其中,有这么一个栗子,如下所示:

@WebFilter(filterName = "testFilter", urlPatterns = "/*", 
        initParams = @WebInitParam(name = "noFilterUrl", value = "/test")) // 给定初始化参数
public class TestFilter implements Filter {
    private List<String> noFilterUrls; 
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 从过滤器配置中获取initParams参数
        String noFilterUrl = filterConfig.getInitParameter("noFilterUrl");
        // 将排除的URL放入成员变量noFilterUrls中
        if (StringUtils.isNotBlank(noFilterUrl)) {
            noFilterUrls = new ArrayList<>(Arrays.asList(noFilterUrl.split(",")));
        }
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        // 过滤器配置的  urlPatterns  为 /* 表示过滤所有的请求
        // 有请求进来时,会先进入到过滤器中,此时则获取请求的uri地址
        String url = ((HttpServletRequest)servletRequest).getRequestURI();
        Boolean flag = false;
        if (!CollectionUtils.isEmpty(noFilterUrls)) {
            for (String noFilterUrl : noFilterUrls) {
                // 如果请求的地址中包含有 initParams 传递的参数值,则不继续向下执行
                if (url.contains(noFilterUrl)) {
                    flag = true;
                    break;
                }
            }
        }
        if (!flag) {
            ......	//过滤请求响应逻辑
        } 
        // 继续向下执行,调用该方法
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {

    }
}

感叹这个作者的奇妙思维方式!

创建测试接口

回归正题,创建上面两个自定义的过滤器之后,还需要创建一个测试接口,如下所示:

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/test1")
@Api(tags = "测试控制器  1")
@Slf4j
public class TestController {

    @PostMapping("/demo1")
    @ApiOperation("demo1")
    public String demo1(){
        log.info("请求被调用了!!!!!");
        return "demo 1 .....";
    }
}

启动项目观察控制台打印。
在这里插入图片描述

这里的顺序是加在时的顺序,并不是@Order(int) 设定的原因!

请求测试

清空控制台的日志信息,请求测试接口,观察控制台日志输出情况,如下所示:
在这里插入图片描述
在这里插入图片描述

通过调用自定义过滤器filter的日志打印,可以很清楚的了解到请求的执行过程。如下所示:
在这里插入图片描述
由最开始的客户端请求–》MyFilter1–》MyFilter2–》指定的controller–》MyFilter2–》MyFilter1–》客户端。闭环操作。

这里为什么是MyFilter1MyFilter2之前,根本原因就是定义filter时,设定了@Order(1)给定了优先级。

数字越小,优先级越高!

验证异常过滤器的执行流程

MyFilter2中,给定了请求参数 msg=err时抛出异常。

出现异常了,后面的filter还会继续执行不?接下来再次进行请求测试:
在这里插入图片描述
查看控制台,观察日志信息,如下所示:
在这里插入图片描述
在执行到MyFilter1MyFilter2后,由于MyFilter1中抛出了异常,还没有执行对应的chain.doFilter(request,response);后续的链路,所以日志在此处戛然而止!

出现异常后,并不会继续执行后续的filter!

注意事项

自定义的Filter类上,不要添加 @Component 注解,不然会导致程序启动报错,启动不成功
在这里插入图片描述

资料参考

SpringBoot自定义过滤器Filter使用详解

这个大佬博客中给出了第二种方式,但总感觉哪里有问题,关于第二种方式的配置操作,可以参考下列资料:

springboot 自定义过滤器

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HTML 扫盲

✏️作者&#xff1a;银河罐头 &#x1f4cb;系列专栏&#xff1a;JavaEE &#x1f332;“种一棵树最好的时间是十年前&#xff0c;其次是现在” 目录前言HTML 结构快速生成代码框架HTML 常见标签注释标签标题标签: h1-h6段落标签&#xff1a;p换行标签&#xff1a;br格式化标签…

PTA第六章作业详解

&#x1f680;write in front&#x1f680; &#x1f4dd;个人主页&#xff1a;认真写博客的夏目浅石. &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd; &#x1f4e3;系列专栏&#xff1a;夏目的作业 &#x1f4ac;总结&#xff1a;希望你看完之后&am…

JAVA进阶 —— Stream流

目录 一、 引言 二、 Stream流概述 三、Stream流的使用步骤 1. 获取Stream流 1.1 单列集合 1.2 双列集合 1.3 数组 1.4 零散数据 2. Stream流的中间方法 3. Stream流的终结方法 四、 练习 1. 数据过滤 2. 数据操作 - 按年龄筛选 3. 数据操作 - 演员信息要求…

蓝桥杯第十四届蓝桥杯模拟赛第三期考场应对攻略(C/C++)

这里把我的想法和思路写出来&#xff0c;恳请批评指正&#xff01; 目录 考前准备 试题1&#xff1a; 试题2&#xff1a; 试题3&#xff1a; 试题4&#xff1a; 试题5&#xff1a; 试题6&#xff1a; 试题7&#xff1a; 试题8&#xff1a; 试题9&#xff1a; 试题1…

第十六章 Java为什么使用序列化

为何要指定serialVersionUID的值如果不指定显示serialVersionUID的值&#xff0c;jvm在序列化时会自动生成一个serialVersionUID&#xff0c;跟属性一起序列化&#xff0c;再进行持久化或者网络传输&#xff0c;在反序列化时&#xff0c;jvm会根据属性自动生成一个新版的serial…

【Jetpack】Lifecycle 架构组件 ( 系统组件与普通组件解耦 | Lifecycle 解耦系统组件与普通组件 | 解耦服务组件与普通组件 | 监听应用程序生命周期 )

文章目录一、系统组件与普通组件解耦二、Lifecycle 解耦 Activity 系统组件与 UI 组件1、传统实现方式① Activity 系统组件② 布局文件③ 执行效果2、LifeCycle 实现方式① 自定义 UI 组件② Activity 系统组件③ 布局组件④ 执行效果三、LifecycleService 解耦 Service 与 UI…

为什么北欧的顶级程序员数量远超中国?

说起北欧&#xff0c;很多人会想到寒冷的冬天&#xff0c;漫长的极夜&#xff0c;童话王国和圣诞老人&#xff0c;但是如果我罗列下诞生于北欧的计算机技术&#xff0c;恐怕你会惊掉下巴。Linux&#xff1a;世界上最流行的开源操作系统&#xff0c;最早的内核由Linus Torvalds开…

2022济南大学acm新生赛题解

通过答题情况的难度系数&#xff1a; 签到&#xff1a;ABL 简单&#xff1a;DGKQ 中等&#xff1a;CMN 困难&#xff1a;EFHIJOPRST A-和 算出n个数的和判断正负性即可&#xff01;&#xff01;&#xff01; 发现很多同学的代码错误&#xff1a;要么sum未赋初值&#xf…

DDOS攻击

注&#xff1a;本博客只是为了自己的学习&#xff0c;记录自己的学习&#xff0c;请勿用于其他途径、1、winR-->cmd2、ping 网站3、替换IP1 import java.io.BufferedInputStream;2 import java.io.IOException;3 import java.net.MalformedURLException;4 import java.net.U…

Vue3做出B站【bilibili】 Vue3+TypeScript+ant-design-vue【快速入门一篇文章精通系列(一)前端项目案例】

本项目分为二部分 1、后台管理系统&#xff08;用户管理&#xff0c;角色管理&#xff0c;视频管理等&#xff09; 2、客户端&#xff08;登录注册、发布视频&#xff09; Vue3做出B站【bilibili】 Vue3TypeScriptant-design-vue【快速入门一篇文章精通系列&#xff08;一&…

【C++】STL简介 及 string的使用

文章目录1. STL简介1.1 什么是STL1.2 STL的版本1.3 STL的六大组件2. string类的使用2.1 C语言中的字符串2.2 标准库中的string类2.3 string类的常用接口说明1. string类对象的常见构造2. string类对象的容量操作3. string类对象的修改操作4. resize和reserve5. 认识迭代器&…

产品研发项目进度管理软件工具有哪些推荐?整理10款最佳进度管理软件

项目进度管理是确保项目按时完成的关键过程&#xff0c;使用合适的项目进度管理工具能确保帮助项目管理者实时了解和控制项目的进展情况&#xff0c;及时发现和解决问题&#xff0c;减少项目风险&#xff0c;提高项目效率和管理水平。这里将整理出国内外最受欢迎的10款项目进度…

ASEMI低压MOS管SI2301参数,SI2301体积,SI2301尺寸

编辑-Z ASEMI低压MOS管SI2301参数&#xff1a; 型号&#xff1a;SI2301 漏极-源极电压&#xff08;VDS&#xff09;&#xff1a;20V 栅源电压&#xff08;VGS&#xff09;&#xff1a;8V 漏极电流&#xff08;ID&#xff09;&#xff1a;2.3A 功耗&#xff08;PD&#xf…

Simulink壁咚(一)——What and How

目录 一、前言 二、Simulink 知多少 三、滤波算法 四、Model Verification 五、Model Coverage 六、Simulink测试实例 七、Simulink Test 八、Test Manager 九、Test Harness 十、 学习 一、前言 Simulink从2017b以后更加工程化和实用化&#xff0c;基于MBD的功能日趋…

MATLAB绘制ROC曲线

ROC曲线(Receiver Operating Characteristic Curve) 1 简介 ROC曲线是用于评估二元分类模型&#xff08;如Logistic回归&#xff09;表现优劣的一种工具&#xff0c;其横轴表示假阳性率&#xff08;false positive rate&#xff0c;FPR&#xff09;&#xff0c;即实际为负例但…

MySQL事务详解

&#x1f3c6;今日学习目标&#xff1a; &#x1f340;Spring事务和MySQL事务详解 ✅创作者&#xff1a;林在闪闪发光 ⏰预计时间&#xff1a;30分钟 &#x1f389;个人主页&#xff1a;林在闪闪发光的个人主页 &#x1f341;林在闪闪发光的个人社区&#xff0c;欢迎你的加入: …

vue3 构建属于自己的组件库dxui

文章目录前言第一步&#xff0c;通过vue-cli搭建vue3框架第二步&#xff0c;构建一个入口&#xff0c;将所有的组件统一管理第三步 修改package.json &#xff0c;对组件进行单独打包第四步输入命令行开始打包第五步&#xff0c;修改package.json文件&#xff0c;为npm 发布做准…

[ vulnhub靶机通关篇 ] 渗透测试综合靶场 DC-1 通关详解 (附靶机搭建教程)

&#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 _PowerShell &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 &#x1f389;点赞➕评论➕收藏 养成习…

Python 基础教程【1】:Python介绍、变量和数据类型、输入输出、运算符

本文已收录于专栏&#x1f33b;《Python 基础》文章目录1、Python 介绍2、变量和数据类型2.1 注释的使用2.2 变量以及数据类型2.2.1 什么是变量&#xff1f;2.2.2 怎么给变量起名&#xff1f;2.2.3 变量的类型&#x1f3a8; 整数 int&#x1f3a8; 浮点数&#xff08;小数&…

教你成为比卡卡西还牛逼的全能忍者,全拷贝与分割函数

如何成为一个集雷切&#xff0c;写轮眼侦查和拷贝与一身的卡卡西&#xff0c;下面教你&#xff01; 目录 第一式——雷切&#xff01; strtok 第二式——写轮眼侦查&#xff01; strerror函数 第三式——写轮眼拷贝&#xff01; memcpy 模拟实现memcpy函数 &#x1f60e;…