WEB三大组件之Filter

news2024/9/25 1:14:10

在很多项目中通常需要用到filter来实现用户身份识别,并将识别出来的用户信息,保存到ThreadLocal对应的上下文,这样在后续的请求链路中,在任何地方都可以直接获取当前的登录用户了。

来看一下Java WEB三大组件之一的过滤器Filter,是如何在技术派中发挥作用的

使用场景

实现类路径:com/github/paicoding/forum/web/hook/filter/ReqRecordFilter.java

1.Filter基础知识点

来了解一下Filter的基础把。

Filter称为过滤器,主要用来拦截http请求,来做一些其他的事情

流程说明

一个http请求过来之后

        首先进入filter,执行相关的业务逻辑

        若判定通行,则进入Servlet逻辑,Servlet执行完毕后,又返回Filter,最后在返回给请求方

        判定失败,直接返回,不需要将请求发给Servlet

应用场景

通过上面的流程,可以推算下具体的使用场景:

        在filter层,来获取用户的身份

        可以考虑在filter层做一些常规的校验(如参数校验。referer校验、权限控制等)

        可以在filter层做运维、安全防护相关的工作(如全链路打点,可以在filter层分配一个traceId;也可以在这一层做限流等)

实现说明:

filter的基本使用比较简单,实现Filter接口即可,如;

@Slf4j
@WebFilter(urlPatterns = "/*", filterName = "reqRecordFilter", asyncSupported = true)
public class ReqRecordFilter implements Filter {
    private static Logger REQ_LOG = LoggerFactory.getLogger("req");
    /**
     * 返回给前端的traceId,用于日志追踪
     */
    private static final String GLOBAL_TRACE_ID_HEADER = "g-trace-id";

    @Autowired
    private GlobalInitService globalInitService;

    @Autowired
    private StatisticsSettingService statisticsSettingService;

    @Override
    public void init(FilterConfig filterConfig) {
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        long start = System.currentTimeMillis();
        HttpServletRequest request = null;
        StopWatch stopWatch = new StopWatch("请求耗时");
        try {
            stopWatch.start("请求参数构建");
            request = this.initReqInfo((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse);
            stopWatch.stop();
            stopWatch.start("cors");
            CrossUtil.buildCors(request, (HttpServletResponse) servletResponse);
            stopWatch.stop();
            stopWatch.start("业务执行");
            filterChain.doFilter(request, servletResponse);
            stopWatch.stop();
        } finally {
            stopWatch.start("输出请求日志");
            buildRequestLog(ReqInfoContext.getReqInfo(), request, System.currentTimeMillis() - start);
            // 一个链路请求完毕,清空MDC相关的变量(如GlobalTraceId,用户信息)
            MdcUtil.clear();
            ReqInfoContext.clear();
            stopWatch.stop();

            if (!isStaticURI(request) && !EnvUtil.isPro()) {
                log.info("{} - cost:\n{}", request.getRequestURI(), stopWatch.prettyPrint(TimeUnit.MILLISECONDS));
            }
        }
    }

    @Override
    public void destroy() {
    }

上面有三个方法:

        init: 初始化执行

        destory: 销毁时执行

        dofilter: 重点关注这个,filter规则命中请求,都会走进来

                三个参数,注意第三个FilterChain,这里是经典的责任链模式

                执行filterChain.doFilter(request, servletResponse); 表示会继续将请求执行下去;若不执行这一句,表示这一次的http请求到此为止,后面免得不走下去了。

3.filter注册

过滤注册到Spring容器有多种使用姿势,出上面使用的@WebFilter之外还有其他的使用姿势。

3.1 WebFilter注解

使用WebFilter注解,标注到实现自己额的过滤器上,有几个参数需要注意,其中urlPatterns最为常用,表示这个filter使用与那些url请求(默认场景下全部都被拦截)

属性名 

类型

描述

filterNameString指定过滤器的name属性,等价于<filter-name>

value

String[]该属性等价于urlPatterns属性。但是两者不应该同时使用。
urlPatternsString[]指定一组过滤器的URL匹配模式。等价于<url-pattern>标签
servletNamesString[]

指定过滤器将应用于哪些Servlet。取值是@WebServlet中的name属性的取值,或者是web.xml中<servlet-name>的取值

dispatcherTypesDispatcherTypes指定过滤器的转发模式。具体取值包括: ASYNC、ERROR、FORWARD、INCLUDE、REQUEST
initParamsWebInitParm[]指定一组过滤器初始化参数。等价于<init-param>标签
asyncSupportedboolean声明过滤器是否支持异步操作模式,等价于<async-supported>标签
descriptionString该过滤器的描述信息,等价于<description>
displayNameString该过滤器的显示名,通常配合工具使用,等价于<display-name>

使用这个注解时,请注意,需要在启动类/配置类添加@ServletComponentScan注解来启用

如:

3.2 FilterRegistrationBean

上面这一种比较简单,但是再指定Filter的优先级的时候比较麻烦,不如下面这种方式简单

4.实例说明

接下来我们看一下,filter在技术派中的具体表现,干了那三件事:

身份识别 ,并保存身份到ReqInfoContext上下文中:

记录请求记录:

添加跨域支持:

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

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

相关文章

flutter环境搭建实践

Dart Dart 是一种客户端和服务器端的编程语言&#xff0c;最早由 Google 提出。它被设计用于构建高性能、高度可伸缩和可靠的应用程序。Dart 可以编译成本地代码或者在虚拟机中直接运行。在移动应用开发中&#xff0c;Dart 主要用于开发 Flutter 应用。 Flutter 和 Dart 的关…

【数据结构和算法初阶(C语言)】队列实操(概念实现+oj题目栈和队列的双向实现,超级经典!!!)

1. 队列的概念及结构 队列&#xff1a;只允许在一端进行插入数据操作&#xff0c;在另一端进行删除数据操作的特殊线性表&#xff0c; 队列具有先进先出 FIFO(First In First Out) 入队列&#xff1a;进行插入操作的一端称为队尾 出队列&#xff1a;进行删除操作的一端称为…

基于单片机的车载酒精含量自检系统设计与实现

摘要:调查显示,大约50%的交通事故与酒后驾车有关,酒后驾车已成为车祸致死的首要原因。为从根本上杜绝酒后驾车,设计了一款基于STC89C52 单片机的车载酒精含量自检系统,该系统能很好地解决酒驾问题,控制简单、使用方便,具有很好的应用价值。 关键词:STC89C52 单片机;车…

Redis:持久化、线程模型、大 key

Redis持久化方式有什么方式&#xff1f; Redis 的读写操作都是在内存中&#xff0c;所以 Redis 性能才会高&#xff0c;但是当 Redis 重启后&#xff0c;内存中的数据就会丢失&#xff0c;那为了保证内存中的数据不会丢失&#xff0c;Redis 实现了数据持久化的机制&#xff0c…

【计算机视觉】二、图像形成:1、向量和矩阵的基本运算:线性变换与齐次坐标

文章目录 一、向量和矩阵的基本运算1、简单变换1. 平移变换2. 缩放变换3. 旋转变换4. 一般线性变换 2、齐次坐标0. 齐次坐标表示1. 2D点的齐次坐标变换2. 投影空间 ( x , y , w ) (x, y, w) (x,y,w)3. 2D直线的齐次坐标表示a. 直线的参数方程表示b. 直线的法向量和原点距离表示…

React——react 的基本使用

前提&#xff1a;安装全局的脚手架&#xff0c;通过create-creat-app 项目名&#xff0c;我们创建好一个新项目&#xff0c;cd进去&#xff0c;通过npm start去运行该项目 注意&#xff1a;简单看下demo的配置&#xff0c;在根目录我们可以看到&#xff0c;没有任何webpack的…

html5cssjs代码 018颜色表

html5&css&js代码 018颜色表 一、代码二、效果三、解释 这段代码展示了一个基本的颜色表&#xff0c;方便参考使用&#xff0c;同时也应用了各种样式应用方式。 一、代码 <!DOCTYPE html> <html lang"zh-cn"> <head><title>编程笔记…

15. jwt认证中间件

在上一篇登录功能的实现中&#xff0c;我们使用了jwt作为鉴权组件&#xff0c;其中登录后会颁发token。前端在访问后续请求时&#xff0c;可以带上这个token。对于一些需要权限校验的请求&#xff0c;我们就需要验证这个token&#xff0c;从token中获取到用户id&#xff08;有了…

8-图像放大

其实&#xff0c;就是开辟一个zoomwidth&#xff0c;zoomheight的内存&#xff0c;再分别赋值即可。 void CDib::Maginify(float xZoom, float yZoom) { //指向原图像指针 LPBYTE p_data GetData(); //指向原像素的指针 LPBYTE lpSrc; //指向缩放图像对应像素的指针 LPBYTE l…

实验二 基本搜索技术 五星图案节点填上数字+遍历所有黑点+门牌号

目的&#xff1a; 1. 掌握递归和排序 2. 掌握BFS与队列 3. 掌握DFS和递归 4. 熟悉并理解回溯问题 实验内容&#xff1a; 1.在五星图案节点填上数字&#xff1a;1~12&#xff0c;不包括7和11。 要求每条直线上数字和相等。 如图就是一个恰当的填法。 请搜索所有可能的填…

SpringMVC请求、响应和拦截器的使用

SpringMVC请求 RequestMapping注解 RequestMapping注解的作用是建立请求URL和处理方法之间的对应关系 RequestMapping注解可以作用在方法和类上 1. 作用在类上&#xff1a;第一级的访问目录 2. 作用在方法上&#xff1a;第二级的访问目录 3. 细节&#xff1a;路径可以不编写…

在Django中使用PyJWT实现登录及验证功能

目录 1、安装PyJWT 2、对信息加密及解密 3、配置登录视图和及url 4、登录装饰器 5、在验证有登录权限的的视图中登录 PyJWT的使用 1、安装PyJWT pip isntall pyjwt 2、对信息加密及解密 import jwt import datetime from jwt import exceptions# 加密盐 JWT_SALT &qu…

深入探索Java中的MarkWord与锁优化机制——无锁、偏向锁、自旋锁、重量级锁

引言 在Java并发编程领域&#xff0c;有效管理对共享资源的访问显得尤为关键。为了保障线程安全&#xff0c;Java虚拟机&#xff08;JVM&#xff09;引入了一系列精妙的锁机制&#xff0c;这其中的核心概念就是Java对象头中的MarkWord。本文将详尽解析MarkWord的作用&#xff…

CVPR2024 | 大核卷积新高度101x101,美团提出PeLK

https://arxiv.org/pdf/2403.07589.pdf 本文概述 最近&#xff0c;一些大核卷积网络以吸引人的性能和效率进行了反击。然而&#xff0c;考虑到卷积的平方复杂度&#xff0c;扩大内核会带来大量的参数&#xff0c;而大量的参数会引发严重的优化问题。由于这些问题&#xff0c;当…

code摘录日记[矩阵变元素,变列向量,3D表面图,table行列设置] Matlab

矩阵变元素&#xff0c;变列向量 W1(Z1 < Z2) nan; % Z1,Z2 all matrix,Only plot points where Z1 > Z2;Z1 < Z2位置值填为NaNx x(:); % Now x is a 30-by-1 vector; matrix变列vector技巧3D表面图 hand figure; % Handle to the figure, for more plotting later…

QComboBox相关的qss学习

QT有关QCobobox控件的样式设置&#xff08;圆角、下拉框&#xff0c;向上展开、可编辑、内部布局等&#xff09;_qcombobox样式-CSDN博客 原始图&#xff1a; 红色边框&#xff1a; QComboBox{ border:2px solid rgb(255, 85, 0); } 绿色背景&#xff1a; QComboBox{ border…

[云原生] Prometheus自动服务发现部署

一、部署服务发现 1.1 基于文件的服务发现 基于文件的服务发现是仅仅略优于静态配置的服务发现方式&#xff0c;它不依赖于任何平台或第三方服务&#xff0c;因而也是最为简单和通用的实现方式。 Prometheus Server 会定期从文件中加载 Target 信息&#xff0c;文件可使用 YAM…

App Inventor 2 Clipboard 拓展:实现剪贴板的复制粘贴功能

效果如下&#xff1a; 此 Clipboard 拓展由中文网开发及维护&#xff0c;最新版本 v1.0&#xff0c;基于 TaifunClipboard 开发。 使用方法 属性及方法很简单&#xff0c;默认操作成功后显示提示信息&#xff0c;SuppressToast设置为 假 后&#xff0c;则不显示提示信息。 经测…

中创ET4410台式电桥固件升级工具(修复了列表扫描的BUG)

中创ET4410台式LCR数字电桥固件升级工具和最新版固件&#xff08;修复了列表扫描的BUG&#xff09; 中创ET4410 台式LCR数字电桥 简单开箱测评&#xff1a;https://blog.zeruns.tech/archives/763.html 之前买的中创ET4410台式LCR数字电桥固件有BUG&#xff08;胜利的VC4090C…

OpenCV实战(33)——OpenCV与深度学习的碰撞

OpenCV实战&#xff08;33&#xff09;——OpenCV与深度学习的碰撞 0. 前言1. 深度学习和卷积神经网络2. 使用深度学习进行人脸检测2.1 SSD 简介2.2 使用 SSD 执行人脸检测 3. 完整代码小结系列链接 0. 前言 深度学习是机器学习的一个子领域&#xff0c;基于传统的神经网络和卷…