Spring 拦截器实现请求拦截与参数处理【拦截器(Interceptor)和过滤器(Filter)的区别】

业务场景:
项目中需要使用请求头传输一个密文字符串,后端服务获取密文字符串后,进行解密验证,然后执行响应的业务,这里有好几个接口都用需要使用这个密文字符串,如果我们在每个接口中进行校验处理,就显得太笨拙了,那有没有统一的处理方法呢?我想到了使用拦截器 HandlerInterceptor 处理,以下是使用分享。

什么是拦截器?

拦截器,顾名思义,就是拦截,对用户请求进行拦截过滤处理。

拦截器的生效时机?

  • 请求进入 Controller 之前,通过拦截器请求执行相关逻辑(符合我们上面的场景)。
  • Controller 执行之后,只是Controller执行完毕,还没到视图渲染,通过拦截器执行相关逻辑。
  • Controller 执行完毕,请求全部结束,通过拦截器执行相关逻辑。

HandlerInterceptor 源码:

 package org.springframework.web.servlet;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.lang.Nullable;public interface HandlerInterceptor {default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {return true;}default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {}default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {}
}

自定义拦截器:
HandlerInterceptor 接口只给我们定义了方法,具体的业务逻辑需要我们自己去实现,自定义拦截器需要实现HandlerInterceptor ,代码如下:

package com.study.web.intercept;import cn.hutool.core.util.StrUtil;
import com.study.utils.DesECBUtil;
import com.study.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;@Slf4j
@Component
public class MyIntercept implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//header 中获取密文String code = request.getHeader("code");if (StringUtils.isBlank(code)) {//为空  不通过throw new BusinessException("code 为空,请核实后重试");}//校验String userCode;try {userCode = DesECBUtil.decryptDES(new String(Base64.decodeBase64(code)), ztmcSecretKey);} catch (Exception e) {log.error("code 解密失败,失败原因:", e);throw new BusinessException("code 解密失败,请联系管理员处理");}//这个code 有时间戳String[] userCodeArr = userCode.split(StrUtil.UNDERLINE);//解密出来的是 usercode_时间戳String userNo = userCodeArr[0];//获取时间戳long timestamp = Long.parseLong(userCodeArr[1]);//获取当前时间戳long currentTimestamp = System.currentTimeMillis() / 1000;//当前时间戳-解密时间戳>30分钟 即过期log.info("当前时间戳秒:{},解密时间戳秒:{}",currentTimestamp,timestamp);if (currentTimestamp - timestamp > 1800) {//链接已失效throw new BusinessException("链接已失效,请重新打开链接");}//设置coderequest.setAttribute("code", userNo);return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}}

我们这里是需要校验header 中的密文字符串是否合法,故要前置校验,所以使用了preHandle 方法。

配置拦截器

我们将⾃定义拦截器加⼊ WebMvcConfigurer 的 addInterceptors ⽅法中,并指定需要拦截的接口路径。

package com.study.web.config;import com.study.web.intercept.PerformanceReviewIntercept;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import javax.annotation.Resource;@Configuration
public class MyInterceptorConfig implements WebMvcConfigurer {@Resourceprivate MyIntercept MyIntercept ;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(performanceReviewIntercept)//添加需要拦截的接口路径.addPathPatterns("intercept/intercept-demo/*");}}

至此,这已经是一个完成可用的拦截器了,可以帮我们统一进行 code 解密验证,就无需去每个 Controller 去处理了。

拦截器(Interceptor)和过滤器(Filter)的区别?

  • 实现原理不同:拦截器是基于Java反射机制实现,而过滤器是基于函数回调的。
  • 使用范围不同:拦截器是 Spring 的一个组件,由 Spring 容器管理,无需依赖 Tomcat 等容器,可以单独使用,而过滤器实现了 Servlet 接口,导致过滤器的使用要依赖于Tomcat等容器,所以他只能在web程序中使用。
  • 触发时机不同:拦截器是在请求进入servlet后,在进入Controller之前、之后、完毕进行处理的,而过滤器是在请求进入容器后,但在进入servlet之前进行预处理,请求结束是在servlet处理完以后。
  • 拦截的请求范围不同:拦截器只会对Controller中请求或访问static目录下的资源请求起作用,而过滤器几乎可以对所有进入容器的请求起作用。
  • 拦截器可以获取IOC容器中的各个bean,在拦截器里注入一个bean,可以调用各种业务逻辑,而过滤器就则不可以。

拦截器(Interceptor)和过滤器(Filter)的相似之处?

Spring的拦截器与Servlet的Filter有相似之处,比如二者都是AOP编程思想的体现,都能实现权限检查、日志记录等。

总结:过滤器只能在 Servlet 前后起作用,而拦截器能够到方法前后、异常抛出等,明显拦截器更具备深度,并且拦截器是 Spring 的一个组件,因此拦截器的使用具有更大的使用空间,在Spring 的程序中建议优先使用拦截器,而非过滤器。

如有不正确的地方请各位指出纠正。

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

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

相关文章

AI预测福彩3D第13弹【2024年3月20日预测--第3套算法重新开始计算第3次测试】

今天咱们继续对第3套算法进行第3次测试,第3套算法加入了012路的权重。废话不多说了,直接上结果吧~ 最终,经过研判分析,2024年3月20日福彩3D的七码预测结果如下: 百位:7 4 8 3 6 9 0(5换0&#x…

锂电池寿命预测 | Matlab基于ALO-SVR蚁狮优化支持向量回归的锂离子电池剩余寿命预测

目录 预测效果基本介绍程序设计参考资料 预测效果 基本介绍 锂电池寿命预测 | Matlab基于ALO-SVR蚁狮优化支持向量回归的锂离子电池剩余寿命预测 基于蚁狮优化和支持向量回归的锂离子电池剩余寿命预测: 1、提取NASA数据集的电池容量,以历史容量作为输入,…

Java项目:66 ssm实验室耗材管理系统设计与实现+jsp

作者主页:源码空间codegym 简介:Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 管理员管理实验材料,审核教师与学生对实验材料的申请信息,统计每学年实验材料的使用总数信息。 教师申请使用实验材料…

【探索Linux】—— 强大的命令行工具 P.28(网络编程套接字 —— 简单的UDP网络程序模拟实现)

阅读导航 引言一、UDP协议二、UDP网络程序模拟实现1. 预备代码⭕makefile文件⭕打印日志文件⭕打开指定的终端设备文件,并将其作为标准错误输出的目标文件描述符 2. UDP 服务器端实现(UdpServer.hpp)3. UDP 客户端实现(main函数&a…

day04vue学习

day04 一、学习目标 1.组件的三大组成部分(结构/样式/逻辑) ​ scoped解决样式冲突/data是一个函数 2.组件通信 组件通信语法父传子子传父非父子通信(扩展) 3.综合案例:小黑记事本(组件版&#xff09…

全量知识系统的核心-全量知识的一个“恰当组织”的构想及百度AI答问

全量知识系统的核心-全量知识的一个恰当组织 Q1. 以下是对 我刚刚完成的文档“全量知识系统的核心:全量知识的一个恰当组织构想”的百度AI答复。由于字数400的限制,内容被分成四段. 第一次回答:学科和科学的框架 关于技术学科、一般学科和…

DeprecationWarning: isDaemon() is deprecated, get the daemon attribute instead

报错处理 # t.setDaemon(True) # 阙辉注释 t.daemonTrue # 阙辉新增

已有TensorFlow安装包新建相应python版本的虚拟环境

已有TensorFlow安装包新建虚拟环境 新建conda虚拟环境 新建的虚拟环境默认在Anaconda安装目录D:\Anaconda3\envs(根据自己的安装目录看) 切换到新建的虚拟环境 在这里可以直接安装下载好的TensorFlow安装包 检查是否安装好 输入python进入python环境…

YOLOv7 | 添加GSConv,VoVGSCSP等多种卷积,有效提升目标检测效果,代码改进(超详细)

⭐欢迎大家订阅我的专栏一起学习⭐ 🚀🚀🚀订阅专栏,更新及时查看不迷路🚀🚀🚀 YOLOv5涨点专栏:http://t.csdnimg.cn/QdCj6 YOLOv7专栏: http://t.csdnimg.cn/dy…

《论文阅读》端到端情感原因对提取的有效子句间建模

《论文阅读》端到端情感原因对提取的有效子句间建模 前言简介模型架构Document EncodingInter-Clause Relationship ModelingClause Pair Representation Learning and Ranking损失函数问题前言 亲身阅读感受分享,细节画图解释,再也不用担心看不懂论文啦~ 无抄袭,无复制,纯…

浙政钉埋点:深入解析与应用实践

一、引言 在数字化时代,数据已经成为驱动业务发展的重要动力。对于政府机构而言,如何有效收集、分析和利用数据,以提升公共服务质量和效率,已成为一项重要课题。浙政钉作为浙江省政府推出的数字化协同办公平台,其埋点…

使用Python实现凯撒密码加密

凯撒密码(Caesar Cipher)是一种简单的替换式密码,其加密原理是将明文中的每个字符按照一定的偏移量进行替换,从而得到密文。在Python中,我们可以使用内置的字符串函数和循环结构来实现凯撒密码的加密过程。 以下是一个…

使用nginx搭建的文件服务器一直提示 404 Not Found ,是文件不存在还是没有权限?

使用nginx搭建一个简单的文件服务器,配置如下 user root; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid;# Load dynamic modules. See /usr/share/nginx/README.dynamic. include /usr/share/nginx/modules/*.conf;events {wor…

mapbox 获取当前比例尺 scale

一、mapbox中提供了比例尺控件,在创建地图后可使用此方式显示比例尺控件 map.addControl(new mapboxgl.ScaleControl(), bottom-left) 可通过修改css改变自带比例尺样式 二、计算得出当前scale, 具体代码可在mapbox源码中查看,此处仅以单位M…

爬虫逆向sm3和sm4 加密 案例

注意!!!!某XX网站逆向实例仅作为学习案例,禁止其他个人以及团体做谋利用途!!! 案例--aHR0cDovLzExMS41Ni4xNDIuMTM6MTgwODgvc3Vic2lkeU9wZW4 第一步:分析页面和请求方式 …

spark基本原理UI界面解读

这里是引用 1 八股文 1.1 基本原理 driver节点是整个应用程序的指挥所 指挥官是sparkcontext 环境:构建一个集群 应用程序提交 确定主节点,确定指挥所driver,确定指挥官sparkcontext sparkcontext会向资源管理器申请资源 会将作业分…

常见的几个Python技术难题

大家在日常开发中有没有遇到一些难题呢?计划后面出几期专题针对性的解决。大家如果有其它问题可以在评论区给出哈。 以下是几个Python技术难题的例子: 并发和多线程编程:Python的全局解释器锁(GIL)限制了多线程的并行…

华为OD机试 - 租车骑绿岛(Java JS Python C C++)

题目描述 部门组织绿岛骑行团建活动。租用公共双人自行车,每辆自行车最多坐两人,最大载重M。 给出部门每个人的体重,请问最多需要租用多少双人自行车。 输入描述 第一行两个数字m、n,分别代表自行车限重,部门总人数。 第二行,n个数字,代表每个人的体重,体重都小于…

CCF-CSP认证考试 202303-2 垦田计划 100分题解

更多 CSP 认证考试题目题解可以前往:CSP-CCF 认证考试真题题解 原题链接: 202303-2 垦田计划 时间限制: 1.0s 内存限制: 512.0MB 问题描述 顿顿总共选中了 n n n 块区域准备开垦田地,由于各块区域大小不一&#xf…

Effective-C++阅读解析条款(条款一:视C++为一个语言联邦)

个人主页:Lei宝啊 愿所有美好如期而遇 前言 博主只是将书中内容用自己的理解写了出来,术语没有那么多,而且其中很多部分理解不是很透彻,对于C初学者来说,本专栏博客还是很有意义的,因为初学者看这本书通…