Java:拦截器简介和应用示例(多个拦截器+校验token是否为空)

news2024/11/14 14:49:26

JAVA 拦截器

简介

拦截器和过滤器均可以拦截http请求,过滤器偏向于基础设施工作,拦截器偏向于业务,拦截器允许在执行Controller之前做验证预处理,在Controller执行之后对返回对象做加工处理。可以用于:权限检查、日志记录、性能监控等。Spring框架为拦截器的实现提供了强大的支持,使得我们可以在Spring MVC应用中轻松地使用拦截器。

实现原理

拦截器实现主要基于两个原理:AOP(动态代理)和责任链模式
AOP:是面向切面的编程的方式,可以在不改变源代码的基础上,进行业务扩展。
责任链模式:类似过滤器链,可以有多个拦截处理,一个处理后放行,下一个拦截才能处理。

作用

  • 日志记录
  • 流量管理
  • 接口鉴权

主要方法

拦截器的执行先后顺序主要由WebMvcConfigurer子类的注册顺序实现的。

  • WebMvcConfigurer方法:
    • addResourceHandlers:指定静态资源的位置并如何访问;
    • addInterceptors:添加拦截器,并指定需要拦截的路径;多个拦截器的执行顺序由添加顺序决定的。
  • HandlerInterceptor方法:
    • preHandle:每次http调用Controller执行执行,返回为true执行下一步请求,false请求结束,按照注册顺序执行。
    • postHandle:每次http调用Controller之后执行,对返回结果的统一渲染,按照注册顺序反执行。
    • afterCompletion:在整个请求处理完成后执行的逻辑,包括视图渲染之后,按照注册顺序反执行;
  • 执行顺序(假如先后注册了interceptor01和interceptor02)
    • interceptor01.preHandle > interceptor02.preHandle > controller的逻辑业务执行 > interceptor02.postHandle > interceptor01.postHandle > interceptor02.afterCompletion > interceptor01.afterCompletion

拦截器和过滤器的区别

  • 实现原理不同:
    • 过滤器:基于filterChain.doFilter函数回调实现,依赖servlet;对所有请求起作用;
    • 拦截器:基于SpringAOP、动态代理、责任链和放蛇实现,依赖SpringMVC;只能对action请求起作用,可以访问action的上下文;
  • 执行顺序不同:(Tomcat->Filter->Servlet->Interceptor->Controller)过滤器先执行,到servlet,Dispatcher servlet调用拦截器,分发给Controller,在Controller处理之前和处理之后执行;
  • 使用方式不同:过滤器需要依赖servlet提供的接口,拦截器需要依赖SpringMVC的HandleInterceptor接口,执行循序由WebMvcConfigurer的配置循序执行决定的。
  • 处理范围不同:
    • 过滤器:只能对request和response进行操作;
    • 拦截器:request,response,handler,modelAndView,exception执行操作
  • 用途不同:
    • 过滤器:处理必要的基础设施工作,编码处理,试图响应,请求参数处理和URL重定向;
    • 拦截器:主要和业务相关,例如身份认真和授权,接口的性能监控,跨域处理日志等;

案例(多个拦截器+校验token)

这是一个学习过程中的应用测试,仅供参考:

创建过滤器MyInterceptor01:


@Slf4j
@Component//注意当前类必须受Spring容器控制
@RequiredArgsConstructor
public class MyInterceptor01 implements HandlerInterceptor {

    private final ObjectMapper objectMapper;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse servletResponse, Object handler) throws Exception {
        // 在请求处理之前执行的逻辑
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        String method = handlerMethod.getClass().getName() + handlerMethod.getMethod().getName();
        log.info("preHandle01: {}", method);

        String token = request.getHeader("token");
        if (StringUtils.isEmpty(token)) {
            servletResponse.setContentType("text/plain;charset=UTF-8"); // 设置内容类型和编码
            try {
                BaseResponse<String> baseResponse = ResultUtils.error("用户未登录,请先登录.");
                String responseStr = objectMapper.writeValueAsString(baseResponse);
                ServletOutputStream outputStream = servletResponse.getOutputStream();
                outputStream.write(responseStr.getBytes(StandardCharsets.UTF_8)); // 写入字节数组
            } catch (IOException ex) {
                throw new RuntimeException(ex);
            }

            return false;
        }
        return true; // 返回true表示继续执行后续操作,返回false表示中断请求处理
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 在请求处理之后执行的逻辑,视图渲染之前
        log.info("postHandle01");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 在整个请求处理完成后执行的逻辑,包括视图渲染之后
        log.info("afterCompletion01");
    }
}

创建过滤器MyInterceptor02:


@Slf4j
@Component //注意当前类必须受Spring容器控制
public class MyInterceptor02 implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 在请求处理之前执行的逻辑
        log.info("preHandle02");
        return true; // 返回true表示继续执行后续操作,返回false表示中断请求处理
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 在请求处理之后执行的逻辑,视图渲染之前
        log.info("postHandle02");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 在整个请求处理完成后执行的逻辑,包括视图渲染之后
        log.info("afterCompletion02");
    }
}

注册过滤器:先添加MyInterceptor021,再添加MyInterceptor02,执行顺序由注册顺序决定;

@Configuration
public class WebInterceptorConfiguration implements WebMvcConfigurer {

    @Autowired
    private MyInterceptor01 myInterceptor01;

    @Autowired
    private MyInterceptor02 myInterceptor02;

    /**
     * 指定静态资源的位置,和如何访问这些资源
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        // 将所有 /static/** 访问都映射到 classpath:/static/ 目录下
        // 静态资源请求的映射,如静态请求为/static/**,则请求会在程序的类路径(通常是src/main/static)下的/static/目录中查找这些资源
        // registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
    }

    /**
     * addPathPatterns:需要过滤的路劲
     * excludePathPatterns:需要拦截的路劲
     * 拦截器的执行循序和配置顺序有关,先进后出
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {

        registry.addInterceptor(myInterceptor01)
                .addPathPatterns("/api/**")  // 拦截的路径
                .excludePathPatterns("/public/**");  // 排除的路径

        registry.addInterceptor(myInterceptor02)
                .addPathPatterns("/api/**")  // 拦截的路径
                .excludePathPatterns("/public/**");  // 排除的路径
    }

}

测试结果:不加token的时候请求被拦截提示未登录
在这里插入图片描述
测试结果:增加token,查看HandlerInterceptor的几个方法的执行顺序
在这里插入图片描述

参考地址:

https://www.cnblogs.com/blogtech/p/18186170
https://blog.csdn.net/qq_34207422/article/details/136619868
https://www.jb51.net/article/219535.htm

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

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

相关文章

2014年全国大学生数学建模竞赛C题生猪养殖管理(含word论文和源代码资源)

文章目录 一、部分题目二、部分论文三、部分源代码四、完整word版论文和源代码 一、部分题目 2014高教社杯全国大学生数学建模竞赛题目 C题 生猪养殖场的经营管理 某养猪场最多能养10000头猪&#xff0c;该养猪场利用自己的种猪进行繁育。养猪的一般过程是&#xff1a;母猪配…

第3关 -- Git 基础知识

任务1: 破冰活动&#xff1a;自我介绍 任务2: 实践项目&#xff1a;构建个人项目 MeiHuaYiShu

【BUG】已解决:ModuleNotFoundError: No module named ‘_ctypes‘

已解决&#xff1a;ModuleNotFoundError: No module named ‘_ctypes‘ 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&#xff0c;我是博主英杰&#xff0c;211科班出身&#xff0c;就职于医疗科技公司&#xff0c;热衷分享知识&#xff0c;武汉城…

【Langchain大语言模型开发教程】记忆

&#x1f517; LangChain for LLM Application Development - DeepLearning.AI 学习目标 1、Langchain的历史记忆 ConversationBufferMemory 2、基于窗口限制的临时记忆 ConversationBufferWindowMemory 3、基于Token数量的临时记忆 ConversationTokenBufferMemory 4、基于历史…

双笼转子感应电机建模仿真(2):任意速旋转坐标系下xy/xy数学模型及仿真模型

1.概述 2. 双笼转子三相感应电机数学模型 2.1. 定子基准下ABC/qd数学模型 2.2. 任意速旋转坐标系下xy/xy数学模型 2.3. 空间矢量数学模型 3. 双笼转子三相感应电动机仿真模型 3.1 基于任意速xy/xy坐标系数学模型(1)~(5)的仿真模型 3.2. 基于任意速xy/xy坐标系中瞬态等效电…

MATLAB图像处理分析基础(一)

一、引言 MATLAB软件得到许多数字图像处理学生、老师和科研工作者的喜爱&#xff0c;成为数字图像处理领域不可或缺的工具之一&#xff0c;其与其他软件相比有以下诸多显著优点。首先&#xff0c;MATLAB 拥有强大的内置函数库&#xff0c;涵盖了图像读取、显示、处理及分析的全…

OpenCV 遍历Mat,像素操作,使用TrackBar 调整图像的亮度和对比度 C++实现

文章目录 1.使用C遍历Mat,完成颜色反转1.1 常规遍历方式1.2 迭代器遍历方式1.3指针访问方式遍历&#xff08;最快&#xff09;1.4不同遍历方式的时间对比 2.图像像素操作&#xff0c;提高图像的亮度3.TrackBar 进度条操作3.1使用TrackBar 调整图像的亮度3.2使用TrackBar 调整图…

【JavaEE进阶】——Spring事务和事务传播机制

目录 &#x1f6a9;事务 &#x1f388;为什么需要事务? &#x1f388;事务的操作 &#x1f6a9;Spring 中事务的实现 &#x1f388;数据准备 &#x1f388;Spring 编程式事务(了解) &#x1f388;Spring 声明式事务 Transactional &#x1f36d;Transactional 详解 &…

2013年全国大学生数学建模竞赛B题碎纸片复原(含word论文和源代码资源)

文章目录 一、部分题目二、部分论文三、部分源代码四、完整word版论文和源代码&#xff08;两种获取方式&#xff09; 一、部分题目 2013高教社杯全国大学生数学建模竞赛题目 B题 碎纸片的拼接复原 破碎文件的拼接在司法物证复原、历史文献修复以及军事情报获取等领域都有着重…

基于术语词典干预的机器翻译挑战赛笔记Task2 #Datawhale AI 夏令营

上回&#xff1a; 基于术语词典干预的机器翻译挑战赛笔记Task1 跑通baseline Datawhale AI 夏令营-CSDN博客文章浏览阅读718次&#xff0c;点赞11次&#xff0c;收藏8次。基于术语词典干预的机器翻译挑战赛笔记Task1 跑通baselinehttps://blog.csdn.net/qq_23311271/article/d…

统计一个页面用到的html,css,js

<!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>统计html</title><style>* {margin: …

【人工智能】AI音乐创作兴起与AI伦理的新视角

文章目录 &#x1f34a;AI音乐创作&#xff1a;一键生成&#xff0c;打造你的专属乐章&#x1f34a;1 市面上的AI音乐应用1.1 Suno AI1.2 网易天音 &#x1f34a;2 AI音乐创作的流程原理(直接制作可跳到第3点)2.1 AI音乐流派2.2 AI音乐风格2.3 AI音乐的结构顺序2.5 选择AI音乐乐…

基于PSO算法优化PID参数的一些问题

目录 前言 Q1&#xff1a;惯性权重ω如何设置比较好&#xff1f;学习因子C1和C2如何设置&#xff1f; Q2&#xff1a;迭代速度边界设定一定能够遍历&#xff08;/覆盖&#xff09;整个PID参数二维空间范围吗&#xff1f;还是说需要与迭代次数相关&#xff1f;迭代次数越高&a…

阵列信号处理学习笔记(一)--阵列信号处理定义

阵列信号 阵列信号处理学习笔记&#xff08;一&#xff09;–阵列信号处理定义 阵列信号处理学习笔记&#xff08;二&#xff09;–空域滤波基本原理 文章目录 阵列信号前言一、阵列信号处理定义1.1 信号1.2 阵列 二、雷达数据中哪些属于空间采样总结 前言 MOOC 阵列信号处理…

Bubbliiiing 的 Retinaface rknn python推理分析

Bubbliiiing 的 Retinaface rknn python推理分析 项目说明 使用的是Bubbliiiing的深度学习教程-Pytorch 搭建自己的Retinaface人脸检测平台的模型&#xff0c;下面是项目的Bubbliiiing视频讲解地址以及源码地址和博客地址&#xff1b; 作者的项目讲解视频&#xff1a;https:…

数据结构排序合集(笔记)

目录 一.插入排序与希尔排序 二.选择排序与堆排序 三.冒泡排序和快速排序 四.归并排序 五.计数排序 一.插入排序与希尔排序 时间复杂度空间复杂度稳定性插入排序O&#xff08;N^2&#xff09;O(1)稳定希尔排序O(N^1.3)O(1)不稳定 插入排序&#xff1a; 希尔排序&#xff…

css-01-如何实现“文本过长(文本在一行排),超出部分被省略号代替”

目录 需求代码代码解释 需求 最近写一个项目&#xff0c;遇到了一个问题&#xff0c;就是希望实现下面这种文字效果&#xff1a;文字在一行排&#xff0c;超出的部分用省略号代替 代码 <!DOCTYPE html> <html lang"en"><head><meta charset…

OCC 创建点线面体

目录 一、利用封装已有算法实现 1、盒子建模算法封装 2、可视化 二、利用OCC 点线面实现 1、实现过程 2、实现一个面 3、拉伸面生成体 4、旋转面生成体 三、总结 一、利用封装已有算法实现 1、盒子建模算法封装 BRepPrimAPI_MakeBox box(2, 2, 2); 2、可视化 void VTK…

Gateway源码分析:路由Route、断言Predicate、Filter

文章目录 源码总流程图说明GateWayAutoConfigurationDispatcherHandlergetHandler()handleRequestWith()RouteToRequestUrlFilterReactiveLoadBalancerClientFilterNettyRoutingFilter 补充知识适配器模式 详细流程图 源码总流程图 在线总流程图 说明 Gateway的版本使用的是…

在线 PDF 制作者泄露用户上传的文档

两家在线 PDF 制作者泄露了数万份用户文档&#xff0c;包括护照、驾驶执照、证书以及用户上传的其他个人信息。 我们都经历过这样的情况&#xff1a;非常匆忙&#xff0c;努力快速制作 PDF 并提交表单。许多人向在线 PDF 制作者寻求帮助&#xff0c;许多人的祈祷得到了回应。 …